dcf配置解析机制(元数据)
openguass的dcf是一个分布式一致性协议的实现(基于paxos协议,类似raft),能够实现分布式一致性数据传输和存储。
dcf通过传入json字符串来传递配置数据,如:
#1. 使能dcf特性开关
enable_dcf = on
#2. 当前节点id, 如果集群为3节点则每个节点可分别配置为1、2、3
dcf_node_id = 1
#3. 指定dcf数据目录
dcf_data_path = '/xxx/cluster/data1/dn1/dcf_data'
#4. 指定dcf集群配置信息,每个节点上dcf_config内容一致,其中配置的ip/端口专用于dcf节点间通信链路,注意与所有其他已使用的ip/端口不要配置冲突
dcf_config = '[{"stream_id":1,"node_id":1,"ip":"x.x.x.21","port":xx,"role":"LEADER"},{"stream_id":1,"node_id":2,"ip":"x.x.x.22","port":xx,"role":"FOLLOWER"},{"stream_id":1,"node_id":3,"ip":"x.x.x.23","port":xx,"role":"FOLLOWER"}]'
其中重点关注如下json字符串,
[{"stream_id": 1,"node_id": 1,"ip": "x.x.x.21","port": 1712,"role": "LEADER"
}, {"stream_id": 1,"node_id": 2,"ip": "x.x.x.22","port": 1713,"role": "FOLLOWER"
}, {"stream_id": 1,"node_id": 3,"ip": "x.x.x.23","port": 1714,"role": "FOLLOWER"
}]
dcf解析json字符串
dcf解析json字符串的流程大致如下:
在start的时候传入cfg_str,然后在parse_streams_cfg中解析到内存中。
json字符串是以json数组方式传入的,在解析前会判断是否是json数组,如果不是json数组就会报错退出。json数组里的对象就是stream,可以配置stream相关的信息,配置了多条流后会循环解析每个stream对象。
若dcf不是第一次启动,而是之前已经启动过并保留了元数据,则在执行md_init时会先读取元数据,若能读取到元数据,即使再传入json字符串也不会再解析。也就是说,只有在第一次启动dcf时才会解析json字符串,一旦启动过一次保存了元数据后就不会再解析传入的json字符串了。
对于单个stream调用parse_stream_cfg_single,解析结果保存到dcf_streams_t,其实就是放到内存里,最终放到全局变量g_metadata中。
typedef struct st_ptlist {pointer_t *items;uint32 capacity;uint32 count;
} ptlist_t;typedef struct st_streams_t {ptlist_t stream_list;
} dcf_streams_t;
在parse_stream_cfg_single中解析时,会解析如下配置:
- stream_id
- node_id
- ip
- port
- role
- weight
- group
- priority
除了stream_id外,其他参数都会保存到dcf_node_t里,
typedef struct st_dcf_node {uint32 node_id; // 节点idchar ip[CM_MAX_IP_LEN]; // 节点监听的ipuint32 port; // 节点监听的端口dcf_role_t default_role; // 节点默认角色uint32 voting_weight; // 投票的权重uint32 group; // 分组iduint64 priority; // 优先级
} dcf_node_t;
都解析成功后会将这些参数添加到stream里,
add_stream_member(streams, stream_id, &node_info);
dcf最多支持64条流,在添加时会对stream_id进行校验,节点数最多支持256个,会对node_id校验,voting_weight与node_id对应,也不能超过256.
在添加流之前还会确认这条流是否存在,如果流已经存在则无法添加成功,确认流存在后还会确认节点是否已经在这条流里面了。即流已经存在并且节点已经在这条流里面了是无法添加流成功的。
if (stream_isexists(stream_list, stream_id)) {if (MD_GET_STREAMS_NODE(stream_list, stream_id, node_id) != NULL) {return CM_TRUE;}}
最终所有的流都被保存到了全局静态变量g_metadata的streams链表里,streams前面已经列举过。
typedef struct st_dcf_meta {latch_t latch;meta_status_t status;uint32 current_node_id;dcf_node_t* all_nodes[CM_MAX_NODE_COUNT];dcf_streams_t* streams;char* buffer;uint32 checksum;
} dcf_meta_t;static dcf_meta_t g_metadata;
按照当前分析来看,一个节点可以有多条流。比如json字符串配置成这样也是可以的,
[{"stream_id": 1,"node_id": 1,"ip": "127.0.0.1","port": 1712,"role": "LEADER"
}, {"stream_id": 1,"node_id": 2,"ip": "127.0.0.1","port": 1713,"role": "FOLLOWER"
}, {"stream_id": 2,"node_id": 3,"ip": "127.0.0.1","port": 1714,"role": "FOLLOWER"
}]
到这里json字符串就被解析到dcf进程中了,这里其实就是解析到了stream的配置。