目录
1. redis发布订阅(pub/sub)
redis发布订阅(pub/sub)是一种消息通信模式:发送者发送消息,订阅者接收消息。
发布订阅也叫生产者消费者模式,是实现消息队列的一种方式。
1.1 发布订阅命令
命令 | 说明 |
subscribe channel1 [channel2…] | 订阅给定的一个或多个频道的信息 |
psubscribe pattern1 [pattern2…] | 订阅一个或多个符合给定模式的频道的信息 |
publish channel message | 将信息发送到指定的频道 |
pubsub subcommand [argument1 [argument2…]] | 查看订阅与发布系统状态 |
unsubscribe [channel1 [channel2…]] | 推定一个或多个给定的频道 |
punsubscribe [pattern1 [pattern2…]] | 退订一个或多个符合给定模式的频道的信息 |
1.2 发布订阅实例
开启redis客户端,让消息订阅者订阅某个频道
[root@CentOS7 src]# ./redis-cli
127.0.0.1:6379> SUBSCRIBE channel
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "channel"
3) (integer) 1
重新开启另一个redis客户端,让消息发布者向频道发布消息
[root@CentOS7 src]# ./redis-cli
127.0.0.1:6379> PUBLISH channel "hello,everyone"
(integer) 2
127.0.0.1:6379> PUBLISH channel "你好"
(integer) 2
然后观察消息的发布和订阅情况
2. redis 事务
2.1 事务与redis事务
事务:事务是指一系列操作步骤,这一系列的操作步骤,要么完全地执行,要么完全地不执行。
要保证一系列的操作都完全成功,提出了事务控制的概念。
redis事务:redis中的事务(transaction)是一组命令的集合,至少是两个或两个以上的命令。redis事务保证这些命令被执行时中间不会被任何其他操作终端。
2.2 事务命令
事务命令 | 说明 |
multi | 标记一个事务的开始 |
exec | 执行所有事务块内的命令 |
watch key1 [key2…] | 监视一个或多个key,如果在事务执行之前这些key被其他命令所改动,那么事务将被打断 |
unwatch | 取消watch命令对所有key的监视 |
discard | 取消事务,放弃执行事务块内的所有命令 |
3. redis对事务控制的实现
一个事务从开始到执行会经历以下三个步骤:开始事务、执行命令、提交事务
3.1 正常情况
# 用multi命令告诉redis,接下来要执行的命令先不要执行,而是将它们暂时存储起来(开启事务)
127.0.0.1:6379> MULTI
OK
# 第一条命令进入等待队列(命令入队)
127.0.0.1:6379> set k1 v1
QUEUED
# 第二条命令进入等待队列(命令入队)
127.0.0.1:6379> set k2 v2
QUEUED
# 告知redis执行前面发送的两条命令(提交事务)
127.0.0.1:6379> EXEC
1) OK
2) OK
#测试可以获取到k1和k2的值
127.0.0.1:6379> mget k1 k2
1) "v1"
2) "v2"
3.2 异常情况(回滚)
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set k3 v3
QUEUED
# 命令语法错误
127.0.0.1:6379> set k4
(error) ERR wrong number of arguments for 'set' command
# 无法执行事务,那么第一条正确的命令也不会执行
127.0.0.1:6379> exec
(error) EXECABORT Transaction discarded because of previous errors.
#获取不到k3和k4的值
127.0.0.1:6379> mget k3 k4
1) (nil)
2) (nil)
3.3 例外情况(部分支持事务)
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set k5 v5
QUEUED
# 此命令错误,字符串不能自增,但是命令入队成功(语法上无错误)
127.0.0.1:6379> incr key
QUEUED
# 事务依然提交,然是key的值时字符串,自增操作执行失败,但整个事务没有回滚
127.0.0.1:6379> exec
1) OK
2) (error) ERR value is not an integer or out of range
127.0.0.1:6379> get k5
"v5"
3.4 放弃情况
127.0.0.1:6379> set k6 v6
QUEUED
127.0.0.1:6379> set k6 vv
QUEUED
# 放弃事务,则命令队列都不会被执行
127.0.0.1:6379> discard
OK
# 获取不到k6的值
127.0.0.1:6379> get k6
(nil)
3.5 复杂情况
1. 悲观锁
悲观锁(pessimistic lock),每次去拿数据的时候都认为别人会修改数据,所以每次在拿数据的时候都会先上锁,这样别人想拿这个数据就会block阻塞直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁,让别人无法操作该数据。
2. 乐观锁
乐观锁(optimistic lock),每次去拿数据的时候都认为别人不会修改该数据,所以不会上锁,但是在更新数据的时候会判断在此期间有没有去更新这条数据,一般使用版本号机制进行判断。乐观锁适用于多读的应用类型,可以提高吞吐量。
乐观锁大多情况是基于数据版本号(version)的机制实现的。数据版本,即为数据增加一个版本标识,在基于数据库表的解决方案种,一般是通过为数据库表添加一个"version"字段来实现读取出数据时,将此版本号一同读出。之后更新时,对此版本号加1。此时,将提交数据的版本号与数据库表对应记录的当前版本号进行比对,如果提交的数据版本号大于数据库表当前版本号,则予以更新,否则认为是过期数据,不予更新。
3. watch机制实现乐观锁
127.0.0.1:6379> set k7 v7
OK
127.0.0.1:6379> watch k7
OK
127.0.0.1:6379> set k7 vvv
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set k7 v
QUEUED
# 提交事务,但k7值不会被修改为v,k7的值仍然是vvv,因为在事务开启之前k7的值被修改了
127.0.0.1:6379> exec
(nil)
127.0.0.1:6379> get k7
"vvv"
4. reids持久化
4.1 持久化概述
持久化可以理解为存储,就是将数据存储到一个不会丢失的地方,如果把数据放在内存种,电脑关闭或重启数据就会丢失,所以放在内存中的数据不是持久的,而放在磁盘种的数据就算是一种持久化。
redis的数据存储在内存中。内存是瞬时的,如果系统宕机或重启,或redis崩溃或重启,所有的内存数据都会丢失。为解决这个问题,redis提供两种机制对数据进行持久化存储,便于发生故障后能迅速恢复数据。
4.2 redis两种持久化方式
1. RDB
redis database(RDB),就是在指定的时间间隔将内存中的数据集快照写入磁盘,数据恢复时将快照文件直接再读到内存。
RDB方式的数据持久化,需修改redis.conf配置文件。
[root@CentOS7 redis-5.0.5]# vim redis.conf
# 指定再多长时间内,有多少次更新操作,就将数据同步到数据文件,可以将多个条件配合。redis默认配置文件中提供了三个条件:分别表示900s内有一个更改、300s内有10个更改以及60s内有10000个更改
218 save 900 1
219 save 300 10
220 save 60 10000
235 stop-writes-on-bgsave-error yes
# 指定存储至本地数据库时是否压缩数据,默认为yes
241 rdbcompression yes
250 rdbchecksum yes
# 设置RDB的文件名,默认dump.rdb
253 dbfilename dump.rdb
# 指定RDB和AOF文件目录
263 dir ./
2. AOF
Append-only file(AOF),redis每接收一条改变数据的命令时,它将该命令写到一个AOF文件中(只记录写操作,不记录读操作),当redis重启时,它通过执行AOF文件中所有的命令来恢复数据。
AOF方式的数据持久化,需修改redis.conf配置文件。
[root@CentOS7 redis-5.0.5]# vim redis.conf
# 是否开启AOF持久化,默认为no(建议设置为yes)
699 appendonly no
# 指定AOF文件名,默认appendonly.aof
703 appendfilename "appendonly.aof"
# 配置向AOF文件写命令数据的策略,有三个可选值:
# no表示不主动进行同步操作,而是完全交由操作系统来做(每30s一次),比较快但不是很安全;
# always表示每次写入都会执行同步,较慢但是比较安全;
# everysec表示每s执行一次同步操作,比较平衡,介于速度和安全之间;
729 appendfsync everysec
751 no-appendfsync-on-rewrite no
# 当目前AOF文件大小超过上一次重写时的AOF文件大小的百分之多少时会再次进行重写,如果之前没有重写,则以启动时的AOF文件大小为依据
770 auto-aof-rewrite-percentage 100
# 允许重写的最小AOF文件大小,默认64Mb
771 auto-aof-rewrite-min-size 64mb
795 aof-load-truncated yes
806 aof-use-rdb-preamble yes
AOF实例
首先随便设置几个键的值value
[root@CentOS7 src]# ./redis-cli
127.0.0.1:6379> set k1 v1
OK
127.0.0.1:6379> set k2 v2
OK
127.0.0.1:6379> exit
查看对应的AOF文件
[root@CentOS7 src]# cat appendonly.aof
*2
$6
SELECT
$1
0
*3
$3
set
$2
k1
$2
v1
*3
$3
set
$2
k2
$2
v2