Apache Seata Raft模式配置中心

本文来自 Apache Seata官方文档,欢迎访问官网,查看更多深度文章。
本文来自 Apache Seata官方文档,欢迎访问官网,查看更多深度文章。

Apache Seata Raft模式配置中心


title: Seata Raft模式配置中心
author: 蒋奕晨-清华大学,Seata 开源之夏学生参与者
description: 在本文中,我将分享基于Raft和RocksDB设计的Seata配置中心和使用方式。
date: 2024/09/19
keywords: [seata,分布式事务,配置中心,Raft,RocksDB]

1. 项目背景

目前seata支持丰富的第三方配置中心,但是考虑使用的便捷性同时为了降低使用seata的门槛,在seata-server利用现有的sofa-jraft+rocksdb构建一个配置中心功能,seata-client直接与seata-server通信,获取seata相关的配置,不需要再去第三方配置中心读取,实现配置中心自闭环。

2. 设计说明

2.1 配置中心

在现有的第三方配置中心实现中,Client端和Server端对于配置中心是解耦的,Client端和Server端直接通过Configuration实例获取配置项,且Configuration对于Client端和Server端的初始化行为是一致的,都是先连接到配置中心中间件然后获取配置,以及添加监听器等。
在这里插入图片描述

当使用Raft的实现配置中心后,由于所有的配置项信息是保存在Server端的,因此初始化Configuration实例时对于Client端和Server端的行为是不一致的。

此外为保证和原来配置中心的逻辑相同,Client端和Server端获取配置项依旧统一从RaftConfiguration实例中获取,不直接和RocksDB进行交互。

在这里插入图片描述

在这里插入图片描述

RaftConfiguration分为Server端和Client端,按照启动环境返回不同配置实例。

public class RaftConfigurationProvider implements ConfigurationProvider {
    @Override
    public Configuration provide() {
        String applicationType = System.getProperty(APPLICATION_TYPE_KEY);
        if (APPLICATION_TYPE_SERVER.equals(applicationType)){
            return RaftConfigurationServer.getInstance();
        }else{
            return RaftConfigurationClient.getInstance();
        }
    }
}

@SpringBootApplication(scanBasePackages = {"org.apache.seata"})
public class ServerApplication {
    public static void main(String[] args) throws IOException {
        System.setProperty(APPLICATION_TYPE_KEY, APPLICATION_TYPE_SERVER);
        // run the spring-boot application
        SpringApplication.run(ServerApplication.class, args);
    }
}

2.2 配置存储模块

在这里插入图片描述

抽象设计

为了未来支持和拓展更多的KV内存键值对数据库(如LevelDB,Caffeine),现抽象一个ConfigStoreManager接口以及抽象类AbstractConfigStoreManager,提供如下公共方法:

  • Get:获取指定namespace,dataId中名为key的单一配置项
  • GetAll:获取指定namespace,dataId中全部配置项
  • Put:新增/修改指定namespace,dataId中某一配置项<key,value>
  • Delete:删除指定namespace,dataId中名为key的配置项
  • DeleteAll:删除指定namespace,dataId中全部配置项
  • Clear:清空所有配置
  • GetAllNamespaces:获取所有命名空间
  • GetAllDataIds:获取指定namespace下的所有配置dataIds

ConfigStoreManagerFactory、ConfigStoreManagerProvider.java:使用SPI机制实现的配置存储工厂类和提供者。

配置监听

Server端和Client端配置中心需要监听配置项的变化。

在Server端,由于配置本身存储在Server端,我们直接拦截配置变更的方法即可。我们在抽象接口中定义了addConfigListenerremoveConfigListener方法用户添加和删除配置监听器。监听的逻辑由具体的实现类负责。

RocksDBConfigStoreManager中,定义了notifyConfigChange方法来触发监听,当调用写相关操作时(如Put、Delete)触发该方法来通知配置的变更。从而触发回调事件通知Server端配置中心。

在Client端,我们定义了配置版本号长连接机制来实现配置的监听。具体的Client端在启动时,与Server建立长连接并定期刷新该连接。Server端内部维护一个watchMap存放所有客户端的监听信息。每当Raft状态机执行配置更新的操作会发送一个ApplicationEvent事件,该事件被ClusterConfigWatcherManager监听,从而通知watchMap中所有客户端配置变更。此外使用了配置版本号来优化实现,在建立长连接时,客户端需要传入版本号,当版本号低于Server端对应配置的版本号时直接返回最新配置。反之,若Server端配置版本号低于本地,则Client端认为该Server的配置已经过期(可能宕机或集群发生脑裂)会重试请求集群中其他的节点。

多租户方案

在Seata-Server端存放配置时,需要实现多租户的配置隔离,要求不同租户间的配置是相互独立、物理/逻辑上是隔离的。

首先调研了业内使用RocksDB的开源项目的实现,总结如下。

  1. JRaft,单RocksDB实例,两个列族,一个用来存Raft条目,一个用来存元信息。
  2. TiKV,两个RocksDB实例,分别为raftDB,kvDB。kvDB中使用了多个列族存放元数据,用户数据,锁数据等。
  3. Pika,为每个数据结构(String,Hash,List,Set,Zset等)创建了一个RocksDB实例,每个RocksDB实例分别用多个列族存储数据,比如Data、Meta

考虑到无法提前知道租户数量(无法在启动时创建指定数量的RocksDB),因此使用单个RocksDB实例,多列族存储。不同租户使用namespace区分,在Rocksdb中通过列族(ColumnFamily)进行逻辑隔离,一个namespace对应一个列族。列族相当于关系型数据库中表的概念。在配置的增删改查时指定namespace操作具体的列族,实现多租户的隔离。此外名为config_version的列族是内置的,用于对现有的配置进行版本号跟踪。
在这里插入图片描述

3. 使用方式

3.0 准备配置文件

首先准备好配置文件,具体可以参考:配置文件示例。
并将配置文件置于Seata server项目资源目录下。

3.1 Server端配置

application.yml 中加入Raft配置中心配置,其余配置参考

config:
  # support: nacos, consul, apollo, zk, etcd3, raft
  type: raft
  raft:
    db:
      type: rocksdb # db类型,目前只支持rocksdb
      dir: configStore  # db文件存储目录
      destroy-on-shutdown: false #应用关闭时是否清除db文件, 默认false
      namespace: 'default' # 命名空间
      dataId: 'seata.properties' # 配置文件id
  file:
    name: 'file' # 初始配置文件名

server:
  raft:
    group: default #此值代表该raft集群的group,client的事务分组对应的值要与之对应
    server-addr: 192.168.241.1:9091, 192.168.241.2:9091 ,192.168.241.3:9091 # 其他Raft节点的ip和端口,端口为该节点的netty端口+1000,默认netty端口为8091
    snapshot-interval: 600 # 600秒做一次数据的快照,以便raftlog的快速滚动,但是每次做快照如果内存中事务数据过多会导致每600秒产生一次业务rt的抖动,但是对于故障恢复比较友好,重启节点较快,可以调整为30分钟,1小时都行,具体按业务来,可以自行压测看看是否有抖动,在rt抖动和故障恢复中自行找个平衡点
    apply-batch: 32 # 最多批量32次动作做一次提交raftlog
    max-append-bufferSize: 262144 #日志存储缓冲区最大大小,默认256K
    max-replicator-inflight-msgs: 256 #在启用 pipeline 请求情况下,最大 in-flight 请求数,默认256
    disruptor-buffer-size: 16384 #内部 disruptor buffer 大小,如果是写入吞吐量较高场景,需要适当调高该值,默认 16384
    election-timeout-ms: 1000 #超过多久没有leader的心跳开始重选举
    reporter-enabled: false # raft自身的监控是否开启
    reporter-initial-delay: 60 # 监控的区间间隔
    serialization: jackson # 序列化方式,不要改动
    compressor: none # raftlog的压缩方式,如gzip,zstd等
    sync: true # raft日志的刷盘方式,默认是同步刷盘

在Seata-Server下,需要一个初始配置文件作为Server端的配置文件(也就是上一步所述的配置文件),file.name配置项需要和该文件名保持一致。在Server初次启动时,会将该配置文件作为Raft配置中心的初始配置。目前支持的文件类型有:conf、yaml、properties、txt。

注意:Raft集群内节点的初始配置文件需要保持一致。

3.2 控制台配置管理界面

当Server端使用Raft模式的配置中心后,可通过在Seata Console中内置的配置管理页面,进行配置中心的管理。用户可以通过在该页面对存储于Seata-Server集群的配置进行增删改查,注意该操作是对于集群生效的,因此可以在集群中的任意节点进行修改,所有操作会通过Raft在集群内进行同步。

注意:该配置管理页面仅在配置中心为Raft模式下开启,对其他类型的配置中心不开放。

3.2.1 配置隔离

Raft配置中心提供了namespace命名空间的机制来实现多租户的配置隔离。不同namespace下的配置通过底层存储机制实现逻辑隔离。在同一namespace下可以有多套配置文件,不同的配置文件用dataId进行区分。一套配置以namespacedataId来唯一标识。

例如:

  • namespace=default(默认),dataId=seata.properties(默认)

  • namespace=dev,dataId=seata-server.properties,dataId=seata-client.yaml

  • namespace=prop,dataId=seata-server.properties,dataId=seata-client.txt

在这里插入图片描述

3.2.2 配置上传

在Sever启动时,Server端配置的初始文件会自动上传到配置中心。此外用户还可以通过点击"上传(Upload)"按钮上传配置文件到指定的namespacedataId。
当配置上传到Server端配置中心后,Client端就可以通过namespacedataId来获取具体的配置文件了。
在这里插入图片描述

目前支持上传的配置文件类型有:txt、text、yaml、properties类型。具体的配置文件可参考示例:配置文件示例

3.2.3 配置查询

选择namespacedataId后,可点击"搜索(Search)"按钮查询该配置下的所有配置项信息。

配置以配置项列表的形式呈现,每一行都代表一个配置项,以KeyValue展示。

在这里插入图片描述

3.2.4 配置删除

当不再需要某一套配置时,用户可以删除指定namespacedataId的配置数据。

注意该操作一旦完成,会清空该配置下的所有配置项信息,且无法恢复。请避免删除正在使用中的配置。

在这里插入图片描述

3.2.5 配置修改

在配置项列表中,用户可以对该配置下的某个配置项进行新增修改删除操作。操作成功后Server端和Client端会及时收到配置变更,从而获取到最新的值。

  • 新增:在当前配置下添加配置项

在这里插入图片描述

  • 修改:修改指定配置项的值。

在这里插入图片描述

  • 删除:删除指定的配置项

在这里插入图片描述

3.3 Client端配置

Client需要添加如下的配置项。其中raft.server-addr需要和Server端Raft集群的IP地址列表一致。

config:
    type: raft # Raft模式
    raft:
        server-addr: 192.168.241.1:7091, 192.168.241.2:7091 ,192.168.241.3:7091 # 配置raft相关元数据的获取地址
        username: 'seata' # 鉴权
        password: 'seata' # 鉴权
        db:
            namespace: 'default' # 命名空间
            dataId: 'seata.properties' # 配置文件Id

此外,client需要引入HttpClient依赖,用于通过Http请求向Seata-Server集群获取配置信息

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
</dependency>

配置完成后,Client应用启动时就会从raft.server-addr配置的Server中订阅并获取指定namespacedataId的配置,并通过监听机制在配置发生变更时获取获取最新配置。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/896648.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Vue是一套构建用户界面的渐进式框架,常用于构建单页面应用

学习总结 1、掌握 JAVA入门到进阶知识(持续写作中……&#xff09; 2、学会Oracle数据库入门到入土用法(创作中……&#xff09; 3、手把手教你开发炫酷的vbs脚本制作(完善中……&#xff09; 4、牛逼哄哄的 IDEA编程利器技巧(编写中……&#xff09; 5、面经吐血整理的 面试技…

HCIE-Datacom题库_11_IPsecVPN【17道题】

一、单选题 1.IPsecSA(SecurityAssociation&#xff0c;安全联盟)有两种生成方式&#xff0c;分别是手工方式和IKE自动协商方式&#xff0c;以下关于这两种方式的描述中&#xff0c;错误的是哪一项? 手工方式和IKE方式建立的SA都支持动态刷新 IKE方式建立的SA,其生存周期由…

传奇架设GEE引擎数据库服务器提示:拒绝未授权ip连接服务器的解决办法

今天一个新手GM遇到一个问题&#xff0c;他有一个GEE引擎的传奇版本&#xff0c;数据库服务器提示&#xff1a;拒绝未授权ip连接服务器&#xff1a;222.186.50.212、111.162.159.87 1.189.121.156、14.204.122.13、1.189.141.27等等&#xff0c;出于担心服务器是否有异常&#…

【VUE安装本地自定义capacitor插件以及打包成安卓APK过程】

capacitor插件创建使用过程 1. 初始化一个vue项目2.安装capacitor依赖3.自动化创建插件4. 实现功能后构建插件,插件目录下生成dist文件夹5. vue项目中安装插件6. vue项目中使用接口7. 构建vue项目8.构建为安卓项目9.打包APK1. 初始化一个vue项目 过程省略,本案例用的vue3+ty…

AI编译器与TVM

由于AI芯片的特殊性和高度定制化&#xff0c;为了兼容硬件的多样性&#xff0c;AI模型必须能被高效地映射到各种AI芯片上。AI编译器将深度学习框架描述的AI模型作为输入&#xff0c;将为各种AI芯片生成的优化代码作为输出。AI编译器的目标是通过编译优化的方法将深度学习框架产…

onlyoffice docker启用jwt并生成jwt

一、说明 本文是docker教程&#xff0c;linux/win的安装版本也类似&#xff0c;只需要修改配置文件中的secrt就可以了【Configuring JWT for ONLYOFFICE Docs - ONLYOFFICE】 二、正文开始 docker启动时候如果不想使用jwt&#xff0c;加上参数-e JWT_ENABLEDfalse就可以了&…

AI驱动的支持截图或线框图快速生成网页应用的开源项目

Napkins.dev是什么 Napkins.dev是一个创新的开源项目&#xff0c;基于AI技术将用户的截图或线框图快速转换成可运行的网页应用程序。项目背后依托于Meta的Llama 3.1 405B大型语言模型和Llama 3.2 Vision视觉模型&#xff0c;结合Together.ai的推理服务&#xff0c;实现从视觉设…

Centos7安装ZLMediaKit

https://github.com/ZLMediaKit/ZLMediaKit 一 获取代码 git clone https://gitee.com/xia-chu/ZLMediaKit cd ZLMediaKit git submodule update --init git submodule update --init 命令用于初始化和更新 Git 仓库中的子模块&#xff08;submodules&#xff09;。这个命令…

AI劳动力崛起:人将面临失业危机?

场景 第一眼看到这个网站的时候&#xff0c;AI员工官网&#xff08;好像是部署在美国&#xff09;&#xff0c;我觉得很好奇&#xff0c;真的可以让AI替代人类完成工作吗&#xff1f;替代到什么程度呢&#xff1f;能以自然语言直接驱动吗&#xff1f; 正好手上在做爬虫项目&am…

X射线衍射(X-ray Diffraction,XRD)小白版

文章目录 实验过程原理晶体构成X射线波长diffraction 干涉效应 Braggs Law晶体间距d散射角度θ半波长λ/2公式 公式名称由来应用设备 实验过程 In the X-ray experiment , a sample is placed into the center of an instrument and illuminated with a beam of X-rays. 在X射…

Debug-029-el-table实现自动滚动分批请求数据

前情提要 最近做了一个小优化&#xff0c;还是关于展示大屏方面的。大屏中使用el-table展示列表数据&#xff0c;最初的方案是将数据全部返回&#xff0c;确实随着数据变多有性能问题&#xff0c;有时请求时间比较长。这里做的优化就是实现列表的滚动到距离底部一定高度时再次请…

Python语法结构(二)(Python Syntax Structure II)

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:Linux运维老纪的首页…

Shell编程-函数

作者介绍&#xff1a;简历上没有一个精通的运维工程师。希望大家多多关注作者&#xff0c;下面的思维导图也是预计更新的内容和当前进度(不定时更新)。 我们前面学习了那么多命令&#xff0c;以及涉及到部分逻辑判断的问题。从简单来说&#xff0c;他就是Shell编程&#xff0c;…

在Xshell中查看日志文件详情

学习总结 1、掌握 JAVA入门到进阶知识(持续写作中……&#xff09; 2、学会Oracle数据库入门到入土用法(创作中……&#xff09; 3、手把手教你开发炫酷的vbs脚本制作(完善中……&#xff09; 4、牛逼哄哄的 IDEA编程利器技巧(编写中……&#xff09; 5、面经吐血整理的 面试技…

排序06 粗排模型

前面讲的多目标模型主要是用于精排。 粗排&#xff1a;尽量减少推理的计算量&#xff0c;牺牲准确性确保线上推理的速度足够快。 精排模型和双塔模型 中间的神经网络被多个任务共享 因此&#xff0c;前期融合模型用于召回&#xff0c;后期融合可以作为精排。 小红书粗排的三…

Shell案例之一键部署mysql

1.问题 我认为啊学习就是一个思考的过程&#xff0c;思考问题的一个流程应该是&#xff1a;提出问题&#xff0c;分析问题&#xff0c;解决问题 在shell里部署mysql服务时&#xff0c;我出现一些问题&#xff1a; 1.安装mysql-server时&#xff0c;没有密钥&#xff0c;安装…

PCL 基于中值距离的点云对应关系

目录 一、概述 1.1原理 1.2实现步骤 1.3应用场景 二、代码实现 2.1关键函数 2.1.1 获取中值距离筛选后的对应点对 2.1.2获取初始点对 2.1.3可视化 2.2完整代码 三、实现效果 PCL点云算法汇总及实战案例汇总的目录地址链接&#xff1a; PCL点云算法与项目实战案例汇…

NetSuite Transfer Order Saved Search的关键字段取值

针对于Transfer Order的Saved Search&#xff0c;我们最经常遇到的问题就是如何取到From Location&#xff0c;To Location&#xff0c;Quantity Fulfilled&#xff0c;Quantity Received这几个值。 原生的TO Register无法取到对应的信息&#xff0c;系统中也没有相应的标准Se…

关于vue3中如何实现多个v-model的自定义组件

实现自定义组件<User v-model"userInfo" v-model:gender"gender"></User> User组件中更改数据可以同步更改父组件中的数据&#xff1a; 1 父组件&#xff1a; <User v-model"userInfo" v-model:gender"gender">&…

[Unity Demo]从零开始制作空洞骑士Hollow Knight第十七集:制作第一个BOSS苍蝇之母

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、战斗场景Battle Scene相关逻辑处理 1.防止玩家走出战斗场景的门2.制作一个简单的战斗场景二、制作游戏第一个BOSS苍蝇之母 1.导入素材和制作相关动画2.制作…