• 长安链共识模块优化中的“精益求精”


    长安链在v2.3.0版本中对共识模块进行了优化,主要包括优化TBFT消息机制并将异步发送信息功能进行了拆分,独立设计了一致性引擎模块。优化后共识模块整体逻辑更清晰、共识更高效。

    TBFT消息机制优化背景

    在长安链的V2.3.0版本的TBFT共识算法中,我们对TBFT共识算法进行了重构,主要是增加了对TBFT消息的缓存。在V2.3.0之前的版本,当一个TBFT节点收到来自某个节点的消息(主要是proposal提案消息、prevote预投票消息、precommit投票消息),但是如果这个共识消息的高度比当前节点的状态要高,TBFT会判断当前的共识高度和共识消息的高度不匹配,就会丢弃掉该消息。这么可能导致的后果就是,在节点未来达成这个消息的高度的时候,它需要该共识消息,而由于之前已经丢弃掉了该共识消息,因此它还需要等待其他节点再次把该共识消息重新发送过来,导致占用不必要的网络通信。

    具体实现

    在长安链在V.2.3.0版本中,TBFT共识增加了一个MsgCache,用来缓存未来的共识消息,目前TBFT是缓存未来10个高度的TBFT消息。当TBFT节点收到来自某个节点的共识消息,判断共识消息的高度是否大于当前共识状态的高度,如果是未来10个高度以内的共识消息,则会放入到MsgCache中。当TBFT共识进入到新的高度的时候,会从MsgCache内获取当前共识高度缓存的proposal和投票(包括prevote投票、precommit投票),然后将提案和投票放入到TBFT共识的消息管道内,以便TBFT共识能够快速获取到当前共识状态所需要的消息。同时在每个新的高度,TBFT会更新MsgCache内的共识高度,每10个高度,会清理一次MsgCache内比当前共识高度低的不再需要的共识消息。

    流程图如下:

    点击放大查看图片

    实现方法如下:

     
    

    // ConsensusFutureMsgCache 缓存未来的共识消息
    type ConsensusFutureMsgCache struct{
    logger protocol.Logger
    sync.Mutex
    size uint64
    consensusHeight uint64
    cache map[uint64]*ConsensusFutureMsg
    }

    // updateConsensusHeight 更新共识高度,删除不再需要的共识消息
    func(cfc *ConsensusFutureMsgCache)updateConsensusHeight(height uint64);

    // addFutureProposal 添加未来的提案到cache
    func(cfc *ConsensusFutureMsgCache)addFutureProposal(logger protocol.Logger, validators *validatorSet,
    proposal *tbftpb.Proposal);

    // addFutureVote 添加未来的投票到cache
    func(cfc *ConsensusFutureMsgCache)addFutureVote(logger protocol.Logger, validators *validatorSet,
    vote *tbftpb.Vote);

    // getConsensusFutureProposal 从cache获取提案
    func(cfc *ConsensusFutureMsgCache)getConsensusFutureProposal(height uint64, round int32)*tbftpb.Proposal;

    // getConsensusFutureProposal 从cache获取投票
    func(cfc *ConsensusFutureMsgCache)getConsensusFutureVote(height uint64, round int32)*roundVoteSet;

     

    一致性引擎方案设计及其成效

    长安链PeerState模块异步发送共识过程中投票信息,并在其他节点未能成功收到投票造成状态落后时,异步补发投票信息。

    我们将异步发送信息功能进行拆分,独立设计一致性引擎模块。共识流程中会直接发送提案/投票等信息,当接收方出现状态落后时,一致性引擎用于补发状态。优化后,逻辑更清晰,并且通过主流程直接发送和消息类型拆分的方式,极大的提高了共识性能。

    需求描述

    序号

    需求

    1

    拆分出独立模块(ConsistentEngine),TBFT可以不依赖新模块(理想情况)独立运行,如果出现网络问题(如丢包),会出现共识过程卡住的问题。

    2

    ConsistentEngine辅助同步TBFT共识状态,避免出现共识过程卡住的问题。

    3

    监测其他节点状态,如果状态落后,推送新状态;

    自己状态落后不做处理(等其他节点推送新状态)。

    4

    ConsistentEngine可用于辅助同步MaxBFT共识状态。

    5

    ConsistentEngine支持注册、回调的方式与tbft模块交互。

    表1

    模块关系图

    点击放大查看图片

    如上图所示,TBFT和ConsistentEngine均为独立模块,两个模块共用相同内存空间存储自身状态。ConsistentEngine中会存储其他节点状态,通过定时器方式,触发状态检测,当发现其他节点状态落后时,发送所需下一状态,推动其他节点状态更新,保证共识正常。

    流程图

    Tbft-ConsistentEngine 交互流程

    点击放大查看图片

    如上图所示,一致性引擎的启动随TBFT一起启动,启动时会初始化并完成注册,初始化远端节点信息,开启广播。关闭时,在TBFT关闭前,先关闭全部广播器,然后关闭TBFT共识服务。运行过程中,共识进入新的高度,读取链配置,如果有验证者变更,则触发一致性引擎远端信息的更新。

    ConsistentEngine 流程

    点击放大查看图片

    发送端:运行后会为每个广播器创建定时器(当前仅使用TBFT状态广播器),当定时器到达定时时间(默认500ms),遍历所有远端节点共识状态,通过PreBroadcaster接口返回待发送消息,通过msgBus将待发送消息发送给接收方。全部消息发送后,重置定时器,等待下一轮消息同步。

    接收端:收到消息后,遍历消息解析器(当前仅使用TBFT状态解析器),解析消息后,将节点信息进行更新。

    接口设计

     
    

    // ConsistentEngine 一致性引擎,用于节点间(共识状态)信息同步
    type ConsistentEngine interface{

    // Start 启动一致性引擎
    // ctx 后续扩展用,启动失败返回error
    Start(ctx context.Context)error

    // Stop 停止一致性引擎
    // ctx 后续扩展用,,停止失败返回error
    Stop(ctx context.Context)error

    // AddBroadcaster 添加状态广播器(如一个tbft状态广播器)
    // id 广播器标识,需要保证唯一性
    // broadcast 广播器,需要用户自己实现(如:tbft广播器、maxbft广播器)
    AddBroadcaster(id string, broadcast StatusBroadcaster)error

    // UpdateNodeStatus 更新本地状态
    // id 节点标识,需要保证唯一性
    // node 需要更新的节点信息(包含节点状态,节点状态可以有多种)
    UpdateNodeStatus(id string, node Node)error

    // PutRemoter 添加节点
    // id 节点标识,需要保证唯一性
    // node 需要添加的节点信息(包含节点状态,节点状态可以有多种)
    PutRemoter(id string, node Node)error

    // RemoveRemoter 删除节点
    // id 节点标识,当节点不存在时返回错误消息
    RemoveRemoter(id string)error

    // RegisterStatusCoder 注册状态解析器
    // decoderType 解析器标识,需要保证唯一性
    // decoder 需要添加的解析器,由用户实现(如:tbft解析器)
    RegisterStatusCoder(decoderType int8, decoder Decoder)error

    // RegisterStatusInterceptor 注册过滤器
    // interceptorType 过滤器标识,需要保证唯一性
    // interceptor 需要添加的过滤器,由用户实现(如:tbft过滤器)
    RegisterStatusInterceptor(interceptorType int8, interceptor StatusInterceptor)error
    }

     
    

    // StatusBroadcaster 状态广播器
    // 由内部定时器触发广播
    // 根据LocalNodeStatus和RemoteNodeStatus当前状态,确认是否进行状态广播
    type StatusBroadcaster interface{

    // ID 广播器标识
    ID()string

    // TimePattern 状态广播触发模式
    // 返回触发间隔
    TimePattern()interface{}

    // PreBroadcaster 广播器,判断是否要发送消息
    // 返回广播器方法
    PreBroadcaster() Broadcast

    // Start 启动
    Start()error

    // Stop 停止
    Stop()error

    // IsRunning 获取运行状态
    IsRunning()bool
    }

     
    

    // Decoder 解析器
    type Decoder interface{

    // MsgType 解析器处理的消息类型
    MsgType()int8

    // Decode 解析器解析对应类型的消息,返回解析后数据对象
    Decode(interface{})interface{}
    }

    ConsistentEngine方案应用成效

    ConsistentEngine方案较PeerState方案在共识模块独立测试中,性能提升35.3%,具体信息如下:

    PeerState方案

    ConsistentEngine方案

    测试方法

    共识模块测试床

    共识模块测试床

    环境

    系统:macOS 12.5.1

    处理器:2.6 GHz 6核 Intel Core i7

    内存:16 GB

    系统:macOS 12.5.1

    处理器:2.6 GHz 6核 Intel Core i7

    内存:16 GB

    存储

    不启用

    不启用

    网络

    启用

    启用

    虚拟机

    不启用

    不启用

    验证

    不启用

    不启用

    WAL

    不启用

    不启用

    CTPS

    17W

    23W(提升35.3%)

    表2

    注:上图性能数据是共识模块独立测试的性能数据,不同于区块链性能数据。

  • 相关阅读:
    leetcode day12 二叉树的最大深度
    二、Node.js内置API(fs、path、http)
    为什么要写单测
    WebSocket: 实时通信的新维度
    作为“初学者”应该怎么上手力扣题
    跨平台应用开发进阶(三十):uni-app 实现视频直播
    SpringBoot SpringBoot 原理篇 3 核心原理 3.2 启动流程【1】
    ChatGPT总结(持续更新)
    ZYNQ双核启动和固化步骤
    图书预约管理系统的设计与实现
  • 原文地址:https://blog.csdn.net/weixin_55760491/article/details/128205188