Nodejs学习笔记(八)--- Redis的交互

前言

1、非关系型数据库和关系型数据库区别,优势比较?

https://www.zhihu.com/question/24225007
http://blog.csdn.net/robinjwong/article/details/18502195

3、mysql和redis的一些区别

mysql和redis的一些区别。我们知道,mysql是持久化存储,存放在磁盘里面,检索的话,会涉及到一定的IO,为了解决这个瓶颈,于是出现了缓存,比如现在用的最多的 memcached(简称mc)。首先,用户访问mc,如果未命中,就去访问mysql,之后像内存和硬盘一样,把数据复制到mc一部分。
redis和mc都是缓存,并且都是驻留在内存中运行的,这大大提升了高数据量web访问的访问速度。然而mc只是提供了简单的数据结构,比如 string存储;redis却提供了大量的数据结构,比如string、list、set、hashset、sorted set这些,这使得用户方便了好多,毕竟封装了一层实用的功能,同时实现了同样的效果,当然用redis而慢慢舍弃mc。
内存和硬盘的关系,硬盘放置主体数据用于持久化存储,而内存则是当前运行的那部分数据,CPU访问内存而不是磁盘,这大大提升了运行的速度,当然这是基于程序的局部化访问原理。
推理到redis+mysql,它是内存+磁盘关系的一个映射,mysql放在磁盘,redis放在内存,这样的话,web应用每次只访问redis,如果没有找到的数据,才去访问Mysql。
然而redis+mysql和内存+磁盘的用法最好是不同的。
前者是内存数据库,数据保存在内存中,当然速度快。
后者是关系型数据库,功能强大,数据访问也就慢。
像memcache,MongoDB,Redis,都属于No sql系列。
不是一个类型的东西,应用场景也不太一样,还是要看你的需求来决定。
一般来说,写入数据是直接到mysql,读取类的是redis。 这样就说 mysql->redis的同步用的比较多。 mysql作为数据持久化和管理比redis好太多,redis大多只用来做 数据读取缓存、队列、锁、等等的使用。 持久化的话也提供了rdb、aof 保证数据的实时不丢失。 redis和mysql要根据具体业务场景去选型
mysql:数据放在磁盘
redis:数据放在内存 redis适合放一些频繁使用,比较热的数据,因为是放在内存中,读写速度都非常快,一般会应用在下面一些场景
排行榜
计数器
消息队列推送

简介和安装

redis简介:

开源高性能key-value存储;采用内存中(in-memory)数据集的方式,也可以采用磁盘存储方式(前者性能高,但数据可能丢失,后者正好相反)
支持字符串(strings)、哈希(hashes)、列表(lists)、集合(sets)和 有序集合(sorted sets)等;支持对复杂数据结构的高速操作。
特性多,支持主从同步、pub/sub等
支持多种客户端(http://redis.io/clients

安装(Windows平台):

Redis下载地址: https://github.com/dmajkic/redis/downloads
node.js客户端:node_redis https://github.com/mranney/node_redis/
redis-2.4.5-win32-win64.zip

redis运行

解压到后运行"64bit"文件夹下的redis-server.exe

image.png

报错:


image.png

提示也比较明显,没有明确的配置文件,使用的是默认配置,请使用‘redis-server /path/to/redis.conf’指定明确的配置文件

redis-server redis.conf
image.png
node_redis安装
npm install redis
或者
npm install hiredis redis

这里采用 npm install hiredis redis 安装
  注:两种都可用,区别在于性能,hiredis是非阻塞的,而且速度更快;如果安装了hiredis,node_redis则会默认以它为解析器,没安装就会用纯javascript解释器.

报错:

image.png
这个报错先记下!

文件是生成成功的


image.png

redis.createClient()连接到redis服务器

本地redis直接连接服务方式:

app_createClient.js
image.png
//app_createClient.js
var redis = require("redis"),
    client = redis.createClient();

client.on("ready",function(err){
        if(err){
            console.log("err : "+err);
        }else{
            console.log("redis start ");
        }
})  

redis start 服务启动成功

redis.createClient():返回的是一个RedisClient的对象,大家可以输出来看一下此对象的具体信息。
ready:Redis的Connection事件之一,当与redis服务器连接成功后会触发这个事件,此时表示已经准备好接收命令,当这个事件触发之前client命令会存在队列中,当一切准备就绪后按顺序调用

具体的配置链接:

app_createClient_2.js
image.png
//app_createClient_2.js
var redis = require("redis"),
    RDS_PORT = 6379, //端口号
    RDS_HOST = '127.0.0.1', //服务器IP
    RDS_OPTS = {},  //设置项
    client = redis.createClient(RDS_PORT,RDS_HOST,RDS_OPTS);

client.on("ready",function(err){
        if(err){
            console.log("err : "+err);
        }else{
            console.log("redis start 2");
        }
}); 

redis.createClient(RDS_PORT,RDS_HOST,RDS_OPTS);
redis的默认端口:6379

认证 client.auth(password, callback)

因为redis服务器默认不需要密码,不过这不太安全,设置一下密码
打开redis.conf文件,找到requirepass,取消注释,设置密码为:tiany

image.png
image.png
image.png
image.png

连接到有密码的redis服务器
方式一:通过设置redis.createClient()的第三个参数,也就是设置项来完成

image.png
//app_createClient_3.js
var redis = require("redis"),
    RDS_PORT = 6379, //端口号
    RDS_HOST = '127.0.0.1', //服务器IP
    RDS_PWD = 'tiany',
    RDS_OPTS = {auth_pass:RDS_PWD},  //设置项 密码
    client = redis.createClient(RDS_PORT,RDS_HOST,RDS_OPTS);

client.on("ready",function(err){
        if(err){
            console.log("err : "+err);
        }else{
            console.log("redis start 2");
        }
}); 

上图可以连接成功,通过设置连接设置项中的auth_pass来通过认证!
auth_pass:默认值为null,默认情况下客户端将不通过auth命令连接,如果设置了此项,客户端将调用auth命令连接

方式二:通过client.auth(password, callback)

image.png
//app_createClient_4.js
var redis = require("redis"),
    RDS_PORT = 6379, //端口号
    RDS_HOST = '127.0.0.1', //服务器IP
    RDS_PWD = 'tiany',
    RDS_OPTS = {},  //设置项 密码
    client = redis.createClient(RDS_PORT,RDS_HOST,RDS_OPTS);

client.auth(RDS_PWD,function function_name () {
    // body...
    console.log("auth 通过 ");
})  

client.on("ready",function(err){
        if(err){
            console.log("err : "+err);
        }else{
            console.log("redis start 4");
        }
}); 

单值set和get

image.png
//app_client_set_get
var redis = require("redis"),
    RDS_PORT = 6379, //端口号
    RDS_HOST = '127.0.0.1', //服务器IP
    RDS_PWD = 'tiany',
    RDS_OPTS = {},  //设置项 密码
    client = redis.createClient(RDS_PORT,RDS_HOST,RDS_OPTS);

client.auth(RDS_PWD,function function_name () {
    // body...
    console.log("auth 通过 ");
});

client.on("connect",function(){
    client.set("author","Tiany",redis.print);
    client.get("author",redis.print);
    console.log("connect");
}); 

client.on("ready",function(err){
        if(err){
            console.log("err : "+err);
        }else{
            console.log("redis start 4");
        }
}); 

API:
  client.set(key,value,[callback]):设置单个key和value,回调函数可选
  client.get(key,[callback]):得到key得到value,回调函数可选(虽然可选,但不写回调函数获取又有什么意义呢_!)
  connect:Redis的Connection事件之一,在不设置client.options.no_ready_check的情况下,客户端触发connect同时它会发出ready,如果设置了client.options.no_ready_check,当这个stream被连接时会触发connect, 这时候就可以自由尝试发命令.
  redis.print:简便的回调函数,测试时显示返回值(从示例的输出结果中可以看出)
其它补充说明:
  client.options.no_ready_check:默认值为false,当连接到一台redis服务器时,服务器也许正在从磁盘中加载数据库,当正在加载阶段,redis服务器不会响应任何命令,node_redis会发送一个“准备确认”的INFO命令,INFO命令得到响应表示此时服务器可以提供服务,这时node_redis会触发"ready"事件,如果该设置项设置为true,则不会有这种检查
  client.set([key,value],callback):与client.set(key,value,[callback]);效果一致(可以自行对上面示例源码进行修改进行测试),必须要有回调函数

多值get和set

image.png
//app_client_hash
var redis = require("redis"),
    RDS_PORT = 6379, //端口号
    RDS_HOST = '127.0.0.1', //服务器IP
    RDS_PWD = 'tiany',
    RDS_OPTS = {},  //设置项 密码
    client = redis.createClient(RDS_PORT,RDS_HOST,RDS_OPTS);

client.auth(RDS_PWD,function function_name () {
    // body...
    console.log("auth 通过 ");
});

client.on("connect",function(){
    client.hmset('short', {'js':'javascript','C#':'C Sharp'}, redis.print);
    client.hmset('short', 'SQL','Structured Query Language','HTML','HyperText Mark-up Language', redis.print);

    client.hgetall("short",function(err,res){
        if(err){
            console.log("err :"+err);
            return;
        }
        console.dir(res);

    });
}); 

client.on("ready",function(err){
        if(err){
            console.log("err : "+err);
        }else{
            console.log("redis start 4");
        }
}); 

API:
  client.hmset(hash, obj, [callback]):赋值操作,第一个参数是hash名称;第二个参数是object对象,其中key1:value1。。,keyn:valuen形式;第三个参数是可选回调函数
  client.hmset(hash, key1, val1, ... keyn, valn, [callback]):与上面做用一致,第2个参数到可选回调函数之前的参数都是key1, val1, ... keyn, valn形式;
  client.hgetall(hash, [callback]):获取值操作,返回一个对象

  其它补充说明:
  console.dir():用于显示一个对象所有的属性和方法

打包执行多个命令[事务]

image.png
//app_client_multi
var redis = require("redis"),
    RDS_PORT = 6379, //端口号
    RDS_HOST = '127.0.0.1', //服务器IP
    RDS_PWD = 'tiany',
    RDS_OPTS = {},  //设置项 密码
    client = redis.createClient(RDS_PORT,RDS_HOST,RDS_OPTS);

client.auth(RDS_PWD,function function_name () {
    // body...
    console.log("auth 通过 ");
});


client.on("connect",function(){
    var key = "lessions";
    client.sadd(key,"java");
    client.sadd(key,"ndoejs");
    client.sadd(key,"js");
    client.sadd(key,"oracle");

    client.multi()
    .sismember(key,"java")
    .smembers(key)
    .exec(function (err,replies){
        console.log("Multi length :"+ replies.length);
        replies.forEach(function  (reply,index) {
             console.log("Reply " + index + ": " + reply.toString());
             // body...
        });
        client.quit();
    });
}); 

client.on("ready",function(err){
        if(err){
            console.log("err : "+err);
        }else{
            console.log("redis start 4");
        }
}); 

API:
  client.multi([commands]):这个标记一个事务的开始,由Multi.exec原子性的执行;github上描述是可以理解为打包,把要执行的命令存放在队列中,redis服务器会原子性的执行所有命令,node_redis接口返回一个Multi对象
  Multi.exec( callback ):执行事务内所有命令;github上描述是client.multi()返回一个Multi对象,它包含了所有命令,直到Multi.exec()被调用;
  Multi.exec( callback )回调函数参数err:返回null或者Array,出错则返回对应命令序列链中发生错误的错误信息,这个数组中最后一个元素是源自exec本身的一个EXECABORT类型的错误
  Multi.exec( callback )回调函数参数results:返回null或者Array,返回命令链中每个命令的返回信息
  client.sadd(key,value1,...valuen,[callback]):集合操作,向集合key中添加N个元素,已存在元素的将忽略;redis2.4版本前只能添加一个值
  sismember(key,value,[callback]):元素value是否存在于集合key中,存在返回1,不存在返回0
  smembers(key,[callback]):返回集合 key 中的所有成员,不存在的集合key也不会报错,而是当作空集返回
  client.quit():与之对应的还有一个client.end()方法,相对比较暴力;client.quit方法会接收到所有响应后发送quit命令,而client.end则是直接关闭;都是触发end事件

end:redis已建立的连接被关闭时触发

client.on('end',function(err){
    console.log('end');
});

其它

http://redis.readthedocs.org/en/latest/index.html
https://github.com/mranney/node_redis/

学习实践参考:
http://www.cnblogs.com/zhongweiv/p/node_redis.html

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350

推荐阅读更多精彩内容

  • NOSQL类型简介键值对:会使用到一个哈希表,表中有一个特定的键和一个指针指向特定的数据,如redis,volde...
    MicoCube阅读 3,961评论 2 27
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,633评论 18 139
  • https://nodejs.org/api/documentation.html 工具模块 Assert 测试 ...
    KeKeMars阅读 6,313评论 0 6
  • 1.1 资料 ,最好的入门小册子,可以先于一切文档之前看,免费。 作者Antirez的博客,Antirez维护的R...
    JefferyLcm阅读 17,036评论 1 51
  • 给Lulu演讲的建议 Frank: 演讲里没有足够多的停顿,没有给观众思考的时间 故事与最后结尾的逻辑...
    持续精进的Lulu阅读 192评论 0 0