文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

关于多写入点数据库集群的一些想法

2024-12-14 00:22

关注

[[422305]]

传统的 Basic Paxos 常常被误认为是 Leader-less 的, 也即多主, 但 Basic Paxos 只能用于确定一个实例的共识, 真正落地还需要结合日志复制状态机, 如果复制组(多节点)不指定 Leader 的话, 那么就会出现争取同一个位置的日志的情况, 也就是在尝试达成这个位置的日志的共识时出现活锁. 这种多节点争取同一个位置的情况, 在实践上将导致系统不可用, 因为, 通常自称采用 Paxos 的多副本数据库系统, 依然要显式指定 Leader, 并不是真正 Leader-less 的.

借鉴 vector 时钟和多复制组的思路(如 Multi Raft Group), 是可以避免多主冲突的, 因为, 不同的节点作为各自组的 Leader, 分别写入不同的日志序列, 也就完全没有争取同一个位置的日志而导致冲突了.

以一个3节点的集群来举例, 通过预先配置强制指定各为其主, 结构为:

 

有复制组 G1, 成员节点是 {A, B, C} , 其中节点 A 是主. 类似的, 复制组 G2 和 G3 的主是 B, C. 当客户端请求不同节点时, 将日志写入不同复制组的日志序列, 因此不会产生冲突.

某一时刻, 所有节点的状态是:

 

这个状态表明, 复制组 G1 累计有 6 条日志, 复制组 G2 是 1 条, 复制组 G3 是 2 条.

到目前为此, 似乎一切顺利, 写入没有冲突, 还能通过复制组形成多副本. 但是, 现实不是这样的, 一个只能写入的数据库几乎没有任何用处, 数据库必须支持读取, 所以, 日志复制状态机架构必须有状态机, 也即这 3 条日志序列必须在所有节点 Apply 到各节点的状态机实例中.

最简单的方法是在各个节点上把 3 条日志序列合并成(Merge)一条日志序列, 通过某种算法保证所有节点上的合并结果一定是相同的, 例如按时间戳排序, 这样才能保证状态机一致(相同).

但是, 节点不能只依赖自己本地的 3 条日志序列合并, 在每一次合并时, 它需要获取其它复制组的最新信息, 判断自己本地的日志序列是不是足够新. 自己作为 Leader 的那一条序列, 当然自己能确定, 但其它两条不能, 需要询问其它节点, 不能定死询问 Leader, 因为需要容忍某个复制组的 Leader 宕机的情况.

所以, 针对其它复制组, 采取 Read Index 逻辑, 可以判断是否最新. 并且在其它组 Leader 宕机的情况下, 将对应的日志序列从其它 Follower 那里补齐.

日志序列中可能包含非幂等的指令, 通过加入时间戳之后, 非幂等的指令可以变成幂等的.(需要文章论证). 以一个 key 为例, 状态机中的 key-value 带有初始化时间戳和最新更新时间戳 {reset_time, modify_time} . 当收到一条 incr 指令时, 指令中带有时间戳, 与 key-value 中的 meta 信息比对之后, 就能知道 Apply 算法.

 

  1. if key.reset_time < op.time { 
  2.     value += 1 
  3. else { 
  4.     // 忽略在初始化之前的指令 

例如, 在 A 节点上针对 key 执行了 set 操作, 便会复位其 reset_time, 之后, 再收到其它节点的更早的 incr 指令时, 这个 incr 指令就不能修改状态机了, 因为这个指令发生在复位之前.

各个节点的系统时钟不同步没关系, 因为一致性与系统时钟没有必然联系(需要文章论证). 只要确保所有节点最终的结果是一致的(相同)的就行. 不要让 A 节点先执行 set 再执行 incr, 而 B 节点先执行 incr 再执行 set 这种情况出现. 在这个例子中, 从上帝视角知道 incr 在 set 之前, 所以, A 节点先执行 set, 然后遇到 incr 指令时会忽略.

上面的时间戳比较要求不同的节点产生的时间戳不能相同, 可以把节点ID当作时间戳的最低位, 避免两个时间戳相同.

对于 incr 操作, 初始化比较简单, 但是, 对于 pop 这种非幂等性的操作, 并不是初始化, 很难解决. 本质上, 是一种回滚操作, 能实现, 但成本太大, 要讨论起来真是够多的.

不同的节点收到不是自己负责的日志序列的延迟不一定, 但是, 我们又不能等确保全部日志序列都收到之后再 Apply, 虽然等全部日志序列都到齐之后再 Apply 可以不需要回滚操作, 但等待行为不能容忍宕机(CAP 理论).

总结起来, 就是 没有银弹 . vector 时钟看起来很美好, 但日志序列之间的相互依赖问题, 要么通过停止等待来解决, 要么通过回滚操作来解决, 否则无法保证多副本一致(相同). 但是, 某些操作的回滚成本太大.

注: 有一种技术叫 CRDT, 思想类似, 但是上面讨论的问题依然存在.

考虑过这个问题:

这时, C 恢复, 那条日志得以复制出去, 这时, A 和 B 需要回滚, 然后重新合并, 再 Apply.

如果 C 在恢复之后, 给那条日志赋予新的时间戳, 那么也会有一种场景(C 宕机前日志已经复制出去了, 但它还没知道结果), 同样需要回滚, 因为别的节点可能已经 Apply 过那条日志了.

来源:idea's blog内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯