目录
Redis事务:一次失误操作,该成功的成功,该失败的失败。
先开启事务,执行一些列的命令,但是命令不会立即执行,会存放在一个
队列中,如果你执行事务,
这个队列中的所有命令都会执行,取消事务,所有命令全部作废。
redis事务的主要作用就是串联多个命令防止 别的命令插队。
大致的形式如下:
begin();
try {
// 执行业务相关代码
command1();
command2();
....
commit();
} catch(Exception e) {
rollback();
}
Redis 在形式上看起来也差不多,MULTI、EXEC、DISCARD这三个指令构成
了 redis 事务处理的基础:
MULTI:用来组装一个事务,从输入Multi命令开始,输入的命令都会依次进
入命令队列中, 但不会执行,直到输入Exec后,redis会将之前的命令依次执
行。
EXEC:用来执行一个事务
DISCARD:用来取消一个事务
事务操作案例1:
127.0.0.1:6379> set user_id 1 # 定义了一个user_id的key,value为1
OK
127.0.0.1:6379> get user_id
"1"
127.0.0.1:6379> MULTI # 标记事务开始
OK
127.0.0.1:6379> incr user_id # 多条命令按顺序入队,返回值为QUEUED,
表示这个命令加入队列了,还没有被执行。
QUEUED
127.0.0.1:6379> incr user_id # incr是自增的命令
QUEUED
127.0.0.1:6379> incr user_id
QUEUED
127.0.0.1:6379> exec # 执行事务过后返回的是事务块内所有命令的返回
值,按命令执行的先后顺序排列。
1) (integer) 2
2) (integer) 3
3) (integer) 4
127.0.0.1:6379> get user_id
"4"
上面的指令演示了一个完整的事务过程,所有的指令在 exec 之前不执行,
而是缓存在服务器的一个事务队列中,
服务器一旦收到 exec 指令,才开执行整个事务队列,执行完毕后一次性返
回所有指令的运行结果。
因为 Redis 的单线程特性,不用担心自己在执行队列的时候被其它指令打
搅,可以保证能得到的有顺序的执行。
案例二:取消事务,放弃执行事务块内的所有命令
127.0.0.1:6379> keys *
(empty list or set)
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> SET greeting "hello"
QUEUED
127.0.0.1:6379> set kaka aaa
QUEUED
127.0.0.1:6379> DISCARD
OK
127.0.0.1:6379> keys *
(empty list or set)
案例三:组队中某个命令出现了错误报告,执行时整个队列中所有的命令
都会被取消。
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> multi # 开启一个事务块
OK
127.0.0.1:6379> set name ready
QUEUED
127.0.0.1:6379> set age 30
QUEUED
127.0.0.1:6379> set1 age 60 # 命令有问题,导致加入队列失败
(error) ERR unknown command `set1`, with args beginning with: `age`,
`60`,
127.0.0.1:6379> exec # 执行exec的时候,事务中所有命令都被取消
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> get name # 事务当中的命令也全都执行失败了
(nil)
127.0.0.1:6379> keys *
(empty list or set)
案例4:命令组队的过程中没有问题,执行中出现了错误会导致部分成功部
分失败。
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set books iamastring
QUEUED
127.0.0.1:6379> set poorman iamdesperate
QUEUED
127.0.0.1:6379> incr books
QUEUED
127.0.0.1:6379> exec
1) OK
2) OK
3) (error) ERR value is not an integer or out of range # incr是对数字类型的进行自增,而books存的是字母
127.0.0.1:6379> get books # 只有incr books 执行失败了,其他都执行成功了。
"iamastring"
127.0.0.1:6379> get poorman
"iamdesperate"
watch监听
WATCH:在执行multi之前,先执行watch key1 [key2 …],可以监视一个或
者多个key,
若在事务的exec命令之前这些key对应的值被其他命令所改动了,那么
事务中所有命令都将被打断,
即事务所有操作将被取消执行。
unwatch:取消 WATCH 命令对所有 key 的监视。如果在执行 WATCH 命
令之后,
EXEC 命令或 DISCARD 命令先被执行了的话,那么就不
需要再执行UNWATCH 了。
注意:Redis 禁止在 multi 和 exec 之间执行 watch 指令,而必须在 multi
之前做好盯住关键变量,否则会出错。
案例一:监视 key,且事务成功执行
127.0.0.1:6379> set lock aa # 新增了一个key/value
OK
127.0.0.1:6379> keys * # 数据库目前就只有lock一个key
1) "lock"
127.0.0.1:6379> watch lock lock_times # 开始监视key为lock或者
lock_times的值。lock_times在数据库不存在也是可以监视的
OK
127.0.0.1:6379> multi # 开启事务
OK
127.0.0.1:6379> SET lock "huangz"
QUEUED
127.0.0.1:6379> INCR lock_times # INCR是对一个key值进行自增,假如
key值没有在数据库当中会进行创建并赋值为1
QUEUED
127.0.0.1:6379> EXEC # 开始执行事务
1) OK
2) (integer) 1
127.0.0.1:6379> get lock
"huangz"
127.0.0.1:6379> get lock_times
"1"
案例二:监视 key,且事务被打断,这里需要准备两个客户端进行测试
案例三:watch监听key后只对当前客户端第一个事务有效,并不影响其他命令执行
127.0.0.1:6379> watch lock
OK
127.0.0.1:6379> set lock 'cccc'
OK
127.0.0.1:6379> get lock
"cccc"
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set lock bbb
QUEUED
127.0.0.1:6379> exec #exec 指令返回一个 null 回复时,事务执行是失败
的
(nil)
案例四:取消监听
127.0.0.1:6379> WATCH lock lock_times
OK
127.0.0.1:6379> UNWATCH
OK
RDB是Redis默认的持久化机制
RDB持久化文件,速度比较快,而且存储的是一个二进制的文件,传
输起来很方便。
RDB持久化时机:
save 900 1:在900内,有1个key改变了,就执行RDB持久化。
save 300 10:在300内,有10个key改变了,就执行RDB持久化。
save 60 10000:在60内,有10000个key改变了,就执行RDB持久化。
RDB无法保证数据的绝对安全。
AOF持久化机制默认是关闭的,Redis官方推荐同时开启RDB和AOF持
久化,更安全,避免数据丢失。
AOF持久化的速度,相对于RDB是较慢的,存储的是一个文本文件,
到了后期文件会比较大,传输困难。
AOF持久化时机。
appendfsync always:每执行一个写操作,立即持久化到AOF文件中,
性能比较低。
appendfsync ererysec:每一秒执行一次持久化。
appendfsyncno:会根据你的操作系统不同,
环境的不同,在一定时间内持久。
AOF 相对RDB更安全,推荐同时开启AOF和RDB
同时开启RDB和AOF的注意事项:
如果同时开启了AOF和RDB持久化,那么在Redis宕机重启之后,需要
加载一个持久化文件,
优先选择AOF文件。
如果先开启了RDB,再次开启AOF,如果RDB执行了持久化,那么
RDB文件中的内容会被AOF覆盖掉。
哨兵可以帮助我们解决主从结构中的单点故障问题
# 哨兵需要后台启动
daemonize yes
# 指定Master节点的ip和端口(主)
sentinel monitor master localhost 6379 2
# 指定Master节点的ip和端口(从)
sentinel monitor master master 6379 2
# 哨兵每隔多久监听一次redis架构
sentinel down-after-milliseconds mymaster 10000
Redis集群在保证主从加哨兵的基本功能之外,还能够提升Redis存储
数据的能力。
Redis集群架构图
Redis集群是无中心的。
Redis集群有一个ping-pang机制
投票机制,Redis集群节点的数量必须是2n+1.
Redis集群中默认分配了16384个hash槽,在存储数据时,就会将key进
行crc16的算法,
并且对16384取余,根据最终的结果,将key-value存放到指定Redis节
点中,
而且每一个Redis集群都在维护着相应的hash槽。
为了保证数据的安全性,每一个集群的节点,至少要有一个从节点。
单独针对Redis集群中的某一个节点搭建主从。
当Redis集群中,超过半数的节点宕机之后,Redis集群就瘫痪了。