首页 > 其他分享 >微服务的分布式事务

微服务的分布式事务

时间:2024-12-27 16:42:12浏览次数:4  
标签:事务 服务 void private message order 分布式

在微服务架构中,分布式事务是一个复杂且常见的挑战。分布式事务是指跨越多个微服务(即多个数据库)的事务,这些服务需要协同工作以确保数据的一致性和完整性。由于微服务通常是独立部署和管理的,每个服务都有自己的数据库,因此传统的单数据库事务管理机制无法直接应用。以下是分布式事务的详细解释、挑战以及常见的解决策略。

分布式事务的定义

分布式事务是指涉及多个独立数据库或服务的事务,这些服务需要协同工作以确保数据的一致性和完整性。分布式事务的目标是确保所有参与的服务要么全部成功提交,要么全部回滚,以避免数据不一致的问题

分布式事务的挑战

  1. ACID原则:

    • 分布式事务需要满足ACID(原子性、一致性、隔离性、持久性)原则,这在分布式系统中非常复杂。
    • 原子性:确保事务中的所有操作要么全部成功,要么全部失败。
    • 一致性:确保事务完成后,系统中的数据仍然保持一致。
    • 隔离性:确保一个事务的执行不会影响其他事务的执行。
    • 持久性:确保事务一旦提交,其结果将永久保存。
  2. 性能开销:

    • 分布式事务通常涉及多个服务之间的通信和协调,增加了网络延迟和资源消耗,从而影响性能。
    • 需要复杂的协调机制,如两阶段提交(2PC),这可能会导致性能瓶颈。
  3. 可用性:

    • 分布式事务的协调机制可能会降低系统的可用性。如果某个服务或网络出现故障,整个事务可能会被阻塞或回滚。
  4. 复杂性:

    • 实现和管理分布式事务需要复杂的逻辑和协调机制,增加了系统的复杂性。
    • 需要处理多种异常情况和失败恢复机制。

分布式事务的解决策略

  1. 两阶段提交(2PC, Two-Phase Commit)
  • 第一阶段(准备阶段):

    • 协调者(Coordinator)向所有参与者(Participants)发送“准备提交”(Prepare to Commit)请求。
    • 参与者响应“准备提交”或“中止提交”(Abort to Commit)。
  • 第二阶段(提交阶段):

    • 如果所有参与者都响应“准备提交”,协调者发送“提交”(Commit)请求。
    • 如果任何一个参与者响应“中止提交”,协调者发送“中止”(Abort)请求。

    示例:
    传统的关系型数据库支持两阶段提交,但这种方式在高并发和分布式系统中性能较差。

  1. Saga模式
    Saga模式是一种分布式事务管理方法,通过一系列的本地事务和补偿事务来确保全局事务的一致性。Saga模式分为编排型(Orchestrated)和编排型(Choreography)两种方式。
  • 编排型Saga:

    • 使用一个协调者(Orchestrator)来管理整个Saga流程。
    • 协调者负责启动和管理各个本地事务,并在某个本地事务失败时触发相应的补偿事务。
  • 编排型Saga:

    • 每个服务都是Saga的参与者,并通过消息队列进行通信。
    • 服务在完成本地事务后发送消息通知其他服务。
    • 如果某个本地事务失败,服务发送补偿消息来回滚之前的事务。

示例:

  • 使用消息队列(如RabbitMQ、Kafka)来实现编排型Saga。

      public class OrderService
      {
      	public void CreateOrder(Order order)
      	{
      		// 创建订单本地事务
      		SaveOrder(order);
    
      		// 发送消息通知支付服务
      		var paymentMessage = new PaymentMessage { OrderId = order.Id, Amount = order.TotalAmount };
      		SendMessageToQueue(paymentMessage);
      	}
    
      	private void SaveOrder(Order order)
      	{
      		// 保存订单到本地数据库
      	}
    
      	private void SendMessageToQueue(PaymentMessage message)
      	{
      		// 发送消息到消息队列
      	}
      }
    
      public class PaymentService
      {
      	public void ProcessPayment(PaymentMessage message)
      	{
      		// 处理支付本地事务
      		ProcessPaymentForOrder(message.OrderId, message.Amount);
    
      		// 发送消息通知库存服务
      		var inventoryMessage = new InventoryMessage { OrderId = message.OrderId, Items = GetOrderItems(message.OrderId) };
      		SendMessageToQueue(inventoryMessage);
      	}
    
      	private void ProcessPaymentForOrder(long orderId, decimal amount)
      	{
      		// 处理支付逻辑
      	}
    
      	private List<Item> GetOrderItems(long orderId)
      	{
      		// 获取订单中的商品
      		return new List<Item>();
      	}
    
      	private void SendMessageToQueue(InventoryMessage message)
      	{
      		// 发送消息到消息队列
      	}
      }
    
      public class InventoryService
      {
      	public void UpdateInventory(InventoryMessage message)
      	{
      		try
      		{
      			// 更新库存本地事务
      			UpdateStock(message.Items);
      		}
      		catch (Exception ex)
      		{
      			// 触发补偿事务
      			RollbackOrder(message.OrderId);
      		}
      	}
    
      	private void UpdateStock(List<Item> items)
      	{
      		// 更新库存逻辑
      	}
    
      	private void RollbackOrder(long orderId)
      	{
      		// 回滚订单逻辑
      	}
      }
    
  1. 最终一致性(Eventual Consistency)
  • 定义:

    • 最终一致性是指系统在一段时间后会达到一致状态,允许一定的不一致。
    • 通过异步消息传递和补偿机制来实现最终一致性。
  • 实现方式:

    • 发布-订阅模式:使用消息队列发布事件,订阅者处理事件并更新状态。
    • 幂等操作:确保每个操作可以被多次执行而不会导致不一致的结果。

示例:

  • 使用消息队列(如Kafka)发布事件。

      public class OrderService
      {
      	public void CreateOrder(Order order)
      	{
      		// 创建订单本地事务
      		SaveOrder(order);
    
      		// 发布订单创建事件
      		var orderCreatedEvent = new OrderCreatedEvent { OrderId = order.Id, TotalAmount = order.TotalAmount };
      		PublishEvent(orderCreatedEvent);
      	}
    
      	private void SaveOrder(Order order)
      	{
      		// 保存订单到本地数据库
      	}
    
      	private void PublishEvent(OrderCreatedEvent @event)
      	{
      		// 发布事件到消息队列
      	}
      }
    
      public class PaymentService
      {
      	public void HandleOrderCreatedEvent(OrderCreatedEvent @event)
      	{
      		// 处理订单创建事件
      		ProcessPayment(@event.OrderId, @event.TotalAmount);
      	}
    
      	private void ProcessPayment(long orderId, decimal amount)
      	{
      		// 处理支付逻辑
      	}
      }
    
      public class InventoryService
      {
      	public void HandleOrderCreatedEvent(OrderCreatedEvent @event)
      	{
      		// 处理订单创建事件
      		UpdateInventory(@event.OrderId);
      	}
    
      	private void UpdateInventory(long orderId)
      	{
      		// 更新库存逻辑
      	}
      }
    
  1. 补偿事务(Compensating Transactions)
  • 定义:

    • 补偿事务是一种回滚机制,当某个本地事务失败时,通过执行补偿事务来恢复系统的一致性。
  • 实现方式:

    • 在每个本地事务成功后,记录相应的补偿操作。
    • 如果某个本地事务失败,执行相应的补偿操作来回滚之前的操作。
  • 示例:

    • 记录补偿操作并在失败时执行。

      public class OrderService
      {
      public void CreateOrder(Order order)
      {
      try
      {
      // 创建订单本地事务
      SaveOrder(order);

        		// 发送消息通知支付服务
        		var paymentMessage = new PaymentMessage { OrderId = order.Id, TotalAmount = order.TotalAmount };
        		SendMessageToQueue(paymentMessage);
        	}
        	catch (Exception ex)
        	{
        		// 触发补偿事务
        		RollbackOrder(order.Id);
        	}
        }
      
        private void SaveOrder(Order order)
        {
        	// 保存订单到本地数据库
        }
      
        private void SendMessageToQueue(PaymentMessage message)
        {
        	// 发送消息到消息队列
        }
      
        private void RollbackOrder(long orderId)
        {
        	// 回滚订单逻辑
        }
      

      }

      public class PaymentService
      {
      public void ProcessPayment(PaymentMessage message)
      {
      try
      {
      // 处理支付本地事务
      ProcessPaymentForOrder(message.OrderId, message.Amount);

        		// 发送消息通知库存服务
        		var inventoryMessage = new InventoryMessage { OrderId = message.OrderId, Items = GetOrderItems(message.OrderId) };
        		SendMessageToQueue(inventoryMessage);
        	}
        	catch (Exception ex)
        	{
        		// 触发补偿事务
        		RollbackOrder(message.OrderId);
        	}
        }
      
        private void ProcessPaymentForOrder(long orderId, decimal amount)
        {
        	// 处理支付逻辑
        }
      
        private List<Item> GetOrderItems(long orderId)
        {
        	// 获取订单中的商品
        	return new List<Item>();
        }
      
        private void SendMessageToQueue(InventoryMessage message)
        {
        	// 发送消息到消息队列
        }
      
        private void RollbackOrder(long orderId)
        {
        	// 回滚订单逻辑
        }
      

      }

      public class InventoryService
      {
      public void UpdateInventory(InventoryMessage message)
      {
      try
      {
      // 更新库存本地事务
      UpdateStock(message.Items);
      }
      catch (Exception ex)
      {
      // 触发补偿事务
      RollbackOrder(message.OrderId);
      }
      }

        private void UpdateStock(List<Item> items)
        {
        	// 更新库存逻辑
        }
      
        private void RollbackOrder(long orderId)
        {
        	// 回滚订单逻辑
        }
      

      }

  1. 分布式锁(Distributed Lock)
  • 定义:

    • 分布式锁是一种机制,用于确保在同一时间只有一个服务可以执行某个关键操作,避免并发问题。
  • 实现方式:

    • 使用分布式锁(如Redis分布式锁、Zookeeper分布式锁)来协调操作。
  • 示例:

    • 使用Redis实现分布式锁。

      using StackExchange.Redis;
      using System;
      using System.Threading.Tasks;

      public class DistributedLockExample
      {
      private readonly ConnectionMultiplexer _redis;
      private readonly IDatabase _db;

        public DistributedLockExample(string redisConnectionString)
        {
        	_redis = ConnectionMultiplexer.Connect(redisConnectionString);
        	_db = _redis.GetDatabase();
        }
      
        public async Task ProcessOrderAsync(Order order)
        {
        	string lockKey = $"order_lock_{order.Id}";
        	string lockValue = Guid.NewGuid().ToString();
        	TimeSpan lockDuration = TimeSpan.FromSeconds(10);
      
        	// 尝试获取分布式锁
        	bool lockAcquired = await _db.LockTakeAsync(lockKey, lockValue, lockDuration);
      
        	if (lockAcquired)
        	{
        		try
        		{
        			// 创建订单本地事务
        			SaveOrder(order);
      
        			// 发送消息通知支付服务
        			var paymentMessage = new PaymentMessage { OrderId = order.Id, TotalAmount = order.TotalAmount };
        			SendMessageToQueue(paymentMessage);
      
        			// 处理库存逻辑
        			UpdateInventory(order.Id);
        		}
        		catch (Exception ex)
        		{
        			// 处理异常并回滚操作
        			RollbackOrder(order.Id);
        			RollbackInventory(order.Id);
        		}
        		finally
        		{
        			// 释放分布式锁
        			await _db.LockReleaseAsync(lockKey, lockValue);
        		}
        	}
        	else
        	{
        		// 无法获取锁,处理重试或失败逻辑
        		Console.WriteLine("Failed to acquire lock. Retrying or handling failure.");
        	}
        }
      
        private void SaveOrder(Order order)
        {
        	// 保存订单到本地数据库
        }
      
        private void SendMessageToQueue(PaymentMessage message)
        {
        	// 发送消息到消息队列
        }
      
        private void UpdateInventory(long orderId)
        {
        	// 更新库存逻辑
        }
      
        private void RollbackOrder(long orderId)
        {
        	// 回滚订单逻辑
        }
      
        private void RollbackInventory(long orderId)
        {
        	// 回滚库存逻辑
        }
      

      }

总结

分布式事务:是指涉及多个独立数据库或服务的事务,需要确保数据的一致性和完整性。

  • 挑战:

    • ACID原则的实现
    • 性能开销
    • 可用性
    • 复杂性
  • 解决策略:

    • 两阶段提交(2PC):通过协调器管理事务的准备和提交阶段。
    • Saga模式:通过一系列本地事务和补偿事务来确保全局事务的一致性。
    • 最终一致性(Eventual Consistency):允许一定的不一致,并通过异步消息传递和补偿机制实现一致性。
    • 补偿事务(Compensating Transactions):记录补偿操作并在失败时执行回滚。
    • 分布式锁(Distributed Lock):确保同一时间只有一个服务可以执行关键操作。

通过选择合适的分布式事务管理策略,可以有效地管理微服务架构中的数据一致性和完整性,同时尽量减少性能开销和复杂性。

  • 选择合适的策略
    在选择具体的分布式事务管理策略时,需要根据具体的应用场景和需求来决定。例如:

    • 高可用性和性能优先:适合使用Saga模式或最终一致性策略。
    • 强一致性要求:适合使用两阶段提交或分布式锁。
    • 简单的事务管理:适合使用补偿事务策略。

标签:事务,服务,void,private,message,order,分布式
From: https://www.cnblogs.com/chenshibao/p/18636136

相关文章

  • 什么是微服务
    微服务(Microservices)是一种软件架构设计风格,它将应用程序分解为一组小的、独立的服务。每个服务实现特定的业务功能,并且可以独立部署、扩展和维护。这种架构设计旨在提高应用程序的灵活性、可扩展性和可维护性,尤其是在处理复杂和大规模的应用程序时。以下是微服务架构的详细解释......
  • 基于Sentinel的服务保护方案的三种方式(请求限流、线程隔离、服务熔断)超详细讲解
    目录1、三种方式介绍1.1请求限流1.2线程隔离方案1.3服务熔断2、基于sentinel实现2.1启动sentinel2.2基于springboot整合sentinel2.2.1请求限流2.2.2请求隔离2.2.2.1 OpenFeign整合Sentinel2.2.3服务熔断2.2.3.1编写降级代码2.2.3.2服务熔断1、三种方......
  • DNS域名解析服务
    一、实验环境二、实验步骤实验一(搭建DNS服务器)1、安装dns(主DNS)yum-yinstallbind-chroot.x86_642、修改主配置文件(主DNS)vim/etc/named.conf修改:vim/etc/named.rfc1912.zones修改:3、创建正向和反向区域数据文件(主DNS)cd/var/named/cpnamed.localhostlkk.co......
  • PowerShell 提供了多种强大且灵活的方式来进行外发数据传输。无论是通过 HTTP 请求、F
    在WindowsPowerShell中,"数据传输外发"(或类似的表述,可能是“外发数据传输”)并没有明确的、标准的技术术语。不过,这可能指的是数据的外发传输(outbounddatatransfer),即从本地计算机传送到外部服务器或其他系统的过程。在PowerShell中,数据传输通常通过不同的网络通信协议来进行......
  • 阿里云镜像服务使用指南
    阿里云容器镜像服务ACR(AlibabaCloudContainerRegistry)是面向容器镜像、HelmChart等符合OCI标准云原生制品安全托管及高效分发平台。ACR企业版支持全球同步加速、大规模和大镜像分发加速、多代码源构建加速等全链路加速能力,与容器服务ACK无缝集成,帮助企业降低交付复杂度,......
  • wevtutil 是 Windows 操作系统中的一个命令行工具,用于管理和操作事件日志。事件日志是
     wevtutil是Windows操作系统中的一个命令行工具,用于管理和操作事件日志。事件日志是操作系统、应用程序和系统服务等记录的重要信息文件,它们用于存储系统运行时的信息、警告和错误,帮助管理员排查问题和进行故障排除。wevtutil提供了强大的功能来查看、导出、清理、配置和管......
  • 在 Ubuntu 上搭建 MinIO 服务器
    在日常开发时,如果有文件上传下载的需求(比如用户头像),但是又不想使用对象存储,那么自己搭建一个MinIO服务器是一个比较简单的解决方案。MinIO是一个基于ApacheLicensev2.0开源协议的对象存储服务。它兼容亚马逊S3云存储服务接口,非常适合于存储大容量非结构化的数据,例如图片......
  • 向服务器更新文件
    //下载版本///<summary>///下载版本///</summary>///<paramname="FilePath">服务器文件地址完整</param>///<paramname="downLoadPath">下载到本地地址</param>///<returns></returns>......
  • 向服务器上传文件
    //--------------------向服务器上传文件------//浏览选择需要上传的文件privatestaticboolUnzip(stringaddress,stringfilezip){//创建对话框OpenFileDialogofd=newOpenFileDialog();ofd.Title="请选择上传的文件";......
  • WCF服务支持http
    //-------------------请求方法Server.cs-----------------publicclassRequestService:ApiController{///<summary>///HttpGet请求///</summary>///<paramname="url">请求地址</param>///<paramname=&......