
# 只读落后自愈技术原理
#### 操作场景
TaurusDB是存算分离架构的云原生数据库，只读节点和主节点共享底层存储数据。为了保证数据缓存的一致性，主节点与只读节点每次通信后，只读节点会从存储中读取主节点产生的redo log来更新数据缓存。由于网络波动或者节点繁忙等原因，只读节点相比主节点会有较高的数据缓存延迟，当延迟超过一定阈值时，只读节点将自动重启，以保证用户从只读节点能够读取最新的数据。
本章节将详细解释只读节点落后并自愈重启背后的技术原理。
#### 主节点与只读节点之间的数据同步机制
图1主备通信与数据同步原理图   
![](https://support.huaweicloud.com/kerneldesc-taurusdb/figure/zh-cn_image_0000002352016809.png "点击放大")
虽然主节点与只读节点共享存储数据，但是主节点和只读节点之间仍需要定期通信，保证只读节点的数据缓存能够与主节点保持同步。
如上图显示了主备通信与数据同步的机制：
1. 主节点写完日志后会推进flush_to_disk_lsn（表示主节点数据可见的最新位点），主节点在往存储层（日志池、页面池）写入Redo Log时，也会定期向只读节点发送增量日志Redo Log的元数据消息，包括Redo Log对应的最新的flush_to_disk_lsn、读取日志的接口信息等。
2. 只读节点获取主节点发送的消息后，会从日志池读取增量日志后推进visible_lsn（表示只读节点数据可见的最新位点），此时相关的数据缓存将失效。若只读节点的visible_lsn与主节点的flush_to_disk_lsn相等，说明没有主备时延，只读节点没有产生延迟。若只读的visible_lsn小于主节点的flush_to_disk_lsn，说明当前只读落后主节点，只读节点产生了数据延迟。
3. 只读节点会向主节点返回消息包，包含的内容如下：
   - 视图：视图中保存了只读节点当前的事务列表，主节点根据各个节点的视图信息，才能对undo日志进行purge清理。
   
   - recycle_lsn：表示只读节点读取数据页的最小lsn。对于只读节点来说，读取的数据页的lsn不会小于recycle lsn，主节点会收集各个只读节点的recycle_lsn，来评估清理底层Redo Log的位点。
   
   - 只读节点的基本信息：包括节点ID, 最新消息更新时间戳等，用来主节点对只读节点的管理。
    
4. 若主节点或者只读节点的数据缓存失效，则主节点和只读节点查询时将分别从页面池获取页面。
 
#### 只读延迟的计算
只读延迟是指在主节点更新数据后，在多少时间后能在只读节点得到这个最新数据。 只读节点读取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时候，可能会产生较大的只读延迟。
#### 自愈策略
如果产生较高的只读延迟，那么用户就无法从只读节点获取最新的数据，可能会对用户业务一致性产生影响，所以当前数据库的策略是如果只读延迟超过阈值（innodb_replica_max_delay，默认30s），只读节点的进程会秒级重新启动，进程重启后的只读节点会从存储中读取最新数据，不会产生延迟。
#### 常见问题
#### 只读重启对业务有什么影响？
重启时间一般在10s内，重启只读节点时，少数正在执行还未返回结果的SQL语句会失败，重试即可成功。
#### 除了重启之外，是否有其他方法能解决只读落后问题？
- 如果希望减少频繁重启，可以在管理控制台上调大innodb_replica_max_delay参数值，以避免在压力过大时只读节点过快触发落后自愈机制。通常不建议调大此参数，因为高时延可能会影响只读节点业务的数据一致性，需提前确认业务能否接受延迟增加。如需修改参数值，请参考[修改TaurusDB实例参数](https://support.huaweicloud.com/usermanual-taurusdb/taurusdb_configuration.html)。
- 如果实例规格较小，建议[扩大实例规格](https://support.huaweicloud.com/usermanual-taurusdb/taurusdb_03_0092.html)。
- 如果读压力较大，建议[增加只读节点](https://support.huaweicloud.com/usermanual-taurusdb/taurusdb_03_0111.html)分摊读压力。
 
