zoukankan      html  css  js  c++  java
  • Apache Ratis的Ratis Server主从同步机制

    前言


    前段时间,笔者讲述了关于Raft协议内部投票过程的一个具体实现,实现过程取自于Apache Ratis项目内部的代码。本文笔者将再来阐述Apach Ratis项目内部Ratis Server的主从服务同步机制。Ratis Server在经过Raft协议投票选举出Leader之后,是如何进行Leader、Follower间的数据同步的呢?更确切地来说,是如何保持主从之间数据的一致性的呢?

    主从服务间的数据同步常用作法


    这里我们所说的主从服务,它所指的是”有状态“的服务,并不是完全无状态只是为了临时快速切换的所谓的“主从服务”。对于这种“有状态”信息的服务,我们的目标是让这些“状态”信息及时同步到其它Follow的服务内。于是,我们可以想到以下一些同步方法:

    • 主服务直接同步状态信息到多个备服务中。这种方案的弊端在于主服务没有持久化未及时同步到Follow服务的状态信息,这会导致系统服务突然crash导致状态信息丢失的情况。
    • 主服务写出状态信息到外部存储中,由备服务再从外部存储中同步状态信息。这里外部存储的引入可以保证状态信息不丢失,但是此方案因为引入了外部存储的关系,在整个服务交互上会比第一种方案复杂一些。这种方案在实际工作的系统内经常能碰到,例如HDFS的QJM机制,还有例如其它一些存储系统的WAL机理等等。

    本文笔者将要阐述的Ratis Server间的主从同步在本质原理上也属于第二套方案,不过在里面额外引入了状态机的角色,状态机将会和WAL进行一些额外的交互操作,下面我们来了解这方面的主要内容。

    Ratis Server主从服务的状态同步机制


    状态机的原语定义


    对于存储系统的主从服务同步来说,我们所指的“状态”一致具体指的是其中元数据的一致性,例如文件,目录属性信息等等。对于这里的状态而言,就会有对应改变这个“状态”的transaction操作,在实际系统中比如客户端的一个个请求操作。

    因此状态机理论可以完全适用于我们当前的主从服务的同步机制,不过会有以下的原语定义:

    • 对于存储系统服务来说,它的StateMachine 内部维护State可以是一个文件map信息结构,包含了所有文件的元数据信息。当我们对这个map进行更新的时候,也就意味着我们将更新State从State1到State2。
    • 客户端的请求操作,对于StateMachine而言,则是一个log entry。不过只有被提交过的committed log,才能被apply到StateMachine中,然后进行State的改变。这里“被提交”的概念是指我的log entry已经被半数以上的Follower服务所接受并应用。

    Ratis Server内部角色服务


    下面我们来看Ratis Server内部服务的定义,如上文所介绍的,至少已经有2个角色,StateMachine和WAL(Transaction Log)。除此之外,还有以下的角色服务:

    • RetryCache,对于客户端而言,Ratis Sever内部有RetryCache,为了避免客户端发起重复的请求操作。
    • Raft Log,Raft Log可以理解为是Ratis Server的WAL,每次用户的操作会被转化为transaction log然后被写入到Raft Log中,如果log写满了,则会新创建Raft Log文件进行写入。
    • LogAppender,此角色服务是将Leader内最新的transaction log发送到远端的各个Follower服务中,并获取返回结果。然后及时更新Raft Log的commit index。
    • StateMachineUpdater,此角色根据Raft Log的commit记录,及时apply 最新committed的log entry到StateMachine中,然后purge掉commit index之前的log文件。同时它会定期给StateMachine做snapshot操作。StateMachineUpdater的功能有点类似于Checkpoint的角色功能。

    在Ratis Server现有的主从同步中,以上角色服务是按照如下图所示进行协调工作的:
    在这里插入图片描述

    上述过程的核心点在于StateMachine只会apply那些成功提交的transaction log,所以我们能够确保主从服务状态的一致性。

  • 相关阅读:
    mybatis批量处理sql
    jdbc连接数据库使用sid和service_name的区别
    js 监听浏览器刷新还是关闭事件
    websocket
    hutool java工具架包功能介绍
    SpringMvc+ajax 实现json格式数据传递
    springMVC form表单提交多个对象集合--使用ajax提交--前台json格式数据封装方法
    linux C之判断文件或目录是否存在 access函数
    Linux C -> symlink 和 readlink -> 符号链接
    linux c开发: 在程序退出时进行处理
  • 原文地址:https://www.cnblogs.com/bianqi/p/12183519.html
Copyright © 2011-2022 走看看