基于 Ractor 模型优化事务复制回放性能

一、背景

当备库回放事务时,多个互相不依赖的事务可以并发回放,本方法主要用于解决多个可并发回放的事务的并发回放问题。通过并发的多个扫描线程实现并发对事物回放队列进行扫描,生成多个可以并发回放的事物,并且通知回放线程进行并发的回放。

二、数据结构设计

备库的事物数据按照事物 ID 分段存储到备库的事物数据队列中,参考如下图 1;根据事物 ID 为 UUID 完全无序的特性,可以对 UUID 进行事物 ID 分段并发扫描。将事物 ID UUID 分段后,交给多个扫描线程协程,每个扫描线程负责某个 UUID 分区进行多个扫描线程并发扫描,扫描可回放的事物。

三、线程生命周期

当扫描线程发现可回放的事物后,会将事物 ID 加入 txnList 执行 enqueu 操作,加入事物 ID 后,扫描线程会执行 notify 操作,唤醒正在睡眠的回放线程进行事务回放操作,示意图参考如下图 2。

![图片](p3-juejin.byteimg.com/tos-cn-i-k3...

回放线程协程的生命周期如下如图 3,回放线程刚启动后处于睡眠状态,当有事务回放时,会被随机唤醒。被唤醒的回放线程协程会执行事务回放任务,并且清理事务的依赖关系。

当发现可回放的事务时,如果发现可回放的事务数等于 1,则由当前协程进行回放减少一次 CPU 切换的开销;当发现多余 1 个可回放事务时,回放线程协程会将除去第一个的可回放事务,加入 txnList 唤醒其他协程进行事务回放,以实现更好回放的并发性能。

四、并发切换问题

在采取了并发清理时,因为 CPU 切换的问题,需要处理重复发现的可回放事务,对重复发现相同的事务 ID 进行防御性幂等处理,如下图 4。因此,需要对每个可回放事务引入 txnIDSet 进行幂等处理。

五、如何判断回放是否结束

因为采取了并发扫描以及并发回放,所以需要在全部可回放事务全部回放结束后,结束回放的流程,在此给出回放结束的定义。

当可回放事务全部回放结束后,认为回放结束。可回放事务分为 3 类,过去发现的可回放事务/现在发现的可回放事务/将来发现的可回放事务。

过去发现的可回放事务都会被加入到 txnList 中,现在发现的可回放事务正在由回放线程进行回放,将来发现的可回放事务是由扫描线程扫描 UUID 进行发现的。

  • 过去发现的事务回放结束的条件为 txnList 为空;

  • 现在发现的事务回放结束的条件为所有的 workerStatus 总和为 0;

  • 将来发现的事务回放结束的条件为所有的扫描线程,GatherAll 扫描可回放事务无法发现。

六、性能调优

根据 CPU 数量,可通过动态调整扫描线程和回放线程的回放协程数量,以合理分配两组协程的负载。这样做可以充分利用多核处理器的性能,并提高系统的吞吐量和响应能力。

相关推荐
ROCKY_8171 小时前
Mysql复习(二)
数据库·mysql·oracle
问道飞鱼4 小时前
【知识科普】认识正则表达式
数据库·mysql·正则表达式
HaiFan.4 小时前
SpringBoot 事务
java·数据库·spring boot·sql·mysql
水根LP494 小时前
linux系统上SQLPLUS的重“大”发现
数据库·oracle
途途途途4 小时前
精选9个自动化任务的Python脚本精选
数据库·python·自动化
04Koi.5 小时前
Redis--常用数据结构和编码方式
数据库·redis·缓存
silver98865 小时前
mongodb和Cassandra
数据库
PersistJiao5 小时前
3.基于 Temporal 的 Couchbase 动态 SQL 执行场景
数据库·sql
上山的月5 小时前
MySQL -函数和约束
数据库·mysql
zhcf5 小时前
【MySQL】十三,关于MySQL的全文索引
数据库·mysql