本文主要介绍亚信安慧AntDB数据库的分布式架构下的特有进程之snapshot sender进程的设计,与snapshot receiver进程是一对,也是分布式架构的核心进程之一。
进程简介
与Snapshot Receiver进程相对应,该进程的作用从整体上看也只包含两个方面:
-
同步/广播快照,作为通信的server端
-
同步/广播事务号,同样也是server端
与此同时,该进程只会出现在gtm主节点上,这里特别强调,gtm的备节点上是没有该进程的,高可用切换以备提升为主,会自动拉起该进程。
进程的内存结构
该进程在物理上并没有特别的文件存储,进程启动之时会申请一起共享内存,大部分数据都存储在这部分内存之中。
内存结构名为SnapSenderData,代码内通常以SnapSender指针来访问这部分内存,完整的结构体定义较为琐碎,为了便于读者理解,这里仅挑选部分重要的内容给出说明,完整的定义参见源码文件(src/backend/replication/snapsender.c):
-
mutex:访问这部分共享内存时要加的
-
gxid_mutex:访问事务号成员时要加的锁
-
state: 标记所有cn节点是否都正常连接上
-
dn_conn_state:标记所有dn节点是否都正常连接上
-
cur_cnt_assign:gtm本节点申请的活跃事务号个数
-
xid_assign[MAX_CNT_SHMEM_XID_BUF]:gtm本节点申请的活跃事务号列表
-
cur_cnt_complete:gtm本节点结束的事务号个数
-
xid_complete[MAX_CNT_SHMEM_XID_BUF]:gtm本节点结束的事务号个数
-
xcnt:整个集群活跃的事务个数
-
xip[MAX_BACKENDS]:整个集群活跃事务号列表
-
latestCompletedXid:当前集群内最大的已完成的事务号
与Snapshot Receiver进程有所区别的是,除了共享内存之外,还有几个私有内存区域,首先是3个数组:
图1:私有内存区域
其次是client结构体,与集群内每个节点(gtm的pgxc_node表内记录的cn、dn主节点)相对应,每个节点在sender进程内都会有一个client对象:
图2:client结构体
除此之外还有2个列表,会用于更新上述client对象内的is_dn属性:
-
dn_master_name_list
-
cn_master_name_list
进程的通信协议
Snapshot sender进程的通信与snapshot receiver进程是相对应的,sender作为server端,响应receiver侧发来的各种请求,反馈相对应的消息,同时兼具广播给所有receiver进程的能力,可以结合《分布式架构剖析之snapshot receiver进程》这篇文章一起理解。
下面逐个介绍sender进程的通信逻辑:
-
消息‘Q’
建连成功之后,receiver那边通过walrcv_startstreaming发来请求,这是建连之后的第一个消息,这个消息会有初始化client对象处理receiver上报的残留2pc,并同步最初的快照等一系列动作,这些都作为异常场景的一部分,具体细节留待下次专题分享。但是正常情况下,这个‘Q’里面没有残留,也没有快照需要同步,所以大部分的逻辑会直接跳过。
-
消息‘a’
广播事务号,其接口是SnapSenderTriggerAssingAndFinishList,大致处理步骤如下:
1、从下面2个地方确认是否需要广播,如果任意一个数组内有值,那就需要广播:
(1)SnapSender->xid_assign:有值表示gtm本地申请了事务
(2)assign_xid_array:有值表示有cn/dn节点申请了事务号
2、合并上述2个数组的内容,调用ProcessShmemXidMsg接口进行广播:
(1)遍历sender内所有的client对象
(2)判断client的状态,如果不是streaming就跳过
(3)client大概率就是挂掉的节点,不能进行广播
(4)构建一条a消息,把事务号列表写入待广播的buffer
(5)通知client广播给对应的receiver进程
(6)如果广播失败,把对应的client状态更改为exiting,表示这个节点down了,会有别的地方去处理down掉的client
3、清空1里面的两个数组
-
消息‘g’
当有其他节点申请事务号时,gtm负责完成事务号的分配,当把事务号反馈给申请节点时,会封装这个‘g’消息,其接口是SnapSenderProcessAssignGxid,大致处理步骤如下:
1、首先从消息流取出procno,这个后续反馈的时候需要一并打包
2、调用GetNewTransactionIdExt函数获取下一个事务号
3、将新获取的事务号放入对应的client->xid内
4、将新获取的事务号放入assign_xid_array数组
5、set latch,sender的latch事件会触发a消息和c消息,即广播申请完成的事务号
-
消息‘c’
与a消息有点类似,这里广播的是结束的事务号,其接口是SnapSenderTriggerAssingAndFinishList,大致处理步骤如下:
1、从下面2个地方确认是否需要广播,如若任意一个数组内有值则就表示需要广播
(1)SnapSender->xid_complete:有值即表示有gtm本地的事务结束
(2)finish_xid_array:有值即表示有cn/dn节点的事务号结束
2、合并上述2个数组的内容,调用ProcessShmemXidMsg接口进行广播
(1)遍历sender内所有的client对象
(2)判断client的状态,如果不是streaming就跳过
(3) client大概率就是挂掉的节点,不能进行广播
(4)构建一条c消息,把事务号列表写入待广播的buffer
(5)通知client广播给对应的receiver进程
(6)如果广播失败,则把对应的client状态更改为exiting,表示这个节点down了,会有别的地方去处理down掉的client
3、清空1里面的两个数组
-
消息‘f’
处理receiver进程发来的结束事务的请求,其接口是SnapSenderProcessFinishGxid,处理步骤大致如下:
1、从消息流里拿到xid和procno
2、从SnapSender->xip里面删除这个事务号,同时SnapSender->xcnt同步减1,即把完成的事务号从集群活跃事务列表内清除
3、从xid_xact2pc_array数组里面删除这个事务号(在有的情况下)
4、从对应client->xid里面删除这个事务号,如果删除成功了(即client->xid里面有值),把这个事务号放入finish_xid_array数组,后续c消息会处理这个数组
-
消息‘s’
同步快照数据给receiver进程,其接口是SnapSenderSendInitSnapShot,触发s消息的行为有2处,它们分别是:
1、每次‘Q’消息的时候,如果所有的cn、dn都正常连接到sender,并且adb_check_sync_nextid(为HA切换单独保留的参数,非HA切换状态恒为true)参数为true,就会触发一次同步快照
2、每次唤醒等待中的节点时,就会触发一次同步快照,把快照同步给该节点
对于SnapSenderSendInitSnapShot函数的处理步骤,涉及包括Q消息上报的残留2pc,gtm自身的残留的2pc等这几部分内容,而这些同样也是异常处理的一部分,留待专题介绍。
-
消息‘h’
心跳处理,其接口是snapsenderProcessHeartBeat,包括以下2个部分:
1、根据各个节点上报来的xmin,更新sender这边对应的client里面的global_xmin,然后重新获取gtm本地的xmin,最后根据整个集群的xmin得到最终的xmin,并更新到SnapSender->global_xmin上
2、把最终的xmin和时间戳封装,反馈给receiver那边
-
消息‘u’
同步nextFullXid给所有节点,其接口是snapsenderUpdateNextXidAllClient,处理步骤如下:
这个u消息目前仅会在Q消息里面触发,每当有receiver进程连上,就把其上报的nextFullXid广播,日常情况下nextFullXid的更新是融合在receiver的a消息内一并进行更新的。
进程的工作主流程
Snapshot sender进程整体上同其他辅助进程相类似,启动之后会处于一个无限循环之中,不断监听各种事件和信号,笔者整理了一份流程图,帮助读者理解,如下图所示:
图3:snapshot sender进程工作主流程图
上述流程图对应的既是SnapSenderMain函数,又是snapshot sender进程的主函数,之前的各种消息处理都是从这里开始的,想深入理解各种细节的读者可以从这里入手。
小结
本文介绍了snapshot sender进程在正常情况下的处理逻辑,辅以snapshot receiver进程的配合,二者共同完成了分布式事务号、分布式快照的同步功能。
除了这两个进程之外,分布式架构里与事务相关的还有一个remote xact manager进程,这个进程与异常处理更是息息相关,在后续异常处理的专题文章内会有介绍。
关于亚信安慧AntDB数据库
AntDB数据库始于2008年,在运营商的核心系统上,服务国内24个省市自治区的数亿用户,具备高性能、弹性扩展、高可靠等产品特性,峰值每秒可处理百万笔通信核心交易,保障系统持续稳定运行超十年,并在通信、金融、交通、能源、物联网等行业成功商用落地。