微服务架构下,解决数据一致性问题的实践

本文涉及的产品
云原生网关 MSE Higress,422元/月
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
注册配置 MSE Nacos/ZooKeeper,118元/月
简介: 随着业务的快速发展,应用单体架构暴露出代码可维护性差、容错率低、测试难度大和敏捷交付能力差等诸多问题,微服务应运而生。微服务的诞生一方面解决了上述问题,但是另一方面却引入新的问题,其中主要问题之一就是:如何保证微服务间的业务数据一致性。

随着业务的快速发展,应用单体架构暴露出代码可维护性差、容错率低、测试难度大和敏捷交付能力差等诸多问题,微服务应运而生。微服务的诞生一方面解决了上述问题,但是另一方面却引入新的问题,其中主要问题之一就是:如何保证微服务间的业务数据一致性。

本文将通过一个商品采购的业务,来看看在Dubbo的微服务架构下,如何通过Fescar来保障业务的数据一致性。本文所述的例子中,Dubbo 和 Fescar 的注册配置服务中心均使用 Nacos。Fescar 0.2.1+ 开始支持 Nacos 注册配置服务中心。

业务描述

用户采购商品的业务,包含3个微服务:

  • 库存服务: 扣减给定商品的库存数量。
  • 订单服务: 根据采购请求生成订单。
  • 账户服务: 用户账户金额扣减。

业务结构图如下:

fescar_1

库存服务(StorageService)

 
public interface StorageService {    
      /**     
       * deduct storage count     
       */
      void deduct(String commodityCode, int count);
}

订单服务(OrderService)


public interface OrderService {    
      /**     
       * create order     
       */
     Order create(String userId, String commodityCode, int orderCount);
}

账户服务(AccountService)

public interface AccountService {    
      /**     
       * debit balance of user's account     
       */
     void debit(String userId, int money);
}

说明: 以上三个微服务均是独立部署。

8个步骤实现数据一致性

Step 1:初始化 MySQL 数据库(需要InnoDB 存储引擎)

在 resources/jdbc.properties 修改StorageService、OrderService、AccountService 对应的连接信息。

jdbc.account.url=jdbc:mysql://xxxx/xxxx
jdbc.account.username=xxxx
jdbc.account.password=xxxx
jdbc.account.driver=com.mysql.jdbc.Driver
# storage db config
jdbc.storage.url=jdbc:mysql://xxxx/xxxx
jdbc.storage.username=xxxx
jdbc.storage.password=xxxx
jdbc.storage.driver=com.mysql.jdbc.Driver
# order db config
jdbc.order.url=jdbc:mysql://xxxx/xxxx
jdbc.order.username=xxxx
jdbc.order.password=xxxx
jdbc.order.driver=com.mysql.jdbc.Driver

Step 2:创建 undo_log(用于Fescar AT 模式)表和相关业务表

相关建表脚本可在 resources/sql/ 下获取,在相应数据库中执行 dubbo_biz.sql 中的业务建表脚本,在每个数据库执行 undo_log.sql 建表脚本。

CREATE TABLE undo_log (

  
  `id` bigint(20) NOT NULL AUTO_INCREMENT,  
  `branch_id` bigint(20) NOT NULL,  
  `xid` varchar(100) NOT NULL,  
  `rollback_info` longblob NOT NULL,  
  `log_status` int(11) NOT NULL,  
  `log_created` datetime NOT NULL,  
  `log_modified` datetime NOT NULL,  
  `ext` varchar(100) DEFAULT NULL,  
  PRIMARY KEY (`id`),
  KEY `idx_unionkey` (`xid`,`branch_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

DROP TABLE IF EXISTS `storage_tbl`;
CREATE TABLE `storage_tbl` (  
  `id` int(11) NOT NULL AUTO_INCREMENT,  
  `commodity_code` varchar(255) DEFAULT NULL,  
  `count` int(11) DEFAULT 0,  
  PRIMARY KEY (`id`),
  UNIQUE KEY (`commodity_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `order_tbl`;
CREATE TABLE `order_tbl` (  
  `id` int(11) NOT NULL AUTO_INCREMENT,  
  `user_id` varchar(255) DEFAULT NULL,  
  `commodity_code` varchar(255) DEFAULT NULL,  
  `count` int(11) DEFAULT 0,  
  `money` int(11) DEFAULT 0,  
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

DROP TABLE IF EXISTS `account_tbl`;
CREATE TABLE `account_tbl` (  
  `id` int(11) NOT NULL AUTO_INCREMENT,  
  `user_id` varchar(255) DEFAULT NULL,  
  `money` int(11) DEFAULT 0,  
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

说明: 需要保证每个物理库都包含 undo_log 表,此处可使用一个物理库来表示上述三个微服务对应的独立逻辑库。

Step 3:引入 Fescar、Dubbo 和 Nacos 相关 POM 依赖

  <properties>
      <fescar.version>0.2.1</fescar.version>
      <dubbo.alibaba.version>2.6.5</dubbo.alibaba.version>
      <dubbo.registry.nacos.version>0.0.2</dubbo.registry.nacos.version>
   </properties>
    
   <dependency>
       <groupId>com.alibaba.fescar</groupId>
       <artifactId>fescar-spring</artifactId>
       <version>${fescar.version}</version>
   </dependency>
   <dependency>
       <groupId>com.alibaba.fescar</groupId>
       <artifactId>fescar-dubbo-alibaba</artifactId>
       <version>${fescar.version}</version>
       <exclusions>
           <exclusion>
               <artifactId>dubbo</artifactId>
               <groupId>org.apache.dubbo</groupId>
           </exclusion>
       </exclusions>
   </dependency>
   <dependency>
       <groupId>com.alibaba</groupId>
       <artifactId>dubbo</artifactId>
       <version>${dubbo.alibaba.version}</version>
   </dependency>
   <dependency>
       <groupId>com.alibaba</groupId>
       <artifactId>dubbo-registry-nacos</artifactId>
       <version>${dubbo.registry.nacos.version}</version>
   </dependency>

说明: 由于当前 apache-dubbo 与 dubbo-registry-nacos jar存在兼容性问题,需要排除 fescar-dubbo 中的 apache.dubbo 依赖并手动引入 alibaba-dubbo,后续 apache-dubbo(2.7.1+) 将兼容 dubbo-registry-nacos。在Fescar 中 fescar-dubbo jar 支持 apache.dubbo,fescar-dubbo-alibaba jar 支持 alibaba-dubbo。

Step 4:微服务 Provider Spring配置

分别在三个微服务Spring配置文件(dubbo-account-service.xml、 dubbo-order-service 和 dubbo-storage-service.xml )进行如下配置:

  • 配置 Fescar 代理数据源

    <bean id="accountDataSourceProxy" class="com.alibaba.fescar.rm.datasource.DataSourceProxy">
        <constructor-arg ref="accountDataSource"/>
    </bean>
    
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="accountDataSourceProxy"/>
    </bean>

    此处需要使用 com.alibaba.fescar.rm.datasource.DataSourceProxy 包装 Druid 数据源作为直接业务数据源,DataSourceProxy 用于业务 SQL 的拦截解析并与 TC 交互协调事务操作状态。

  • 配置 Dubbo 注册中心

      <dubbo:registry address="nacos://${nacos-server-ip}:8848"/>
    
  • 配置 Fescar GlobalTransactionScanner

    <bean class="com.alibaba.fescar.spring.annotation.GlobalTransactionScanner">
        <constructor-arg value="dubbo-demo-account-service"/>
        <constructor-arg value="my_test_tx_group"/>
    </bean>

    此处构造方法的第一个参数为业务自定义 applicationId,若在单机部署多微服务需要保证 applicationId 唯一。

构造方法的第二个参数为 Fescar 事务服务逻辑分组,此分组通过配置中心配置项 service.vgroup_mapping.my_test_tx_group 映射到相应的 Fescar-Server 集群名称,然后再根据集群名称.grouplist 获取到可用服务列表。

Step 5:事务发起方配置

在 dubbo-business.xml 配置以下配置:

  • 配置 Dubbo 注册中心
    同 Step 4
  • 配置 Fescar GlobalTransactionScanner
    同 Step 4
  • 在事务发起方 service 方法上添加 @GlobalTransactional 注解

     
    @GlobalTransactional(timeoutMills = 300000, name = "dubbo-demo-tx")

    timeoutMills 为事务的总体超时时间默认60s,name 为事务方法签名的别名,默认为空。注解内参数均可省略。

Step 6:启动 Nacos-Server

  • 下载 Nacos-Server 最新 release 包并解压
  • 运行 Nacos-server

Linux/Unix/Mac

sh startup.sh -m standalone

Windows

cmd startup.cmd -m standalone

访问 Nacos 控制台:http://localhost:8848/nacos/index.html#/configurationManagement?dataId=&group=&appName=&namespace

若访问成功说明 Nacos-Server 服务运行成功(默认账号/密码: nacos/nacos)

Step 7:启动 Fescar-Server

  • 下载 Fescar-Server 最新 release 包并解压
  • 初始化 Fescar 配置

进入到 Fescar-Server 解压目录 conf 文件夹下,确认 nacos-config.txt 的配置值(一般不需要修改),确认完成后运行 nacos-config.sh 脚本初始化配置。

sh nacos-config.sh $Nacos-Server-IP

eg:

sh nacos-config.sh localhost 

脚本执行最后输出 "init nacos config finished, please start fescar-server." 说明推送配置成功。若想进一步确认可登陆Nacos 控制台 配置列表 筛选 Group=FESCAR_GROUP 的配置项。

nacos_1

  • 修改 Fescar-server 服务注册方式为 nacos

进入到 Fescar-Server 解压目录 conf 文件夹下 registry.conf 修改 type="nacos" 并配置 Nacos 的相关属性。

 registry {  
   # file nacos
   type = "nacos"

  nacos {    
    serverAddr = "localhost"
    namespace = "public"
    cluster = "default"
  }
  file {    
    name = "file.conf"
  }
}

type: 可配置为 nacos 和 file,配置为 file 时无服务注册功能
nacos.serverAddr: Nacos-Sever 服务地址(不含端口号)
nacos.namespace: Nacos 注册和配置隔离 namespace
nacos.cluster: 注册服务的集群名称
file.name: type = "file" classpath 下配置文件名

  • 运行 Fescar-server

Linux/Unix/Mac

sh fescar-server.sh $LISTEN_PORT $PATH_FOR_PERSISTENT_DATA $IP(此参数可选)

Windows

cmd fescar-server.bat $LISTEN_PORT $PATH_FOR_PERSISTENT_DATA $IP(此参数可选)

$LISTEN_PORT:Fescar-Server 服务端口
$PATH_FOR_PERSISTENT_DATA: 事务操作记录文件存储路径(已存在路径)
$IP(可选参数): 用于多 IP 环境下指定 Fescar-Server 注册服务的IP

eg: sh fescar-server.sh 8091 /home/admin/fescar/data/

运行成功后可在 Nacos 控制台看到 服务名 =serverAddr 服务注册列表:

nacos_2

Step 8:启动微服务并测试

  • 修改业务客户端发现注册方式为 nacos
    同Step 7 中[修改 Fescar-server 服务注册方式为 nacos] 步骤
  • 启动 DubboAccountServiceStarter
  • 启动 DubboOrderServiceStarter
  • 启动 DubboStorageServiceStarter

启动完成可在 Nacos 控制台服务列表 看到启动完成的三个 provider:

nacos_3

  • 启动 DubboBusinessTester 进行测试

注意: 在标注 @GlobalTransactional 注解方法内部显示的抛出异常才会进行事务的回滚。整个 Dubbo 服务调用链路只需要在事务最开始发起方的 service 方法标注注解即可。

通过以上8个步骤,我们实现了用户采购商品的业务中库存、订单和账户3个独立微服务之间的数据一致性。

参考链接:

本文 sample 地址:
https://github.com/fescar-group/fescar-samples/tree/master/nacos

Fescar:
https://github.com/alibaba/fescar

Dubbo:
https://github.com/apache/incubator-dubbo

Nacos:
https://github.com/alibaba/nacos

本文作者:清铭,社区昵称 slievrly,Fescar 开源项目发起人之一,阿里巴巴中件间 TXC/GTS 核心研发成员,长期从事于分布式中间件核心研发工作,在分布式事务领域有着较丰富的技术积累。

有关 Fescar 的更多信息:

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
1月前
|
弹性计算 API 持续交付
后端服务架构的微服务化转型
本文旨在探讨后端服务从单体架构向微服务架构转型的过程,分析微服务架构的优势和面临的挑战。文章首先介绍单体架构的局限性,然后详细阐述微服务架构的核心概念及其在现代软件开发中的应用。通过对比两种架构,指出微服务化转型的必要性和实施策略。最后,讨论了微服务架构实施过程中可能遇到的问题及解决方案。
|
30天前
|
Java 开发者 微服务
从单体到微服务:如何借助 Spring Cloud 实现架构转型
**Spring Cloud** 是一套基于 Spring 框架的**微服务架构解决方案**,它提供了一系列的工具和组件,帮助开发者快速构建分布式系统,尤其是微服务架构。
160 69
从单体到微服务:如何借助 Spring Cloud 实现架构转型
|
29天前
|
运维 监控 持续交付
微服务架构解析:跨越传统架构的技术革命
微服务架构(Microservices Architecture)是一种软件架构风格,它将一个大型的单体应用拆分为多个小而独立的服务,每个服务都可以独立开发、部署和扩展。
180 36
微服务架构解析:跨越传统架构的技术革命
|
3天前
|
负载均衡 Serverless 持续交付
云端问道9期实践教学-省心省钱的云上Serverless高可用架构
详细介绍了云上Serverless高可用架构的一键部署流程
27 10
|
17天前
|
弹性计算 Java 关系型数据库
Web应用上云经典架构实践教学
Web应用上云经典架构实践教学
Web应用上云经典架构实践教学
|
3天前
|
存储 人工智能 运维
面向AI的服务器计算软硬件架构实践和创新
阿里云在新一代通用计算服务器设计中,针对处理器核心数迅速增长(2024年超100核)、超多核心带来的业务和硬件挑战、网络IO与CPU性能增速不匹配、服务器物理机型复杂等问题,推出了磐久F系列通用计算服务器。该系列服务器采用单路设计减少爆炸半径,优化散热支持600瓦TDP,并实现CIPU节点比例灵活配比及部件模块化可插拔设计,提升运维效率和客户响应速度。此外,还介绍了面向AI的服务器架构挑战与软硬件结合创新,包括内存墙问题、板级工程能力挑战以及AI Infra 2.0服务器的开放架构特点。最后,探讨了大模型高效推理中的显存优化和量化压缩技术,旨在降低部署成本并提高系统效率。
|
5天前
|
运维 监控 安全
天财商龙:云上卓越架构治理实践
天财商龙成立于1998年,专注于为餐饮企业提供信息化解决方案,涵盖点餐、收银、供应链和会员系统等。自2013年起逐步实现业务上云,与阿里云合作至今已十年。通过采用阿里云的WA体系,公司在账号管理、安全保障、监控体系和成本管控等方面进行了全面优化,提升了业务稳定性与安全性,并实现了显著的成本节约。未来,公司将持续探索智能化和全球化发展,进一步提升餐饮行业的数字化水平。
|
5天前
|
运维 安全 架构师
架构师工具箱:Well-Architected云治理提效实践
本次分享基于阿里云Well-Architected Framework的最佳实践案例,涵盖企业从上云到优化的全过程。安畅作为国内领先的云管理服务提供商(Cloud MSP),拥有800多名员工,其中70%为技术工程师,为企业提供架构安全、数据智能等技术服务。内容包括Landing Zone与Well-Architected的关系、企业云治理现状及需求分析,重点探讨了安全合规、成本优化、资源稳定性和效率提升等方面的最佳实践,并通过具体客户案例展示了如何通过自动化工具和定制化解决方案帮助企业提升云上业务价值。
|
1月前
|
运维 监控 Java
后端开发中的微服务架构实践与挑战####
在数字化转型加速的今天,微服务架构凭借其高度的灵活性、可扩展性和可维护性,成为众多企业后端系统构建的首选方案。本文深入探讨了微服务架构的核心概念、实施步骤、关键技术考量以及面临的主要挑战,旨在为开发者提供一份实用的实践指南。通过案例分析,揭示微服务在实际项目中的应用效果,并针对常见问题提出解决策略,帮助读者更好地理解和应对微服务架构带来的复杂性与机遇。 ####
|
1月前
|
消息中间件 运维 安全
后端开发中的微服务架构实践与挑战####
在数字化转型的浪潮中,微服务架构凭借其高度的灵活性和可扩展性,成为众多企业重构后端系统的首选方案。本文将深入探讨微服务的核心概念、设计原则、关键技术选型及在实际项目实施过程中面临的挑战与解决方案,旨在为开发者提供一套实用的微服务架构落地指南。我们将从理论框架出发,逐步深入至技术细节,最终通过案例分析,揭示如何在复杂业务场景下有效应用微服务,提升系统的整体性能与稳定性。 ####
41 1