本项目完整地址 simple-redis
Simple-Redis 是支持分布式事务的,采用 TCC(Try-Commit-Cancel)实现分布式事务,以当前节点为事务协调者,控制分布在其他节点的本地事务。所以 Simple-Redis 的分布式事务实现包括两个部分:
- 事务协调者:一个分布式事务的控制器。
- 本地事务:用于执行命令,并进行 commit 或者 cancel。
事务协调者
定义
TCC 事务协调者定义如下:
1 | // Coordinator TCC事务协调者 |
流程
一次分布式事务的流程如下:
- 对命令和 watch 的 key,按照节点的不同进行分组。
- 对每一组节点发送 try 命令,try 命令比较复杂又分为几个子命令:
- try start:通知节点有新建一个本地分布式事务。
- try watched:发送 wath 时的 version,比较 version 是否发生变化。
- try xxx:依次发送在该节点上执行的命令。
- try end:通知 try 阶段已经结束,本地事务检查版本是否变化、锁定相关的 key。
- 对每一组节点发送 commit 或者 cancel 命令。
- 重组事务的返回结果,按照正常的顺序进行返回。
1 | // ExecTx 执行TCC分布式事务 |
try
try 命令比较复杂,分为几个子命令:
- try start:通知节点有新建一个本地分布式事务。
- try watched:发送 wath 时的 version,比较 version 是否发生变化。
- try xxx:依次发送在该节点上执行的命令。
- try end:通知 try 阶段已经结束,本地事务检查版本是否变化、锁定相关的 key。
1 | func (coordinator *Coordinator) sendTry(peer string, cmdLines [][][]byte) redis.Reply { |
本地事务
本地事务就是分布式事务在节点上的实际执行者,下面是本地事务的定义:
- watchedKeys 对应 try watched 命令,记录 watch 时的版本,用于在执行时进行版本比较。
- cmdLines 对应 try xxx 命令,记录当前节点的本地事务中,包含的所有需要执行的命令。
1 | // Transaction TCC本地事务 |
Try
在收到 try end 命令后,表明 try 阶段已经结束,此时本地事务:
- 锁定需要读写的 key。
- 在在时间轮中添加任务, 自动回滚超时未提交的事务。
- 读取版本是否变化,如果有变化则返回错误。
1 | // Try TCC事务的结束try阶段,锁定key |
Commit
在本地事务收到 commit 命令后,会执行命令,(如果开启原子事务)并记录 undolog。
1 | // Commit TCC事务的commit阶段 |
Cancel
在收到 cancel 命令后,(如果开启原子性事务)会执行 undo log 进行回滚。
1 | // Cancel TCC事务的cancel阶段 |