Pika主从同步方案代码理解

背景

从节点收到 Bitop 这样的命令之后,要再次读取后面的 key 对应的内容进行运算,但是没法保证从节点使用这两个 key 读取到的内容就和 master 读到的内容一样,会导致 slave 得到的运算结果和 master 不一致(结果存进 dest_key,会导致主从的dest_key不一致)

命令:Bitop

命令介绍:对一个或多个保存二进制位的字符串 key 进行位元操作,并将结果保存到 destkey 上

1
2
3
4
5
6
7
8
9
redis> SET key1 "foobar"
OK
redis> SET key2 "abcdef"
OK
redis> BITOP AND dest key1 key2
(integer) 6
redis> GET dest
"`bc`ab"
redis>

修改方案

binlog 改成了一条 set 的 binlog,写成了: set key result_to_dest (注: result_to_dest就是后面使用后面的key得到的运算结果,也就是存到了第一个 key 中的内容)

修改代码前后对比

include/pika_bit.h +126

修改前:

截屏2023-07-05 14.43.28.png

修改后:

截屏2023-07-05 14.36.17.png

这里新增了 Bitop 拷贝构造函数和 DoBinlog 函数,以及需要新加的 value_to_dest 这个最终要写到 binlog 里面的参数,这里写了拷贝构造函数是因为使用默认的拷贝构造会导致多个 bitop 命令并发的时候,他们都用了同一个set 命令的实例,会有线程安全问题。DoBinlog 函数就是让程序执行 DoBinlog 的时候不使用基类 Cmd 的DoBinlog 而是使用子类覆写的 Binlog,current_key() 这个函数把需要锁的 key 传过来。

src/pika_bit.cc +211

修改前:

截屏2023-07-05 14.47.18.png

修改后:

截屏2023-07-05 14.48.11.png

这里在 Bitop 方法里面新增了 value_to_dest 这个参数,并且实现了 DoBinlog 这个函数,这里PikaCmdArgsType 的这个参数 set_args 本质是一个 std::vector<std::string>,这里我们把命令” set “,存储目标 “ dest_key “,运算结果” value_to_dest “放到这个 vector 里面,这里相当于 bitop 计算出来后的值当做 set 命令的 value, set_cmd_ 这个是一个指向 SetCmd 类的一个智能指针,然后进行初始化流程,最后调用基类 Cmd 的DoBinlog 完成流程

src/storage/include/storage/storage.h +223

修改前:

截屏2023-07-05 15.07.57.png

修改后:

截屏2023-07-05 15.09.54.png

src/storage/src/redis_strings.cc +291

修改前:

截屏2023-07-05 15.11.22.png

修改后:

截屏2023-07-05 15.12.47.png

这里多个 value_to_dest 参数,把 BitOpOperate 计算出来的值传给 value_to_dest

src/storage/src/redis_strings.h +35

修改前:

截屏2023-07-05 15.14.56.png

修改后:

截屏2023-07-05 15.15.59.png

相关 PR: #1658

相关 Issue: #1638