Redis发布与订阅&&事务&&lua 脚本

Redis 发布与订阅

  1. Redis 发布订阅 (pub/sub) 是一种消息通信模式:发送者 (pub) 发送消息,订阅者 (sub) 接收消息。

  2. Redis 客户端可以订阅任意数量的频道

  3. 频道 channel1 , 以及订阅这个频道的三个客户端 —— client2 、 client5 和 client1 之间的关系:
    在这里插入图片描述

  4. 当有新消息通过 PUBLISH 命令发送给频道 channel1 时, 这个消息就会被发送给订阅它的三个客户端:
    在这里插入图片描述

  5. 第一个 redis-cli 客户端

    
    redis 127.0.0.1:6379> SUBSCRIBE runoobChat
    
    Reading messages... (press Ctrl-C to quit)
    1) "subscribe"
    2) "runoobChat"
    3) (integer) 1
    
  6. 重新开启个 redis 客户端,然后在同一个频道 runoobChat 发布两次消息,订阅者就能接收到消息。

  7. 第二个 redis-cli 客户端

    redis 127.0.0.1:6379> PUBLISH runoobChat "Redis PUBLISH test"
    
    (integer) 1
    
    redis 127.0.0.1:6379> PUBLISH runoobChat "Learn redis by runoob.com"
    
    (integer) 1
    
    # 订阅者的客户端会显示如下消息
     1) "message"
    2) "runoobChat"
    3) "Redis PUBLISH test"
     1) "message"
    2) "runoobChat"
    3) "Learn redis by runoob.com"
    

订阅一个或多个符合给定模式的频道。

  1. Redis Psubscribe 命令订阅一个或多个符合给定模式的频道。每个模式以 * 作为匹配符,比如 it* 匹配所有以 it 开头的频道( it.news 、 it.blog 、 it.tweets 等等)。

  2. news.* 匹配所有以 news. 开头的频道( news.it 、 news.global.today 等等),

  3. 命令格式:redis 127.0.0.1:6379> PSUBSCRIBE pattern [pattern ...]

    redis 127.0.0.1:6379> PSUBSCRIBE mychannel
    Reading messages... (press Ctrl-C to quit)
    1) "psubscribe"
    2) "mychannel"
    3) (integer) 1
    

Redis 发布订阅

  1. Redis Pubsub 命令用于查看订阅与发布系统状态,它由数个不同格式的子命令组成。

  2. 命令:redis 127.0.0.1:6379> PUBSUB <subcommand> [argument [argument ...]]

    redis 127.0.0.1:6379> PUBSUB CHANNELS
    (empty list or set)
    

Redis Publish 命令用于将信息发送到指定的频道。

  1. 返回接收到信息的订阅者数量。 redis 127.0.0.1:6379> PUBLISH channel message

    redis 127.0.0.1:6379> PUBLISH mychannel "hello, i m here"
    (integer) 1
    

Redis Punsubscribe 命令用于退订所有给定模式的频道。

  1. 命令:redis 127.0.0.1:6379> PUNSUBSCRIBE [pattern [pattern ...]]

    redis 127.0.0.1:6379> PUNSUBSCRIBE mychannel 
    1) "punsubscribe"
    2) "a"
    3) (integer) 1
    

Redis Subscribe 命令用于订阅给定的一个或多个频道的信息。。

  1. 返回接受的信息,命令:redis 127.0.0.1:6379> SUBSCRIBE channel [channel ...]

    redis 127.0.0.1:6379> SUBSCRIBE mychannel 
    Reading messages... (press Ctrl-C to quit)
    1) "subscribe"
    2) "mychannel"
    3) (integer) 1
    1) "message"
    2) "mychannel"
    3) "a"
    

Redis Unsubscribe 命令用于退订给定的一个或多个频道的信息。

  1. 命令:redis 127.0.0.1:6379> UNSUBSCRIBE channel [channel ...]

    redis 127.0.0.1:6379> UNSUBSCRIBE mychannel 
    1) "unsubscribe"
    2) "a"
    3) (integer) 0
    

ACID回顾

  1. 所谓事务(Transaction) ,是指作为单个逻辑工作单元执行的一系列操作
  2. Atomicity(原子性):构成事务的的所有操作必须是一个逻辑单元,要么全部执行,要么全部不执行。Redis:一个队列中的命令 执行或不执行
  3. Consistency(一致性):数据库在事务执行前后状态都必须是稳定的或者是一致的。Redis: 集群中不能保证时时的一致性,只能是最终一致性
  4. Isolation(隔离性):事务之间不会相互影响。Redis: 命令是顺序执行的,在一个事务中,有可能被执行其他客户端的命令的
  5. Durability(持久性):事务执行成功后必须全部写入磁盘。Redis有持久化但不保证 数据的完整性

Redis 事务

  1. Redis 事务可以一次执行多个命令, 并且带有以下三个重要的保证:

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

  3. 以 MULTI 开始一个事务, 然后将多个命令入队到事务中, 最后由 EXEC 命令触发事务, 一并执行事务中的所有命令:

    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"
    
  4. 单个 Redis 命令的执行是原子性的,但 Redis 没有在事务上增加任何维持原子性的机制,所以 Redis 事务的执行并不是原子性的。

  5. 事务可以理解为一个打包的批量执行脚本,但批量指令并非原子化的操作,中间某条指令的失败不会导致前面已做指令的回滚,也不会造成后续的指令不做。

DISCARD 取消事务,放弃执行事务块内的所有命令

redis 127.0.0.1:6379> MULTI
OK

redis 127.0.0.1:6379> PING
QUEUED

redis 127.0.0.1:6379> SET greeting "hello"
QUEUED

redis 127.0.0.1:6379> DISCARD
OK

EXEC 执行所有事务块内的命令

  1. 事务块内所有命令的返回值,按命令执行的先后顺序排列。 当操作被打断时,返回空值 nil 。
# 事务被成功执行

redis 127.0.0.1:6379> MULTI
OK

redis 127.0.0.1:6379> INCR user_id
QUEUED

redis 127.0.0.1:6379> INCR user_id
QUEUED

redis 127.0.0.1:6379> INCR user_id
QUEUED

redis 127.0.0.1:6379> PING
QUEUED

redis 127.0.0.1:6379> EXEC
1) (integer) 1
2) (integer) 2
3) (integer) 3
4) PONG


# 监视 key ,且事务成功执行

redis 127.0.0.1:6379> WATCH lock lock_times
OK

redis 127.0.0.1:6379> MULTI
OK

redis 127.0.0.1:6379> SET lock "huangz"
QUEUED

redis 127.0.0.1:6379> INCR lock_times
QUEUED

redis 127.0.0.1:6379> EXEC
1) OK
2) (integer) 1


# 监视 key ,且事务被打断

redis 127.0.0.1:6379> WATCH lock lock_times
OK

redis 127.0.0.1:6379> MULTI
OK

redis 127.0.0.1:6379> SET lock "joe"        # 就在这时,另一个客户端修改了 lock_times 的值
QUEUED

redis 127.0.0.1:6379> INCR lock_times
QUEUED

redis 127.0.0.1:6379> EXEC                  # 因为 lock_times 被修改, joe 的事务执行失败
(nil)

MULTI 标记一个事务块的开始

  1. Redis Multi 命令用于标记一个事务块的开始。

  2. 事务块内的多条命令会按照先后顺序被放进一个队列当中,最后由 EXEC 命令原子性(atomic)地执行。

    redis 127.0.0.1:6379> MULTI            # 标记事务开始
    OK
    
    redis 127.0.0.1:6379> INCR user_id     # 多条命令按顺序入队
    QUEUED
    
    redis 127.0.0.1:6379> INCR user_id
    QUEUED
    
    redis 127.0.0.1:6379> INCR user_id
    QUEUED
    
    redis 127.0.0.1:6379> PING
    QUEUED
    
    redis 127.0.0.1:6379> EXEC             # 执行
    1) (integer) 1
    2) (integer) 2
    3) (integer) 3
    4) PONG
    

UNWATCH 取消 WATCH 命令对所有 key 的监视。

redis 127.0.0.1:6379> WATCH lock lock_times
OK

redis 127.0.0.1:6379> UNWATCH
OK

Watch 命令用于监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断

redis> WATCH lock lock_times
OK

Redis 脚本

  1. Redis 脚本使用 Lua 解释器来执行脚本。 Redis 2.6 版本通过内嵌支持 Lua 环境。执行脚本的常用命令为 EVAL。
  2. Eval 命令的基本语法:redis 127.0.0.1:6379> EVAL script numkeys key [key ...] arg [arg ...]

执行 Lua 脚本。

  1. Redis Eval 命令使用 Lua 解释器执行脚本。

  2. 命令基本语法: redis 127.0.0.1:6379> EVAL script numkeys key [key ...] arg [arg ...]

    1. script: 参数是一段 Lua 5.1 脚本程序。脚本不必(也不应该)定义为一个 Lua 函数。
    2. numkeys: 用于指定键名参数的个数。
    3. key [key …]: 从 EVAL 的第三个参数开始算起,表示在脚本中所用到的那些 Redis 键(key),这些键名参数可以在 Lua 中通过全局变量 KEYS 数组,用 1 为基址的形式访问( KEYS[1] , KEYS[2] ,以此类推)。
    4. arg [arg …]: 附加参数,在 Lua 中通过全局变量 ARGV 数组访问,访问的形式和 KEYS 变量类似( ARGV[1] 、 ARGV[2] ,诸如此类)
    redis 127.0.0.1:6379> eval "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 first second
    1) "key1"
    2) "key2"
    3) "first"
    4) "second"
    

Redis Evalsha 命令根据给定的 sha1 校验码,执行缓存在服务器中的脚本。

  1. 将脚本缓存到服务器的操作可以通过 SCRIPT LOAD 命令进行,这个命令的其他地方,比如参数的传入方式,都和 EVAL 命令一样
  2. 基本命令:redis 127.0.0.1:6379> EVALSHA sha1 numkeys key [key ...] arg [arg ...]
    1. sha1 : 通过 SCRIPT LOAD 生成的 sha1 校验码。
    2. numkeys: 用于指定键名参数的个数。
    3. key [key …]: 从 EVAL 的第三个参数开始算起,表示在脚本中所用到的那些 Redis 键(key),这些键名参数可以在 Lua 中通过全局变量 KEYS 数组,用 1 为基址的形式访问( KEYS[1] , KEYS[2] ,以此类推)。
    4. arg [arg …]: 附加参数,在 Lua 中通过全局变量 ARGV 数组访问,访问的形式和 KEYS 变量类似( ARGV[1] 、 ARGV[2] ,诸如此类)。
redis 127.0.0.1:6379> SCRIPT LOAD "return 'hello moto'"
"232fd51614574cf0867b83d384a5e898cfd24e5a"

redis 127.0.0.1:6379> EVALSHA "232fd51614574cf0867b83d384a5e898cfd24e5a" 0
"hello moto"

Redis Script Exists 命令用于校验指定的脚本是否已经被保存在缓存当中

  1. 命令:SCRIPT EXISTS sha1 [sha1 ...]

  2. 返回值 :一个列表,包含 0 和 1 ,前者表示脚本不存在于缓存,后者表示脚本已经在缓存里面了。列表中的元素和给定的 SHA1 校验和保持对应关系,比如列表的第三个元素的值就表示第三个 SHA1 校验和所指定的脚本在缓存中的状态。

    redis 127.0.0.1:6379> SCRIPT LOAD "return 'hello moto'"    # 载入一个脚本
    "232fd51614574cf0867b83d384a5e898cfd24e5a"
    
    redis 127.0.0.1:6379> SCRIPT EXISTS 232fd51614574cf0867b83d384a5e898cfd24e5a
    1) (integer) 1
    
    redis 127.0.0.1:6379> SCRIPT FLUSH     # 清空缓存
    OK
    
    redis 127.0.0.1:6379> SCRIPT EXISTS 232fd51614574cf0867b83d384a5e898cfd24e5a
    1) (integer) 0
    

Redis Script Flush 命令用于清除所有 Lua 脚本缓存

  1. redis Script Flush 命令基本语法如下:redis 127.0.0.1:6379> SCRIPT FLUSH

  2. 返回值:总是反馈OK

    redis 127.0.0.1:6379> SCRIPT FLUSH
    OK
    

Redis Script kill 命令用于杀死当前正在运行的 Lua 脚本

  1. Redis Script kill 命令用于杀死当前正在运行的 Lua 脚本,当且仅当这个脚本没有执行过任何写操作时,这个命令才生效。这个命令主要用于终止运行时间过长的脚本,比如一个因为 BUG 而发生无限循环的脚本。

  2. SCRIPT KILL 执行之后,当前正在运行的脚本会被杀死,执行这个脚本的客户端会从 EVAL 命令的阻塞当中退出,并收到一个错误作为返回值。

  3. redis Script kill 命令基本语法如下:redis 127.0.0.1:6379> SCRIPT KILL

  4. 返回值:返回OK

    redis 127.0.0.1:6379> SCRIPT KILL
    OK
    

Redis Script Load 命令用于将脚本 script 添加到脚本缓存中,但并不立即执行这个脚本。

  1. Redis Script Load 命令用于将脚本 script 添加到脚本缓存中,但并不立即执行这个脚本。

  2. EVAL 命令也会将脚本添加到脚本缓存中,但是它会立即对输入的脚本进行求值。如果给定的脚本已经在缓存里面了,那么不执行任何操作。

  3. 在脚本被加入到缓存之后,通过 EVALSHA 命令,可以使用脚本的 SHA1 校验和来调用这个脚本。脚本可以在缓存中保留无限长的时间,直到执行 SCRIPT FLUSH 为止。

  4. redis Script Load 命令基本语法如下:redis 127.0.0.1:6379> SCRIPT LOAD script

  5. 返回值:给定脚本的 SHA1 校验和

    redis 127.0.0.1:6379> SCRIPT LOAD "return 1"
    "e0e1f9fabfc9d4800c877a703b823ac0578ff8db"
    
  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值