OpenGauss(OG)的gs_ctl build 对应 PG的pg_rewind,OG没有pg_rewind这个可执行程序,但是有pg_rewind.cpp这个文件,gs_ctl build会调用pg_rewind.cpp中的gs_increment_build()。
在对Patroni的修改中,原pg_rewind的相关逻辑不再被调用,根据代码可知,只要在patroni.yml中设置use_pg_rewind为false,就能禁用Patroni中pg_rewind所有相关逻辑,而且OG也没有pg_rewind可执行程序(而是用gs_ctl build替代pg_rewind),这也是patroni判断是否禁用pg_rewind的充分条件。
patroni.yml

patroni/postgresql/rewind.py

禁用了原pg_rewind逻辑后,要增加opengauss的rewind逻辑,逻辑要实现下面的功能:
1、启动Patroni时,判断自己为备机后,做一次rewind(如果没有做过basebackup则做basebackup而不是rewind),如果集群中还没有主机,要推迟到下一个run_cycle循环中的follow做rewind,如果还没有,再推迟到下一个follow,直到集群中出现主机。
2、在运行过程中,备机发现主机改变了(集群中发生了主备切换),备机要做一次rewind。
3、备机发现opengauss崩溃退出,拉起opengauss前要做一次rewind。
4、做rewind时如果不成功,连续尝试3次,都失败后执行reinitialize(删除数据目录,做basebackup)。
5、执行rewind不另起一个线程,而是使用主循环线程。
patroni/ha.py:class Ha :def __init__()

patroni/ha.py:def load_cluster_from_dcs() 判断集群主节点的改变

patroni/ha.py:def _handle_opengauss_rewind_or_reinitialize() 尝试3次调用gs_ctl build做rewind,返回0认为成功,其它认为失败,如果3次都失败,则执行reinitialize,即删除datadir,执行basebackup。如果集群中没有主节点,则返回None,推迟到下一个follow中执行。

patroni/ha.py:def recover() 在recover中执行rewind,recover并非每次循环都会执行。当第一次启动、拉起opengauss时会执行recover,如果集群中还没有确定leader,则等待下一个循环执行。

patroni/ha.py:def follow() 在follow中执行rewind,follow每次循环都会执行。当集群的主节点发生改变(自动切换或手动切换)时,在def load_cluster_from_dcs()中self._opengauss_leader_changed被设为True,导致follow中执行rewind,执行成功后self._opengauss_leader_changed被设为False。

patroni/postgresql/rewind.py:def gsctl_build() 生成gs_ctl build命令并且调用,并获得返回值,返回0表示执行成功,需要判断一下,如果自己是主节点,则不执行gs_ctl build直接返回成功。
注意,这些逻辑的原则是:避免rewind重复执行,和避免在该执行rewind的时候未能执行。
通过patroni.yml中新增参数:use_rewind来控制是否使能opengauss的rewind逻辑。

为这个参数新增一个openguass段,是因为在Patroni代码中,将第一层参数识别为字典,所以布尔类型的参数最好不要放在第一层。
