redis的高速存取性能让人印象深刻,虽然是分布式存储,但相比本地内存,性能毫不逊色。

之所以能做到这点,是由于redis的“单线程,多路复用IO”,同一时刻只有一个操作在进行。

而且多次建立从redis存取数据的链接,操作完成后关闭,性能表现超出SQL一大截。(虽然这样的设计某种程度上算是对redis性能的浪费。。。)

redis的nodejs版本API支持其几乎所有命令,现对项目中涉及的记录如下。

根据redis中的数据类型区分:

0、建立node-redis的client端连接

 // redis 链接
var redis = require('redis');
var client = redis.createClient('6379', '127.0.0.1'); // redis 链接错误
client.on("error", function(error) {
console.log(error);
});
// redis 验证 (reids.conf未开启验证,此项可不需要)
// client.auth("foobared");

在我使用的Nodejs V 0.10中,已附带了node-reids API,不需要再npm安装了。

1、set的存取

 client.set('key001', 'AAA', function (err, response) {
if (err) {
console.log("err:", err);
} else {
console.log(response);
client.get('key001', function (err, res) {
if (err) {
console.log("err:", err);
} else {
console.log(res);
client.end();
}
});
}
});

运行结果为:

> node redistest.js
OK
AAA

2、hash存取

hash set的设值和抽取数据都有单个key和多个key两种方式:

※ 设定单个key的值,在取值时获取特定filed下指定key的值:

 client.hset('filed002', 'key001', 'wherethersisadoor', function (err, res) {
if (err) {
console.log(err);
} else {
console.log('res:', res);
client.hget('filed002', 'key001', function (err, getRslt) {
if (err) {
console.log(err);
} else {
console.log('getRslt:', getRslt);
client.end();
}
});
}
});

运行结果如下:

> node redistest.js
res: 1
getRslt: wherethersisadoor

注意:当hget方法在指定field下找不到指定的key时,会传给回调函数null,而非空字符或undefined。

※ 设定多个key的值,取值时获取指定field下指定单个或多个key的值

 var qe = {a: 2, b:3, c:4};
client.hmset('field003', qe, function(err, response) {
console.log("err:", err);
console.log("response:", response);
client.hmget('field003', ['a', 'c'], function (err, res) {
console.log(err);
console.log(res);
client.end();
});
});

运行结果如下:

> node redistest.js
err: null
response: OK
null
[ '2', '4' ]

hmset方法的设定值可以是JSON格式的数据,但是redis中key的值是以字符串形式存储的,如果JSON数据层数超过一层,会出现值是'[object Object]'的情况。

hmget方法的返回值是个数组,其中元素的顺序对应于参数的key数组中的顺序,如果参数数组中有在field内不存在的key,返回结果数组的对应位置会是null,也即无论是否能取到值,结果数组中的元素位置始终与参数的key数组中元素位置一一对应。

获取hash中所有key的方法是client.keys(fieldname, callback); 需要注意的是如果hash中key的数目很多,这个方法的可能耗费很长时间。

3、sorted sets 有序集合

有序集合是redis中一种有意思的数据结构,集合中元素是有序的,排序的依据是元素对应的score,在向有序集合中加入元素时,需要同时设定数据的值和对应的score,数据在有序集合中的存储位置依据score确定。

score的类型被限定为浮点数,当两个不同的元素具有相同的score时,两者的位置按照字符串大小升序排列。

有序集合中每个元素都被限制为唯一的,向一个有序集合中设定两个值相同而score不同的元素,只会更新已经被设定元素的score,这点需要注意。

 var vals = [];
for (var score = 0; score < 4; score++) {
for (var val = 10; val < 14; val++) {
vals.push(score);
vals.push(val);
}
} client.zadd('004', vals, function(err, res) {
console.log(err);
console.log(res);
client.zrange('004', 0, -1, function(err, resp) {
console.log(err);
console.log('range result:', resp);
client.zcount('004', -Infinity, Infinity, function(err, respo) {
console.log(err);
console.log("len:", respo);
client.end();
});
});
});

执行结果如下:

> node redistest.js
null
4
null
range result: [ '10', '11', '12', '13' ]
null
len: 4

zadd方法接收数组作为设定值的参数,数组中数据顺序为[score1, key1, score2, key2,...]的形式。

参数数组中原本会有score不同的4组值,但是由于score对应的元素值相同,最终集合中仅存在一组值。

zrange方法获取指定下标范围的内的所有key值,包括起始位置和终止位置。

zcount方法获取指定集合指定范围内的元素个数,设定为-Infinity, Infinity时,可以获取数组长度。

redis中的游标设计思想类似SQL中的游标,node-redis API中使用scan方法作为游标,对应不同的数据结构,有hscan和zscan等方法。

 client.zscan('004', 0, 'COUNT', '1', function(err, res) {
console.log(err);
console.log(res);
console.log(res[1].length);
client.end();
});

执行结果如下:

> node redistest.js
null
[ '0', [ '10', '3', '11', '3', '12', '3', '13', '3' ] ]
8

返回结果是一个数组。数组第一个元素是游标的返回值,标明当前读取位置,用这个值作为参数再次调用scan方法,将会从前次终止的位置继续读取集合。

数组第二个元素是游标读取的内容,数组内元素格式是[key1, score1, key2, score2...]。'COUNT'参数的作用是限定scan方法的读取数量,此处为起作用,原因未明,需继续调查。

4、lists 列表

列表中的元素顺序就是插入顺序,元素没有唯一性限制。

 client.del("003", function(err, respo) {
client.rpush("003", [1, 2, 3, 4, 5], function(err, res) {
console.log(err);
console.log(res);
client.lrange('003', 0, -1, function(err, resp) {
console.log(err);
console.log("resp:", resp);
client.end();
});
});
});

执行结果如下:

> node redistest.js
null
5
null
resp: [ '1', '2', '3', '4', '5' ]

使用sort方法可得到排序后的结果。

list的push方法有左右两个版本,lpush和rpush,分别表示从list的头部和尾部插入元素。

总结,对于redis中的大规模数据,单一数据类型并不经常可以很好的实现业务需求,可以通过不同数据类型的组合,在快速存储数据的基础上,快速的索引匹配数据查找。在实际使用中,用到的是将大量数据存储在hash集合中,而hash集合的key存储在有序集合中,提取key中的数字部分作为score,在有序集合中取出特定位置的key,再根据key去hash集合中取值。

接触redis的时间不长,这是个很高效的存储工具,与SQL完全不同,在扩展程序功能方面有很多可以尝试的地方,以后在设计程序时,可以将redis因素加入考虑。

2016/04/10 补充

使用async并发写入redis时,由于没有写入锁定,获取key的当前状态和写入数据之间的时间内,redis数据也可能发生变化,造成脏数据写入,这点必须注意。

目前阶段,解决这个问题的方案是估计并发程序的大致执行时间,如果单次并发执行时间较长,则不同并发之间在读-写间隔内操作同一个key的几率降低,可以不考虑脏数据问题(暂时解决方案);而如果单次并发时间较短,则设置并发线程数量为1,限定串行执行。

现在接触到的新技术,不同于经年完善的传统方案,有些设定没有考虑应用于新的应用领域,有些则是技术革新带来的新型规范,虽然开发过程中都可以算作踩坑,但并不是所有出现问题的地方都一无是处,要注意平时固执于“经典”观点,不愿接受更新的惰性。

node-redis使用记录的更多相关文章

  1. redis 学习记录

    http://www.yiibai.com/redis/redis_quick_guide.html Redis 是一款依据BSD开源协议发行的高性能Key-Value存储系统(cache and s ...

  2. CentOS 6.5下Redis安装记录

    Redis简介: Redis是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并提供多种语言的API.从2010年3月15日起,Redis的开发工 ...

  3. [Node.js] Node + Redis 实现分布式Session方案

    原文地址: http://www.moye.me/?p=565 Session是什么? Session 是面向连接的状态信息,是对 Http 无状态协议的补充. Session 怎么工作? Sessi ...

  4. Redis使用记录-相关资料汇总

    1 redis在centos上的安装 http://www.cnblogs.com/hanyinglong/p/5036558.html 2 redis在windows上的可视化GUI工具 https ...

  5. Node + Redis 实现分布式Session方案(转载)

    Session是什么? Session 是面向连接的状态信息,是对 Http 无状态协议的补充. Session 怎么工作? Session 数据保留在服务端,而为了标识具体 Session 信息指向 ...

  6. Node Redis 入门

    基础准备:Node.Js .npm或cnpm.redis安装 1.建立一个项目文件夹,这里命名 wxfc ,打开命令行输入 npm install redis . 因为没有创建package.json ...

  7. Node Redis 小试

    Redis 是一个高性能的 key-value 数据库,为了保证效率,数据都是缓存在内存中,在执行频繁而又复杂的数据库查询条件时,可以使用 Redis 缓存一份查询结果,以提升应用性能. 背景 如果一 ...

  8. redis 问题记录

    摘抄来自:https://zhuoroger.github.io/ 1.slowlog和排队延时 slowlog是排查性能问题关键监控指标.它是记录Redis queries运行时间超时特定阀值的系统 ...

  9. Redis学习记录(三)

    1.Redis集群的搭建 1.1redis-cluster架构图 架构细节: (1)所有的redis节点批次互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽. (2)节点的fail ...

  10. Redis学习记录(一)

    在学习Redis之前,要知道什么是NoSQL? 1.NoSQL 1.1. 什么是NoSQL NoSQL(NoSQL = Not Only SQL),表示“不仅仅是SQL”,泛指非关系型数据库. 1.2 ...

随机推荐

  1. oracle数据库恢复归档脚本

    cat restorearch1.sh rman target / << EOFRUN {SET ARCHIVELOG DESTINATION TO '/archlog1/db2_arch ...

  2. Leetcode225 用栈实现队列

    大众思路: 用两个栈实现,记为s1,s2 1.元素入栈时,加入s1 2.元素出栈时,对s2进行判断,如果s2为空,则将全部s1元素弹出并压入到s2,然后从s2栈顶弹出一个元素:如果s2不为空,则直接从 ...

  3. 使用canvas输出base64_url

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  4. Python 学习笔记(十)Python集合(三)

    集合运算 元素与集合的关系 元素与集合的关系 ,就是判断某个元素是否是集合的一员."a" in aset >>> s =set([1,2,3,4]) >&g ...

  5. 【微信开发】微信开发模式 api 接口文档简介

    微信公众平台分为订阅号和服务号,服务号提供9大接口,需要通过微信认证后才能使用这些接口.认证费用300元.下面是接口的大致介绍: 1. 语音识别:通过语音识别接口,用户发送的语音,将会同时给出语音识别 ...

  6. Java项目排查cpu负载高

    背景 我负责的其中一个项目在空负载的情况下,CPU占用率依然保持着100%左右,线上.测试.开发的服务都一样:是什么导致的呢?在开发环境我查看了请求流量,这个流量可以忽略但CPU占用率一直在60%-1 ...

  7. Linux -- 用户篇

    Linux -- 用户与用户组 1.Linux 系统中有三种角色:所有者(用户),用户组与其他人,一张图可以说明用户与用户组的关系. 如图,某公司相当于一个用户组,该用户组下有A,B两个用户,用户拥有 ...

  8. 竞赛题解 - NOIP2018 赛道修建

    \(\mathcal {NOIP2018}\) 赛道修建 - 竞赛题解 额--考试的时候大概猜到正解,但是时间不够了,不敢写,就写了骗分QwQ 现在把坑填好了~ 题目 (Copy from 洛谷) 题 ...

  9. 如何理解Hibernate的持久化?

    学习Hibernate,必须要理解什么是持久化?结合了一下网上的各位大佬的观点和自己的理解: 持久化概念 持久化是将程序数据在持久状态和瞬时状态间转换的机制.通俗的讲,就是瞬时数据(比如内存中的数据, ...

  10. 理解Redux以及如何在项目中的使用

    今天我们来聊聊Redux,这篇文章是一个进阶的文章,建议大家先对redux的基础有一定的了解,在这里给大家推荐一下阮一峰老师的文章: http://www.ruanyifeng.com/blog/20 ...