天天看点

SpringCloud的分布式锁和分布式事务

基于 Redis 的分布式锁

利用 SETNX 和 SETEX

基本命令主要有:

SETNX(SET If Not Exists):当且仅当 Key 不存在时,则可以设置,否则不做任何动作。

SETEX:可以设置超时时间

其原理为:通过 SETNX 设置 Key-Value 来获得锁,随即进入死循环,每次循环判断,如果存在 Key 则继续循环,如果不存在 Key,则跳出循环,当前任务执行完成后,删除 Key 以释放锁。

这种方式可能会导致死锁,为了避免这种情况,需要设置超时时间。

通过数据库实现分布式锁是最不可靠的一种方式,对数据库依赖较大,性能较低,不利于处理高并发的场景。

通过 Redis 的 Redlock 和 ZooKeeper 来加锁,性能有了比较大的提升。

基于 Zookeeper 的分布式锁

ZooKeeper 简介

ZooKeeper 是一个分布式的,开放源码的分布式应用程序协调服务,是 Google Chubby 的一个开源实现,是 Hadoop 和 Hbase 的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。

针对 Redlock,曾经有位大神对其实现的分布式锁提出了质疑,但是 Redis 官方却不认可其说法,所谓公说公有理婆说婆有理,对于分布式锁的解决方案,没有最好,只有最适合的,根据不同的项目采取不同方案才是最合理的。

首先我们应知道,事务是为了保证数据的一致性而产生的。那么分布式事务,顾名思义,就是我们要保证分布在不同数据库、不同服务器、不同应用之间的数据一致性。

为什么需要分布式事务?

最传统的架构是单一架构,数据是存放在一个数据库上的,采用数据库的事务就能满足我们的要求。随着业务的不断扩张,数据的不断增加,单一数据库已经到达了一个瓶颈,因此我们需要对数据库进行分库分表。为了保证数据的一致性,可能需要不同的数据库之间的数据要么同时成功,要么同时失败,否则可能导致产生一些脏数据,也可能滋生 Bug。

在这种情况下,分布式事务思想应运而生。

应用场景

分布式事务的应用场景很广,我也无法一一举例,我列举出比较常见的场景,以便于读者在实际项目中,在用到了一些场景时即可考虑分布式事务。

支付

最经典的场景就是支付了,一笔支付,是对买家账户进行扣款,同时对卖家账户进行加钱,这些操作必须在一个事务里执行,要么全部成功,要么全部失败。而对于买家账户属于买家中心,对应的是买家数据库,而卖家账户属于卖家中心,对应的是卖家数据库,对不同数据库的操作必然需要引入分布式事务。

在线下单

买家在电商平台下单,往往会涉及到两个动作,一个是扣库存,第二个是更新订单状态,库存和订单一般属于不同的数据库,需要使用分布式事务保证数据一致性。

银行转账

账户 A 转账到账户 B,实际操作是账户 A 减去相应金额,账户 B 增加相应金额,在分库分表的前提下,账户 A 和账户 B 可能分别存储在不同的数据库中,这时需要使用分布式事务保证数据库一致性。否则可能导致的后果是 A 扣了钱 B 却没有增加钱,或者 B 增加了钱 A 却没有扣钱。

SpringBoot 集成 Atomikos 实现分布式事务

Atomikos 简介

Atomikos 是一个为 Java 平台提供增值服务的开源类事务管理器。

以下是包括在这个开源版本中的一些功能:

全面崩溃 / 重启恢复;

兼容标准的 SUN 公司 JTA API;

嵌套事务;

为 XA 和非 XA 提供内置的 JDBC 适配器。

注释:XA 协议由 Tuxedo 首先提出的,并交给 X/Open 组织,作为资源管理器(数据库)与事务管理器的接口标准。目前,Oracle、Informix、DB2 和 Sybase 等各大数据库厂家都提供对 XA 的支持。XA 协议采用两阶段提交方式来管理分布式事务。XA 接口提供资源管理器与事务管理器之间进行通信的标准接口。XA 协议包括两套函数,以 xa_ 开头的及以 ax_ 开头的

继续阅读