Redis通过multi,exec,watch命令来实现事务的功能。事务提供了一种将多个命令请求打包,然后一次性,按顺序地执行多个命令的机制,并且在事务执行期间,服务器不会中断事务而改去执行其他客户端的命令请求。下面来看看Redis中事务的实现原理。


一.事务的实现


一个事务从开始到结束会经历三个阶段:事务开始,命令入队,事务执行。


1.事务开始


Redis提供multi命令标志着事务的开始,这一命令其实就是修改了客户端的flags属性,将flags属性改为REDIS_MULTI。


2.命令入队


当客户端处于非事务状态时,客户端发送的命令会立即被服务器执行。当客户端处于事务状态时,服务器会将客户端的命令放入一个事务队列,然后向客户端返回QUEUED回复,表示命令入队。


3.执行事务


当处于事务状态的客户端向服务器发送exec命令时,这个命令会立即被服务器执行,服务器会遍历事务队列,取出队列中所有命令,顺序执行命令,将命令的执行结果保存在回复队列里。


二.Redis的watch命令


watch命令可以在exec命令执行之前,监视任意数量的数据库键,并在exec命令执行时,检查被监视的键是否至少有一个已经被修改过了,如果是的话,服务器将拒绝执行事务,并向客户端返回事务执行失败的空回复。


1.使用watch监视数据库键


每个Redis数据库都保存着一个 watched_keys字典,字典的键是被watch命令监视的数据库键,字典的值则是一个链表,链表里记录了所有监视相应数据库的客户端。通过watched_keys字典,服务器可以清楚地知道哪些数据库键正在被监视,以及哪些客户端正在监视这些数据库键。


2.监视机制的触发


所有对数据库进行的修改命令,在执行之后都会调用touchWatchKey函数对watched_keys字典进行检查,查看是否有客户端正在监视刚刚被命令修改过的数据库键,如果有的话,那么touchWatchKey函数会将被监视修改键的客户端的REDIS_DIRTY_CAS标识打开,标识客户端的事务安全性已经被破坏。


3.判断事务是否安全


当服务器收到客户端发来的exec命令时,服务器会检查这个客户端是否打开了REDIS_DIRTY_CAS标识来决定是否执行事务。如果客户端的REDIS_DIRTY_CAS标识已经被打开,说明客户端监视的键当中,至少有一个键已经被修改了,这种情况下,服务器会拒绝客户端提交的事务,返回事务执行失败。


以上就是Redis提供的watch命令的实现原理,Redis通过watch监视机制来保证事务执行期间,没有其他客户端修改了监视的键,从而实现事务的功能。


参考内容:Redis设计与实现-黄健宏