【学习Seata1.6源码#03】TC 集群具有高可用架构的秘密

简介: 【学习Seata1.6源码#03】TC 集群具有高可用架构的秘密

一、背景

TC 集群具有高可用架构,应用到集群是这样一个间接的关系:应用 -》事务分组 -》TC 集群,应用启动后所指定的事务分组不能变,可通过配置中心变更事务分组所属的 TC 集群,Seata 客户端监听到这个变更后,会切换到新的 TC 集群。

2Zmh5D.gif

本篇从源码梳理这个高可用能力是如何实现的。

二、环境配置

客户端配置使用nacos配置中心和nacos注册中心,

seata:
  enabled: true
  # Seata 应用编号
  application-id: seataclistock
  # Seata 事务组编号,用于 TC 集群名。该配置需要与服务端提到的group相对应,也需要与下面的相对应
  tx-service-group: tx_group_stock
  # 关闭自动代理
  enable-auto-data-source-proxy: false
  config:
    # support: nacos, consul, apollo, zk, etcd3
    type: nacos
    nacos:
      serverAddr: 
      namespace: seata # 需要与服务端添加的配置文件相同
      group: SEATA_GROUP_ROCKTEST
      username: seata
      password: seata
      data-id: seataClient.tx_group_busin.properties
  registry:
    # support: nacos, eureka, redis, zk, consul, etcd3, sofa
    type: nacos
    nacos:
      application: seata-server
      serverAddr: 
      namespace: seata  # 需要与服务端添加的配置文件相同
      group: SEATA_GROUP_ROCKTEST   # 需要与服务端添加的配置文件相同
      username: seata
      password: seata
复制代码

三、从配置中心获取TC集群

服务注册的能力要依赖配置中心,从nacos的配置中心获取配置NacosConfiguration#initSeataConfig

  • Data Id:seataClient.tx_group_stock.properties
  • Group:SEATA_GROUP_LWKTEST

其中的service.vgroupMapping.tx_group_stock的值是dev_cluster_1,接下来注册能力就要使用这个集群来工作。

private static void initSeataConfig() {
    try {
        String nacosDataId = getNacosDataId();
        String config = configService.getConfig(nacosDataId, getNacosGroup(), DEFAULT_CONFIG_TIMEOUT);
        if (StringUtils.isNotBlank(config)) {
            seataConfig = ConfigProcessor.processConfig(config, getNacosDataType());
            NacosListener nacosListener = new NacosListener(nacosDataId, null);
            configService.addListener(nacosDataId, getNacosGroup(), nacosListener);
        }
    } catch (NacosException | IOException e) {
        LOGGER.error("init config properties error", e);
    }
}
复制代码

RegistryFactory#getInstance()这是个单例机制,所以源码梳理起来很简单,下边获取TC服务的时候会调用此单例方法做初始化。

  1. 读取配置文件中registry.type,
  2. 配置的值是nacos,所以读出的值是nacos
  3. 通过SPI加载并实例化 NacosRegistryProvider
public class RegistryFactory {
    /**
     * Gets instance.
     *
     * @return the instance
     */
    public static RegistryService getInstance() {
        return RegistryFactoryHolder.INSTANCE;
    }
    private static RegistryService buildRegistryService() {
        RegistryType registryType;
        //registryTypeName = "registry.type"
        String registryTypeName = ConfigurationFactory.CURRENT_FILE_INSTANCE.getConfig(
            ConfigurationKeys.FILE_ROOT_REGISTRY + ConfigurationKeys.FILE_CONFIG_SPLIT_CHAR
                + ConfigurationKeys.FILE_ROOT_TYPE);
        try {
            // nacos
            registryType = RegistryType.getType(registryTypeName);
        } catch (Exception exx) {
            throw new NotSupportYetException("not support registry type: " + registryTypeName);
        }
        // 通过SPI 加载并实例化 NacosRegistryProvider
        return EnhancedServiceLoader.load(RegistryProvider.class, Objects.requireNonNull(registryType).name()).provide();
    }
    private static class RegistryFactoryHolder {
        private static final RegistryService INSTANCE = buildRegistryService();
    }
}
复制代码

TM、RM 客户端需要与TC通信,所以在其初始化时必然会有获取TC集群的逻辑,对应在源码TmNettyRemotingClient#init 中的reconnect方法。

@Override
public void init() {
    // registry processor
    registerProcessor();
    if (initialized.compareAndSet(false, true)) {
        //父类中会开启定时任务来执行 getClientChannelManager().reconnect(transactionServiceGroup)
        super.init();
        if (io.seata.common.util.StringUtils.isNotBlank(transactionServiceGroup)) {
            getClientChannelManager().reconnect(transactionServiceGroup);
        }
    }
}
复制代码

reconnect中的.NettyClientChannelManager#getAvailServerList 是根据seata.tx-service-group的值来检索TC集群信息。直接提供出来调用堆栈,方便大家快速熟悉调用链路:

getServiceGroup:111, RegistryService (io.seata.discovery.registry)
lookup:145, NacosRegistryServiceImpl (io.seata.discovery.registry.nacos)
getAvailServerList:257, NettyClientChannelManager (io.seata.core.rpc.netty)
reconnect:171, NettyClientChannelManager (io.seata.core.rpc.netty)
init:198, TmNettyRemotingClient (io.seata.core.rpc.netty)
init:47, TMClient (io.seata.tm)
initClient:220, GlobalTransactionScanner (io.seata.spring.annotation)
afterPropertiesSet:512, GlobalTransactionScanner (io.seata.spring.annotation)
复制代码

这里便是通过Seata客户端 seata.tx-service-group的值,找到最终TC集群的关键之处。在getServiceGroup中从nacos中获取service.vgroupMapping.tx_group_stock的值,即dev_cluster_1

default String getServiceGroup(String key) {
    //key = service.vgroupMapping.tx_group_stock
    key = PREFIX_SERVICE_ROOT + CONFIG_SPLIT_CHAR + PREFIX_SERVICE_MAPPING + key;
    if (!SERVICE_GROUP_NAME.contains(key)) {
        ConfigurationCache.addConfigListener(key);
        SERVICE_GROUP_NAME.add(key);
    }
    return ConfigurationFactory.getInstance().getConfig(key);
}
复制代码

然后NettyClientChannelManager#reconnect中获取 TC 集群中的所有 TC 服务节点,对每个TC 服务节点建连。

for (String serverAddress : availList) {
    try {
        acquireChannel(serverAddress);
        channelAddress.add(serverAddress);
    } catch (Exception e) {
        LOGGER.error("{} can not connect to {} cause:{}", FrameworkErrorCode.NetConnect.getErrCode(),
            serverAddress, e.getMessage(), e);
    }
}
复制代码

再梳理一下,梳理这么多的关键就是通过tx_group_stock 找到 TC 集群 dev_cluster_1

  • 客户端:
seata:
  # 默认关闭,如需启用spring.datasource.dynami.seata需要同时开启
  enabled: true
  # Seata 事务组编号,用于 TC 集群名。该配置需要与服务端提到的group相对应,也需要与下面的相对应
  tx-service-group: tx_group_stock
复制代码
  • nacos:
Data ID: seataClient.tx_group_stock.properties
Group: SEATA_GROUP_ROCKTEST
配置内容:
    ...
    service.vgroupMapping.tx_group_stock=dev_cluster_1
    ...
复制代码
  • TC服务端:
registry:
  # support: nacos 、 eureka 、 redis 、 zk  、 consul 、 etcd3 、 sofa
  type: nacos
  preferred-networks: 30.240.*
  nacos:
    application: seata-server
    cluster: dev_cluster_1
复制代码

RegistryService#getServiceGroup中从nacos获取值的时候,有个细节需要注意:通过namespace + Group + Key(Data Id) 三维来唯一标示一个Key。

四、刷新TC集群

AbstractNettyRemotingClient#init中默认会每隔10s进行一次 TC 服务清单刷新与重连

timerExecutor.scheduleAtFixedRate(new Runnable() {
    @Override
    public void run() {
        clientChannelManager.reconnect(getTransactionServiceGroup());
    }
}, SCHEDULE_DELAY_MILLS, SCHEDULE_INTERVAL_MILLS, TimeUnit.MILLISECONDS);
复制代码

五、最后说一句

我是石页兄,如果这篇文章对您有帮助,或者有所启发的话,欢迎关注笔者的微信公众号【 架构染色 】进行交流和学习。您的支持是我坚持写作最大的动力。


相关文章
|
1月前
|
负载均衡 算法
架构学习:7种负载均衡算法策略
四层负载均衡包括数据链路层、网络层和应用层负载均衡。数据链路层通过修改MAC地址转发帧;网络层通过改变IP地址实现数据包转发;应用层有多种策略,如轮循、权重轮循、随机、权重随机、一致性哈希、响应速度和最少连接数均衡,确保请求合理分配到服务器,提升性能与稳定性。
241 11
架构学习:7种负载均衡算法策略
|
2月前
|
人工智能 自然语言处理
RWKV-7:RWKV系列开源最新的大模型架构,具有强大的上下文学习能力,超越传统的Attention范式
RWKV-7是RWKV系列的最新大模型架构版本,具有强大的上下文学习能力,超越了传统的attention和linear attention范式。本文详细介绍了RWKV-7的主要功能、技术原理及其在多语言处理、文本生成等领域的应用场景。
181 7
RWKV-7:RWKV系列开源最新的大模型架构,具有强大的上下文学习能力,超越传统的Attention范式
|
1月前
|
监控 JavaScript 数据可视化
建筑施工一体化信息管理平台源码,支持微服务架构,采用Java、Spring Cloud、Vue等技术开发。
智慧工地云平台是专为建筑施工领域打造的一体化信息管理平台,利用大数据、云计算、物联网等技术,实现施工区域各系统数据汇总与可视化管理。平台涵盖人员、设备、物料、环境等关键因素的实时监控与数据分析,提供远程指挥、决策支持等功能,提升工作效率,促进产业信息化发展。系统由PC端、APP移动端及项目、监管、数据屏三大平台组成,支持微服务架构,采用Java、Spring Cloud、Vue等技术开发。
|
2月前
|
机器学习/深度学习 前端开发 算法
婚恋交友系统平台 相亲交友平台系统 婚恋交友系统APP 婚恋系统源码 婚恋交友平台开发流程 婚恋交友系统架构设计 婚恋交友系统前端/后端开发 婚恋交友系统匹配推荐算法优化
婚恋交友系统平台通过线上互动帮助单身男女找到合适伴侣,提供用户注册、个人资料填写、匹配推荐、实时聊天、社区互动等功能。开发流程包括需求分析、技术选型、系统架构设计、功能实现、测试优化和上线运维。匹配推荐算法优化是核心,通过用户行为数据分析和机器学习提高匹配准确性。
178 3
|
3月前
|
人工智能 云计算 网络架构
阿里云引领智算集群网络架构的新一轮变革
11月8日~10日在江苏张家港召开的CCF ChinaNet(即中国网络大会)上,众多院士、教授和业界技术领袖齐聚一堂,畅谈网络未来的发展方向,聚焦智算集群网络的创新变革。
阿里云引领智算集群网络架构的新一轮变革
|
3月前
|
负载均衡 Dubbo 算法
集群容错架构设计
集群容错架构设计
52 1
集群容错架构设计
|
2月前
|
存储 负载均衡 监控
揭秘 Elasticsearch 集群架构,解锁大数据处理神器
Elasticsearch 是一个强大的分布式搜索和分析引擎,广泛应用于大数据处理、实时搜索和分析。本文深入探讨了 Elasticsearch 集群的架构和特性,包括高可用性和负载均衡,以及主节点、数据节点、协调节点和 Ingest 节点的角色和功能。
80 0
|
3月前
|
人工智能 运维 网络架构
阿里云引领智算集群网络架构的新一轮变革
11月8日至10日,CCF ChinaNet(中国网络大会)在江苏张家港召开,众多院士、教授和技术领袖共聚一堂,探讨网络未来发展方向。阿里云研发副总裁蔡德忠发表主题演讲,展望智算技术发展趋势,提出智算网络架构变革的新思路,发布高通量以太网协议和ENode+超节点系统规划,引起广泛关注。阿里云HPN7.0引领智算以太网生态蓬勃发展,成为业界标杆。未来,X10规模的智算集群将面临新的挑战,Ethernet将成为主流方案,推动Scale up与Scale out的融合架构,提升整体系统性能。
|
3月前
|
存储 缓存 NoSQL
【赵渝强老师】Memcached集群的架构
Memcached 是一个高性能的分布式内存对象缓存系统,通过在内存中维护一个巨大的 Hash 表来存储各种格式的数据,如图像、视频、文件及数据库检索结果等。它主要用于减轻数据库压力,提高网站系统的性能。Memcached 不支持数据持久化,因此仅作为缓存技术使用。其数据分布式存储由客户端应用程序实现,而非服务端。
122 0
【赵渝强老师】Memcached集群的架构
|
3月前
|
调度 Docker 容器
【赵渝强老师】Docker Swarm集群的体系架构
Docker Swarm自1.12.0版本起集成至Docker引擎,无需单独安装。它内置服务发现功能,支持跨多服务器或宿主机创建容器,形成集群提供服务。相比之下,Docker Compose仅限于单个宿主机。Docker Swarm采用主从架构,Swarm Manager负责管理和调度集群中的容器资源,用户通过其接口发送指令,Swarm Node根据指令创建容器运行应用。

热门文章

最新文章