美文网首页
Redis 入门(三):订阅/发布、事务、脚本

Redis 入门(三):订阅/发布、事务、脚本

作者: alexlee666 | 来源:发表于2019-11-21 16:45 被阅读0次

    一、Redis 消息通信模式 -- 发布/订阅

    Publish/Subscribe 是 Redis 的消息通信模式,某些 redis client 可以去订阅某些channel,然后可以启用某些 redis client 向某些chenel发布message,然后message就会被推送给那些申请订阅的客户端,这个过程就像是预定/上门配送光明牛奶的过程。

    客户端订阅某channel
    发布推送message
    举个栗子来说明过程:
    • Step 1. 某客户端A订阅了channel1
    127.0.0.1:6379[1]> subscribe channel1 
    Reading messages... (press Ctrl-C to quit)
    1) "subscribe"
    2) "channel1"
    3) (integer) 1
    
    
    • Step 2. 新开一个客户端B,向channel1中发布message
    $ redis-cli 
    127.0.0.1:6379> auth root
    OK
    127.0.0.1:6379> publish channel1 "hello redis"
    (integer) 1
    127.0.0.1:6379> publish channel1 "hello beijing"
    (integer) 1
    
    

    观察A中可以看到有消息收到:

    127.0.0.1:6379[1]> subscribe channel1 
    Reading messages... (press Ctrl-C to quit)
    1) "subscribe"
    2) "channel1"
    3) (integer) 1
    1) "message"
    2) "channel1"
    3) "hello redis"
    1) "message"
    2) "channel1"
    3) "hello beijing"
    
    

    二、Redis 事务

    同 MySQL 等数据库类似,内存数据库 Rediscove(NoSQL)同样有事务的概念。Redis 开启一个事务后,输入多个命令,然后一起提交执行。

    • Redis 命令具有原子性;
    • Redis 事务不具有原子性:Redis 事务可以看成是多个任务组成的脚本,当某个命令执行失败时并不会影响到之前已被执行的命令(即不会回滚)。

    Redis 事务的相关命令:

    命令 描述 备注
    multi 事务开启
    exec 执行事务 执行 multi 之后 exec 之前输入的所有命令
    discard 取消事务 用在multi 之后 exec 之前,当然输入的命令也不会执行
    watch 监听一个或多个key 用在 multi 之前。比如如果client A 中 watch k1 并使用 multi 启动事务且输入命令 get k1,但是在 client A 使用 exec 执行事务之前 client B 更新了 k1 的值,那么之后client A 执行事务会报 nil,即事务被打断
    unwatch 取消监听

    下面举例说明 watch 的使用:

    • 首先,client A 中定义事务:
    127.0.0.1:6379> watch k1
    OK
    127.0.0.1:6379> multi 
    OK
    127.0.0.1:6379> get k1
    QUEUED
    127.0.0.1:6379> get k2
    QUEUED
    
    
    • 然后,client B 中修改 k1 的值:
    127.0.0.1:6379> set k1 v2
    OK
    
    
    • 最后,client A 中执行事务:
    127.0.0.1:6379> exec
    (nil)
    
    

    可以看到,client A 中的事务被打断了。


    三、Redis 脚本

    Redis 中内嵌了Lua 解释器用于解释执行 script。

    3.1 为何引入脚本?

    • 减少网络开销:Lua 脚本将多个命令请求通过脚本的形式一次性发送;
    • 原子性保证:与 Redis 事务无法保证原子性不同,脚本能够保证所有命令的原子性;
    • 可复用:客户端发送的脚本会被永久保存在 Redis 中,供后期复用。

    3.2 使用方法

    3.2.1 redis-cli 中使用

    Redis 中通常使用eval 命令来提交脚本。命令格式为:
    eval "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 k1 k2 v v2
    其中:

    • eval为命令;
    • "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 是脚本,其中{}就相当于数组
    • KEYS[1]:表示第1个参数,对应后面的k1;
    • KEYS[2]:表示第2个参数,对应后面的k2;
    • ARGV[1]:表示第1个value,对应后面的v1;
    • ARGV[2]:表示第1个value,对应后面的v2;
    • 2 是key的个数,即 numkeys;
    • KEYS 和 ARGV必须是大写字母

    因此这种对应关系类似字符串的格式化,但是 numkeys 后依次为各参数,而并非完全对应脚本中参数或者value的先后顺序,比如:

    127.0.0.1:6379> eval "redis.call('set',KEYS[1],ARGV[1]);redis.call('set',KEYS[2],ARGV[2]);return 'OK';" 2 k2 k3 v2 v3
    "OK"
    127.0.0.1:6379> get k2
    "v2"
    127.0.0.1:6379> get k3
    "v3"
    
    

    可以看到 2 后面依次跟着第1、2个参数。

    3.3 其他命令

    • script load
      该命令用于将脚本(不包括后面的numkeys、参数名、参数值)加载到内存中,但是不执行。
      命令格式:script load "脚本内容" 参数... 参数值...
    127.0.0.1:6379> script load "redis.call('set',KEYS[1],ARGV[1]);redis.call('set',KEYS[2],ARGV[2]);return 'OK';"
    "046ab9327f94abbe991894063370234cb4add8f7"
    
    

    其中"046ab9327f94abbe991894063370234cb4add8f7"就是校验码。

    • evalsha
      该命令和eval用法类似,区别在于:
      • 先要load 脚本到内存中;
      • 使用脚本的sha校验码来替代了eval中具体的脚本内容。
    127.0.0.1:6379> evalsha 046ab9327f94abbe991894063370234cb4add8f7 2 k2 k3 v2 v3
    "OK"
    
    
    • script exists
      该命令用于判断内存中是否存在指定的脚本(使用sha校验码),命令格式为:
      script exists 脚本校验码
    127.0.0.1:6379> script exists 046ab9327f94abbe991894063370234cb4add8f7
    1) (integer) 1
    
    
    • script flush
      该命令用于清除内存中的所有脚本,命令格式为:
      script flush
    127.0.0.1:6379> script flush
    OK
    127.0.0.1:6379> script exists 046ab9327f94abbe991894063370234cb4add8f7
    1) (integer) 0
    
    

    可以看到
    046ab9327f94abbe991894063370234cb4add8f7 这个脚本缓存已经被清除了。

    • script kill
      该命令用于kill 掉正在运行的脚本,命令格式为:
      script kill
    127.0.0.1:6379> script kill
    (error) NOTBUSY No scripts in execution right now.
    
    
    3.2.2 终端 terminal 中使用

    命令格式:redis-cli --eval lua_file 参数... 参数值...

    redis-cli --eval lua_file key1 key2 , arg1 arg2 arg3
    # 如果redis 设置了密码,则需要在redis-cli 后面添加参数 -a root,其中root是设置的密码
    
    

    笔者水平有限,如有错误,敬请指正!

    相关文章

      网友评论

          本文标题:Redis 入门(三):订阅/发布、事务、脚本

          本文链接:https://www.haomeiwen.com/subject/pguzictx.html