分布式事务: 下游两个db使用redis, 需要更新这两个不同的db, 如何自己实现最终一致性

在分布式环境下,当你有两个下游数据库(DB1和DB2)都使用Redis作为中介,并且需要保证对这两个数据库的更新操作最终一致,可以采用几种常见的方法来实现最终一致性:

  1. 事务消息(Transaction Messaging)

    • 使用消息队列(如RabbitMQ、RocketMQ、Kafka等)发布带有事务属性的消息,例如采用两阶段提交协议(Two-Phase Commit, 2PC)或者更轻量级的一阶段提交变种(如Confirm/Cancel模式)。
      • 发送一个“准备”消息到消息队列,当两个数据库的更新操作都成功时,确认消息;
      • 如果任何一个数据库更新失败,则取消消息,触发补偿操作(比如回滚未成功的操作);
      • 消费者监听消息队列,接收到确认的消息后,再更新Redis。
  2. Saga模式

    • 定义一系列的本地事务(Local Transactions),每个事务对应一个数据库操作,并且每个事务都有对应的补偿操作(Compensation Action)。
      • 执行第一个数据库更新,如果成功则继续下一个数据库更新,否则执行补偿操作;
      • 一旦所有数据库更新成功,更新Redis;
      • 如果在任何阶段失败,则按照相反顺序执行补偿操作,使系统回到一致状态。
  3. TCC(Try-Confirm-Cancel)模式

    • 设计每个数据库操作为一个TCC服务,每个服务具有Try、Confirm和Cancel三个接口。
      • Try阶段尝试执行业务检查和预留资源;
      • Confirm阶段在所有Try都成功后,确认之前的业务操作;
      • Cancel阶段在任何Try失败时,撤销已执行的操作;
      • 在所有数据库操作的Confirm阶段成功后,更新Redis。
  4. 基于Redis的分布式锁和Watch-Dog机制

    • 使用Redis的原子操作如MULTI/EXEC事务块或者Lua脚本,确保Redis和数据库之间的更新是一致的;
    • 对每个数据库操作加分布式锁,确保互斥执行;
    • 更新Redis的同时,把更新状态和相关标识存储到Redis;
    • 利用Redis的发布/订阅机制,当一个数据库更新成功后,通知另一个数据库进行更新;
    • 若更新失败,可设置Watch-Dog服务定期检查Redis中的状态,并对未达到最终一致性的操作进行补偿或重试。
  5. 异步更新和超时重试

    • 先尝试更新两个数据库;
    • 成功更新数据库后,将更新命令异步写入Redis;
    • 设置后台任务或定时任务检测Redis中是否有未同步成功的操作,如果有,则进行重试,直到所有数据最终一致。

TCP和UDP可以绑定同一个端口吗?

TCP和UDP是两种不同的传输层协议,它们各自的数据包结构、传输方式和拥塞控制机制均不相同。理论上,TCP和UDP可以绑定到同一个端口号,因为在操作系统层面,一个端口号是用来标识特定主机上的特定服务的,而这个端口号与传输层协议是相互独立的。

例如,在一台机器上,你可以启动一个监听TCP 80端口的HTTP服务(如Apache或Nginx),同时也可以启动一个监听UDP 80端口的DNS服务或其他基于UDP的应用。操作系统会根据不同的协议将数据包路由到对应的服务程序。

需要注意的是,同一时刻内,同一IP地址、同一端口号不能同时存在两个监听的TCP服务或UDP服务,但在TCP和UDP之间是可以共享端口号的。换言之,TCP和UDP可以用相同的端口,但不能有两个或以上的TCP服务或UDP服务使用相同的四元组(IP地址、端口号、协议类型)。

最后编辑: kuteng  文档更新时间: 2024-04-02 09:53   作者:kuteng