目录
1.1 发布订阅
1.1.1 什么是发布订阅
1.1.2 常用命令
1.1.3 示例演示
1.2 事务管理
1.2.1 事务定义
1.2.2 Multi、Exec、discard
1.2.3 示例
1.2.4 事务的错误处理
1.2.5 事务的冲突问题
1.2.5.1 事务场景
1.2.5.2 悲观锁
1.2.5.3 乐观锁
1.2.5.4 事务解决冲突(WATCH)
1.2.5.5 unwatch
1.2.6 Redis事务的三个特征
1.1 发布订阅
1.1.1 什么是发布订阅
Redis发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。Redis客户端可以订阅任意数量的频道
当有新的消息通过 PUBLISH 命令发送给频道 channel1 时,这个消息就会被发送给订阅的三个客户端
1.1.2 常用命令
命令语法 | 描述 |
PSUBSCRIBE pattern [pattern......] | 订阅一个或多个符合给定模式的频道 |
PUBSUB subcommand [argument [argument...]] | 查看订阅与发布系统的状态 |
PUBLISH channel message | 将信息发送到指定的频道 |
PUNSUBSCRIBE [pattern [pattern......]] | 退订所有给定模式的频道 |
SUBSCRIBE channel [channel......] | 订阅给定的一个或者多个频道信息 |
UNSUBSCRIBE [channel [channel......]] | 退订给定的频道 |
1.1.3 示例演示
创建四个客户端Cli_1~Cli4
#cli1 创建订阅的频道redisChat
127.0.0.1:6379> SUBSCRIBE redisChat
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "redisChat"
3) (integer) 1
#cli2 在同一频道redisChat 发布消息
127.0.0.1:6379> PUBLISH redisChat "SendMessage_1"
(integer) 1
#此处可切换到 cli1内查看是否读取到cli2发布的消息
#cli3 在同一频道redisChat 发布消息
127.0.0.1:6379> PUBLISH redisChat "SendMessage_2"
(integer) 1
#此处可切换到 cli1内查看是否读取到cli3发布的消息
#cli4 创建订阅的频道redisChat
127.0.0.1:6379> SUBSCRIBE redisChat
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "redisChat"
3) (integer) 1
#cli3 在同一频道redisChat 发布消息
127.0.0.1:6379> PUBLISH redisChat "SendMessage_2"
(integer) 1
#此处可切换到 cli1及cli4内查看是否读取到cli3发布的消息
cli1收到3条信息 分别来自于 cli2一次 以及 cli3两次
cli4收到1条信息 cli3一次
1.2 事务管理
1.2.1 事务定义
Redis事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断
Redis 事务的主要作用就是串联多个命令防止别的命令插队
1.2.2 Multi、Exec、discard
从输入Multi命令开始,后面输入的数量命令都会一次进入到命令队列当中,但是不会执行,直到输入Exec后,Redis会将之前的命令队列中的命令依次执行
组队过程中,可以通过 discard 来放弃组队
Redis的事务可以一次执行多条命令
批量操作在发送 Exec 命令前被放入队列缓存
收到 Exec 命令后,进入事务执行,如果事务中有任意命令执行失败,其余的命令依旧会执行
在事务的执行过程中,会按照顺序串行化执行队列中的命令,其他客户端提交的命令请求,不会插入到事务执行的命令序列中
1.2.3 示例
#组队阶段成功、提交成功的情况
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> set k1 v1
QUEUED
127.0.0.1:6379(TX)> set k2 v2
QUEUED
127.0.0.1:6379(TX)> exec
1) OK
2) OK
#组队阶段报错、提交必然报错(所有数据全部回滚)
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> set k3 v3
QUEUED
127.0.0.1:6379(TX)> set k4
(error) ERR wrong number of arguments for 'set' command
127.0.0.1:6379(TX)> set k5 v5
QUEUED
127.0.0.1:6379(TX)> exec
(error) EXECABORT Transaction discarded because of previous errors.
#组队阶段成功、提交时发现组队命令有异常
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> set k3 v3
QUEUED
127.0.0.1:6379(TX)> incr k3
QUEUED
127.0.0.1:6379(TX)> set k4 v4
QUEUED
127.0.0.1:6379(TX)> get k3
QUEUED
127.0.0.1:6379(TX)> exec
1) OK
2) (error) ERR value is not an integer or out of range
3) OK
4) "v3"
1.2.4 事务的错误处理
组队时某个命令出现了错误报告,执行时整个的队列都会被取消
执行时某个命令报错,则只有报错的命令不会被执行,而其他命令都会执行,不会回滚
1.2.5 事务的冲突问题
1.2.5.1 事务场景
有一账户余额为10000元,现在出现三个请求,第一个请求想给金额-8000元,第二个请求想给金额-5000元,第三个请求想给金额-1000元
如果没有事务管理,则有可能出现如下场景
1.2.5.2 悲观锁
悲观锁(Pessimistic Lock)顾名思义,就是很悲观。每次去拿数据时都认为别人会修改,所以在每次拿数据时都会上锁,这样别人想拿到这个数据就会停顿,直到它拿到锁为止。在传统的关系型数据库内就会用到这种锁机制,比如 行锁 表锁 读锁 写锁,都是在操作之前先进行上锁处理
1.2.5.3 乐观锁
乐观锁(Optimistic Lock)顾名思义,就是很乐观。每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量。Redis就是利用这种check-and-set机制实现事务的
1.2.5.4 事务解决冲突(WATCH)
在执行multi之前,先执行 watch key1 [key2 ....] 用于指定key的监视,如果在事务执行前这些key被其他命令锁改动,那么事务将被打断
#cli1
set money 10000
#cli2
127.0.0.1:6379> watch money
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> decrby money 8000
QUEUED
#cli3
127.0.0.1:6379> watch money
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> decrby money 3000
QUEUED
#cli2
exec
#cli3
exec
1.2.5.5 unwatch
用于取消命令对所有key的监视
如果在执行 watch 命令之后,Exec 或 DisCard 命令先被执行的话,那么就不需要再次执行 unwatch
1.2.6 Redis事务的三个特征
单独的隔离操作 | 事务中所有命令都会序列化,按顺序执行。事务在执行过程中,不会被其他客户端发来的请求所打断 |
没有隔离级别的概念 | 队列中的命令没有提交前都不会被实际执行,因为事务提交前,所有指令都是处于等待状态 |
不保证原子性 | 事务中如果有一条命令执行失败,其后命令以及会执行,并且不会回滚 |