只读落后自愈技术原理
GaussDB(for MySQL)是存储计算分离架构的云原生数据库,只读节点和主节点共享底层的存储数据。为了保证内存中的缓存数据的一致性,主节点与只读节点通信后,只读节点需要从Log Stores中读取主节点产生的redo来更新内存中的缓存数据。
主节点与只读节点的通信
虽然主节点与只读节点共享底层存储数据,但是主节点和只读节点之间仍需要进行信息通信。
- 主节点发送到只读节点内容:redo的描述信息,比如redo日志的最新lsn和内部读取日志的接口信息。
- 只读节点发送到主节点内容:
- 只读节点当前的视图,视图中保存了当前的事务列表,主节点根据各个节点的视图信息,才能对undo日志进行purge清理。
- 只读节点的recycle_lsn,recycle_lsn表示只读节点读取数据页的最小lsn。对于只读节点来说,读取的数据页的lsn不会小于recycle lsn,主节点收集各个只读节点的recycle_lsn,来评估清理底层redo日志的位点。
- 各个只读节点的基本信息如节点ID, 最新消息更新时间戳等,用来主节点对只读节点的管理。
进行通信后,只读节点才能读取redo日志,进行数据可见性的更新。
只读延迟的计算
只读延迟是指在主节点更新数据后,在多少时间后能在只读节点得到这个最新数据。 只读节点读取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的推进
根据延迟的计算方式,产生延迟的关键点在于只读节点visible lsn推进速度的快慢。
只读节点推进visible lsn的工作流程如下:
- 只读节点通过与主节点通信,获取最新redo的lsn和其描述信息。
- 从log store中读取redo日志到内存中。
- redo 日志解析处理,失效内存中相关元数据信息、更新内存中的视图信息等。
- 推进visible lsn。
在大多数情况下,主节点和只读节点时延很小,但是在一些特殊场景下如主节点做大量DDL时候,可能会产生较大的只读延迟。
自愈策略
如果产生较高的只读延迟,那么用户就无法从只读节点获取最新的数据,可能会对用户业务一致性产生影响,所以当前数据库的策略是如果只读延迟超过默认值30s,只读节点会重新启动,重启后的只读节点会从存储中读取最新数据,不会产生延迟。