Redis事务机制

严格意义来讲,Redis的事务和我们理解的传统数据库(如mysql)的事务是不一样的;

Redis的事务实质上是命令的集合,在一个事务中要么所有命令都被执行,要么所有事物都不执行。 
一个事务从开始到执行会经历以下三个阶段:

  1. 开始事务。
  2. 命令入队。
  3. 执行事务。

在MySQL中我们使用START TRANSACTION 或 BEGIN开启一个事务,使用COMMIT提交一个事务;

而在Redis中我们使用MULTI 开始一个事务,由 EXEC 命令触发事务, 一并执行事务中的所有命令。

redis分布式事务解决方案 redis分布式事务原理_分布式锁

redis分布式事务解决方案 redis分布式事务原理_分布式锁_02

可以看到,MULTI 开始到 EXEC结束前,中间所有的命令都被加入到一个命令队列中;当执行 EXEC命令后,将QUEUE中所有的命令执行。

此外我们可以使用DISCARD取消事务。

redis分布式事务解决方案 redis分布式事务原理_redis分布式事务解决方案_03

需要注意的是: 
1.Redis的事务没有关系数据库事务提供的回滚(rollback),所以开发者必须在事务执行失败后进行后续的处理; 

分布式锁

什么是分布式锁?

分布式锁是控制分布式系统之间同步访问共享资源的一种方式。如果不同的系统或是同一个系统的不同主机之间共享了一个或一组资源,那么访问这些资源的时候,往往需要互斥来防止彼此干扰来保证一致性,在这种情况下,便需要使用到分布式锁。

实现分布式锁有很多实现方式和工具,如Zookeeper、Redis等。

使用Redis实现分布式锁原理:

Redis为单进程单线程模式,采用队列模式将并发访问变成串行访问,且多客户端对Redis的连接并不存在竞争关系,基于此,Redis中可以使用SETNX命令实现分布式锁。

SETNX——SET if Not eXists(如果不存在,则设置):

setnx key value

将 key 的值设为 value ,当且仅当 key 不存在。 
若给定的 key 已经存在,则 SETNX 不做任何动作。

redis分布式事务解决方案 redis分布式事务原理_分布式锁_04

如果需要解锁,使用 del key 命令就能释放锁:

redis分布式事务解决方案 redis分布式事务原理_redis分布式事务解决方案_05

左图首先使用setnx对键加锁成功返回1,右图再次使用setnx命令对键加锁失败返回0,说明有客户端持有锁。使用del释放锁以后,右图就可以使用setnx命令对键加锁。

解决死锁

如果一个持有锁的客户端失败或崩溃了不能释放锁,该怎么解决?

答:给锁设置一个过期时间,可以通过两种方法实现:通过命令 “setnx 键名 过期时间 “;或者通过设置锁的expire时间,让Redis去删除锁(指的是键)。