只读落后自愈技术原理
TaurusDB是存算分离架构的云原生数据库,只读节点和主节点共享底层存储数据。为了保证数据缓存的一致性,主节点与只读节点每次通信后,只读节点会从存储中读取主节点产生的redo log来更新数据缓存。由于网络波动或者节点繁忙等原因,只读节点相比主节点会有较高的数据缓存延迟,当延迟超过一定阈值时,只读节点将自动重启,以保证用户从只读节点能够读取最新的数据。
本文将详细解释只读节点落后并自愈重启背后的技术原理。
主节点与只读节点之间的数据同步机制

虽然主节点与只读节点共享存储数据,但是主节点和只读节点之间仍需要定期通信,保证只读节点的数据缓存能够与主节点保持同步。
如上图显示了主备通信与数据同步的机制:
- 主节点写完日志后会推进flush_to_disk_lsn(表示主节点数据可见的最新位点),主节点在往存储层(日志池、页面池)写入Redo Log时,也会定期向只读节点发送增量日志Redo Log的元数据消息,包括Redo Log对应的最新的flush_to_disk_lsn、读取日志的接口信息等。
- 只读节点获取主节点发送的消息后,会从日志池读取增量日志后推进visible_lsn(表示只读节点数据可见的最新位点),此时相关的数据缓存将失效。若只读节点的visible_lsn与主节点的flush_to_disk_lsn相等,说明没有主备时延,只读节点没有产生延迟。若只读的visible_lsn小于主节点的flush_to_disk_lsn,说明当前只读落后主节点,只读节点产生了数据延迟。
- 只读节点会向主节点返回消息包,包含的内容如下:
- 视图:视图中保存了只读节点当前的事务列表,主节点根据各个节点的视图信息,才能对undo日志进行purge清理。
- recycle_lsn:表示只读节点读取数据页的最小lsn。对于只读节点来说,读取的数据页的lsn不会小于recycle lsn,主节点会收集各个只读节点的recycle_lsn,来评估清理底层Redo Log的位点。
- 只读节点的基本信息:包括节点ID, 最新消息更新时间戳等,用来主节点对只读节点的管理。
- 若主节点或者只读节点的数据缓存失效,则主节点和只读节点查询时将分别从页面池获取页面。
只读延迟的计算
只读延迟是指在主节点更新数据后,在多少时间后能在只读节点得到这个最新数据。 只读节点读取redo日志进行缓存数据更新,对应的redo日志的lsn,称为visible lsn,表示只读节点能读取数据页的最大lsn。对于主节点来说,每更新或者插入一条数据产生的最新redo日志的lsn为flush_to_disk_lsn,表示主节点能访问的数据页的最大lsn。只读延迟其实就是只读节点visible lsn相比于主节点flush_to_disk_lsn的延迟,举个例子,比如t1时刻:主节点flush_to_disk_lsn=100, 只读节点visible lsn=80, 经过一段时间只读节点回放redo日志后,t2时刻:主节点 flush_to_disk_lsn=130,只读节点visible lsn=100。那么此时我们可以计算出只读延迟为:t2-t1,因为经过t2-t1的时间后只读节点才能读取主节点t1时刻的数据。
根据延迟的计算方式,产生延迟的关键点在于只读节点visible lsn推进速度的快慢。在大多数情况下,主节点和只读节点时延很小,但是在一些特殊场景下如主节点做大量DDL时候,可能会产生较大的只读延迟。
自愈策略
如果产生较高的只读延迟,那么用户就无法从只读节点获取最新的数据,可能会对用户业务一致性产生影响,所以当前数据库的策略是如果只读延迟超过默认值30s,只读节点会重新启动,重启后的只读节点会从存储中读取最新数据,不会产生延迟。