Redis的订阅事务持久化

Posted Dream

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Redis的订阅事务持久化相关的知识,希望对你有一定的参考价值。

1、Redis事务概念

(1)概念

redis的事务可以一次执行多个命令,它是按顺序地串行化执行,执行的过程中不允许插入其他命令。

不支持事务回滚

(2)常用命令

  • discard:取消事务,放弃执行事务块内的所有命令
  • exec:执行所有事务块内的命令
  • multi:标记一个事务块的开始
  • unwatch:取消watch命令对所有key的监视
  • watch:监视一个或多个key,如果在事务执行之前这个key被其他的命令所改动,那么事务将会被打断

(3)应用

在商品秒杀的过程中,当用户抢到了秒杀的商品后,要保证添加秒杀成功的用户的信息与用户的移除一起执行

(4)事务总结

Redis单条命令是保证原子性的,但是Redis的事务是没有原子性的。

Redis的事务执行的过程:开启(multi)、入队、执行(exec)

异常:编译时异常(代码有错误),队列中的所有命令都不会被执行。运行时异常,如果存在语法性错误,其他命令正常执行,错误命令抛出异常。

 

2、转账案例

(1)命令流程

127.0.0.1:6379> set account:a 100
OK
127.0.0.1:6379> set account:b 51
OK
127.0.0.1:6379> get account:a
"100"
127.0.0.1:6379> set account:a 100
OK
127.0.0.1:6379> set account:b 50
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> get account:a
QUEUED
127.0.0.1:6379> get account:b
QUEUED
127.0.0.1:6379> decrby account:a 10
QUEUED
127.0.0.1:6379> incrby account:b 10
QUEUED
127.0.0.1:6379> get account:a
QUEUED
127.0.0.1:6379> get account:b
QUEUED
127.0.0.1:6379> exec
1) "100"
2) "50"
3) (integer) 90
4) (integer) 60
5) "90"
6) "60"

现在两个账户中存入一定金额,通过命令multi开启一个事务,在执行exec命令之前,输入的其他命令都加在了一个队列里面,exec命令会执行事务快内的所有元素。

 

3、discard命令

(1)概念

在输入multi命令后所有的命令都会进入到一个队列中,但是没有执行。在执行exec命令之前,可以通过discard命令来放弃队列的内容。

(2)命令

127.0.0.1:6379> multi
OK
127.0.0.1:6379> set hello 123
QUEUED
127.0.0.1:6379> get aa
QUEUED
127.0.0.1:6379> discard
OK
127.0.0.1:6379> exec
(error) ERR EXEC without MULTI

 

4、redis的事务处理

(1)概念

如果执行某一个命令出现了错误,则只有报错的命令不会执行,其他命令都会执行,不会回滚

(2)redis语法错误时的事务处理

127.0.0.1:6379> set aaa nihao
QUEUED
127.0.0.1:6379> get aaa
QUEUED
127.0.0.1:6379> get aaa
QUEUED
127.0.0.1:6379> get aaa
QUEUED
127.0.0.1:6379> incr aaa
QUEUED
127.0.0.1:6379> exec
1) OK
2) "nihao"
3) "nihao"
4) "nihao"
5) (error) ERR value is not an integer or out of range

错误的命令报错,但是没有错误的命令都能正常执行

(3)redis命令错误时的事务处理

127.0.0.1:6379> multi
OK
127.0.0.1:6379> set aaa 123
QUEUED
127.0.0.1:6379> get aaa
QUEUED
127.0.0.1:6379> qqqqq
(error) ERR unknown command \'qqqqq\'
127.0.0.1:6379> exec
(error) EXECABORT Transaction discarded because of previous errors.

队列中的某一个命令出现错误,那么整个队列就会被取消

 

5、redis事务的watch

一个事务监视aaa并处理aaa:

127.0.0.1:6379> watch aaa
OK
127.0.0.1:6379> multi 
OK
127.0.0.1:6379> set aaa 123
QUEUED
127.0.0.1:6379> get aaa
QUEUED
127.0.0.1:6379> incr aaa
QUEUED
127.0.0.1:6379> exec
(nil)

另一个事务在上面的事务提交之前将aaa的值改变:

127.0.0.1:6379> set aaa 111
OK
127.0.0.1:6379> get aaa
"111"

为了保证数据的安全,aaa并没有获得值

 

 6、持久化

Redis的持久化:可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。存储在内存中的数据虽然高效,但是断电的时候数据会丢失;存储在硬盘上的数据速度虽然慢于内存,但是断电不会丢失。

Redis的持久化支持两种方式:

(1)RDB持久化

将数据以快照的形式存储到磁盘上(二进制文件),当再次重启服务器的时候可以直接读取磁盘上的快照,默认的文件名为:dump.rdb。

优势:

适合于数据量较大的数据库操作,这是相对于AOF方式的持久化而言的,如果数据库的操作过于复杂那么日志文件也会相当复杂,数据库的恢复过程工作量会相应增加。

快照保存的数据极快,还原数据极快

适合于灾难备份

劣势:

易丢失数据,快照是在一定的时间间隔做一次,如果redis意外down掉的话,就会丢失快照后的所有修改

小内存机器不适合使用(占用内存较多)

(2)AOF持久化

比快照方式有更好的持久性,在使用aof持久化方式的时候,redis会将每一个收到的写命令都通过write函数追加到文件中。以日志的形式记录数据库的操作,当重启服务器后读取日志文件,重建整个数据库的内容。

劣势:

持久化的文件会越来越大,例如:调用incr test命令100次,文件必须保存全部的100条命令,其中有99条是多余的。

 

7、乐观锁

Redis Watch 命令用于监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断,类似于Java中的CAS算法。

 

以上是关于Redis的订阅事务持久化的主要内容,如果未能解决你的问题,请参考以下文章

Redis---常见重点知识1(事务持久化机制发布订阅)

Redis---常见重点知识1(事务持久化机制发布订阅)

Redis学习--key的通用操作移库操作订阅与事务持久化和总结

Redis发布订阅和事务实现原理

Redis发布订阅和事务实现原理

最近学习redis一些简单的记录