随处可见的学习笔记-Redis入门

他山之石,可以攻玉

题图--引自网络,侵删,请联系我

引言

前两天写了个NodeJs爬虫,很简单那种。就是爬取某个网站的首页解析所有的Url然后再爬取内页。这里就带来了一个问题。众所周知,Js是单线程异步的,并以此为卖点。可是在这个场景就有一个很明显的问题。
比如首页有30个Url它会一次性解析30个Url然后同时去请求,失败率不可谓不高。类似的场景我曾经使用过用数组来模拟栈用于控制并发,然实在不能说很优雅,各种判断,轮训,时间长了再去看不合心意,于是便想到Redis。
这是一个NoSql数据库,经常用来做缓存,因为是存在内存里的效率很高,当然也支持存进硬盘做持久化,我看上它是有一个事务,能否用这个事务来做并发控制呢?就是我来学习它的初衷,毕竟既能解决缓存又可以做并发控制岂不美哉?

初探

  1. 安装
    Redis的安装非常简单,以Linux为例:
     前往首页选择最新稳定版下载(官网下载地址:https://redis.io/download)
          $ wget http://download.redis.io/releases/redis-4.0.9.tar.gz
          $ tar xzf redis-4.0.9.tar.gz
          $ cd redis-4.0.9
          $ make
      好了装完了  
    
  2. 使用
       $ src/redis-server //开启本地服务器
       $ src/redis-cli //开启本地客户端 
       redis> set foo bar
       OK
       redis> get foo
       "bar"
       以上是官网示例
       默认端口:6379 可以通过 --port 来设置
       cli 可以通过 -h 指定host地址,-p来指定端口
       然后为了方便我们可以。
       ln -s  /home/pi/redis-4.0.9/src/redis-server  /usr/bin/redis-server
       ln -s  /home/pi/redis-4.0.9/src/redis-cli /usr/bin/redis-cli
   //注意一点,默认情况下Redis只能本地访问,设置密码以后才能远端访问。
  1. 基本概念
    数据结构
    Redis有五种数据结构:String,Hash,List,Set和zset。
    **String(字符串) **
    简单的键值对:
    SET name “Redis”
    GET name
    //输出 Redis
    

** Hash(哈希)**
是个键值集合,存数据的方式,当作Js的对象来理解似乎没有太大问题。
这个估计最常用

HMSET obj name “Redis” state “Studying” 
HGGET obj name
//输出Redis
HGET obj
//输出 Redis
//Studying

List(列表)
字符串列表,按照输入顺序排序,类比Js的话,就是使用push和unpush的数组。
我觉得翻译成队列更合适。

 lpush runoob redis
 lpush runoob mongodb
 lpush runoob rabitmq
 lrange runoob 0 10
//输出
    1) "rabitmq"
     2) "mongodb"
     3) "redis"

Set(集合)
学术性的说法叫:String的无序集合。
在我看来..相当于先创建一个空数组,然后一个值一个值往里加,与上面的区别似乎是这是个哈系表?。

sadd runoob 
sadd runoob redis
sadd runoob mongodb
sadd runoob rabitmq
sadd runoob rabitmq
smembers runoob
 //输出
 1) "redis"
 2) "rabitmq"
 3) "mongodb"

zset(有序集合)

自带排序的集合..
学术性的说法:不允许重复的,每一个元素关联一个double类型数的String类型元素集合。每个元素虽然不能重复,但是被用来排序的double值是可以重复的。
通俗一点就是,下标只用来排序且允许重复,每个成员都是字符串且唯一的数组....

     zadd runoob 0 redis
     zadd runoob 0 mongodb
     zadd runoob 0 rabitmq
     zadd runoob 0 rabitmq
     ZRANGEBYSCORE runoob 0 1000
     1) "mongodb"
     2) "rabitmq"
     3) "redis"
  1. 基本操作
    上面每一种都介绍一下的话,篇幅太长,我重点看看Hash的..其它估计也都差不多,举一反三。只要会增删改查感觉基本的应用就没问题了。
  增:HMSET key name1 value1 name2 value2 ....
  删:HDEL key [name value] //允许删除整个key 或者只删除key里面的某一个值
  改:HMSET key name1 value1 name2 value2 .... //直接覆盖,和Js的对象一样..
  查:HMGET key name //获取key下某个字段的值
      HGETALL key   //获取某key所有的字段和值

一些花样

HEXISTS key name  //某Key 对应字段是否存在
HSETNX key field value //安全添加只有字段不存在的时候才会添加
HKEYS key //获取所有的关键字
HVALS key //获取所有的值

5.事务
恩,到重点了,我原本是想用这个做并发控制来着。只看描述似乎是没问题的。
而且事务似乎有Watch这个方法..检测某值如果改变则取消...
emmm..高并发的抢购活动似乎很有用,问题是,我可能需要一个,改变值才去执行的方法。
Redis似乎也有发布订阅....emmmm,太繁琐了..我可能不太需要一个观察者..
实际去阅读文档发现,这个事务执行的是Redis命令...我想想...

读取所有Url
取一部分用事务存入Reds。
再一条一条取出来下载。
下完了再执行这个步骤..
emmmm...我为什么不新建一个数组?

好吧,言归正传。
所谓事务
Redis 事务可以一次执行多个命令, 并且带有以下两个重要的保证:

  • 批量操作在发送 EXEC 命令前被放入队列缓存。
  • 收到 EXEC 命令后进入事务执行,事务中任意命令执行失败,其余的命令依然被执行。
  • 在事务执行过程,其他客户端提交的命令请求不会插入到事务执行命令序列中。
  • 一个事务从开始到执行会经历以下三个阶段:

三个阶段:
1. 开始事务。
2. 命令入队。
3. 执行事务。
注意点:
Redis的命令执行是原子性的,即不成功就失败,失败会回滚状态,不存在中间态。颇有“无胜利,毋宁死”的感觉。
但是事务不一样,虽然Redis的命令是原子性的,但是Redis的事务不是,也就是说,如果一组事务有几个失败了,成功的依旧不会回滚。
例子:

redis 127.0.0.1:6379> MULTI
OK

redis 127.0.0.1:6379> SET book-name "Mastering C++ in 21 days"
QUEUED

redis 127.0.0.1:6379> GET book-name
QUEUED

redis 127.0.0.1:6379> SADD tag "C++" "Programming" "Mastering Series"
QUEUED

redis 127.0.0.1:6379> SMEMBERS tag
QUEUED

redis 127.0.0.1:6379> EXEC
1) OK
2) "Mastering C++ in 21 days"
3) (integer) 3
4) 1) "Mastering Series"
   2) "C++"
   3) "Programming"
  1. 其它
    除了上面这些,Redis还有发布订阅,脚本,等其它知识点,只是暂时似乎用不上,所以,在此略过不表。

在Node.js中使用Redis

Node.js有一个Redis库,直接

npm install redis;
node
var redis = require('redis')
var client = redis.createClient(port, host); 

这里就能拿到一个可以执行Redis的对象。
用法示例:

//原命令 hmset key name1 value1 name2 value2...
//在Js中
var mainkey = key;
vae setOBj={
    name1:value1,
    name2:value2,
    ...
}
client.hmset(mainKey,setObj,(err,res)=>{
        if(err){
          console.log(err);
         return;
        }
        console.log(res);//正常这里会返回OK
        client.quit(); //单次操作建议退出,不退出超时也会断开。
    });

//原命令 hgetall key
var mainid = key;
client.HGETALL(mainid,(err,res)=>{
         if(err){
             console.log(err);
             return;
         }
        result=res;//这里返回的是对象。
        client.quit();
     
});

值得一提的是,hmset也好,HMSET也罢,它都认识..很方便。
需要注意的是,这里无论写入还是读取都是异步的,写入还好,如果是读取,恐怕需要注意使用async,await,和Promise来做同步操作。
这里我只是举了两个刚用到的列子,其它还有很多,github上写的很详细注意返回数据的时机就可以了。

结语

本以为利用Redis的事务可以做爬虫的并发控制,最后发现,并不能,如果它能在事务中执行下载的话,倒是可以做图片下载的并发控制..
还有待研究,这篇文章作为完整的入门来说并不合格,我仅仅只是发现一个问题,然后去解决,记录下来了解决过程罢了。
Node.js的Redis库暂时没看见中文文档,示例中有一些用的到的地方,看的有点费劲,程序员学好英语还是非常必要的。
关于Node.js中使用Redis等待返回,官网有个示例,不过,我是之后才去看到,所以,我用的自己的方法,但是,这个方法很蠢,一个请求创建了两个Promis,还有待优化。
简单介绍下:在Api中使用Async 创建一个Promis,await,调用一个带Async的函数,函数中掉用Client的方法,这里再来一个Promise,await。
去掉Api中的Async Promise await的话,内层掉用Client的函数会直接返回一个Promise即使没有读到return,推测是Client函数中的方法做的,经过一遍一遍的测试,最后变成了如上所述的结构。
//2018/5/30
修正这一段描述,今天看ES6的入门,这里的Promise是async返回的,猛然想到,如果去掉async是没有promise返回的,当时忽略了这一点。

做完后发现github上的示例有一个推荐写法....emmmmmm...
查文档很重要..好..那么就这样。

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

推荐阅读更多精彩内容