我正在开发一个带有微服务的分布式系统,只有一个只写数据库,其余的在逻辑复制中只读
我的挑战是保持数据的一致性,尤其是客户账户中的余额
由于我的业务模型必然需要微服务来对数据库表进行更新,并且根据情况,将余额添加到客户的帐户中。
我的问题是,如果客户执行一些减少其帐户余额的过程,同时某些微服务也在操纵他的帐户余额,如何保证客户余额的一致性
我考虑过在数据库中创建一个事务,并在系统完成处理作为该过程一部分的其他表中的更新时立即使用该事务来更改其余额,因为这会在事务未完成时阻止读取该客户的余额。完了,这是最正确的方法吗?
经过一番研究,我找到了解决方案,这些解决方案都是由 PostgreSQL 原生提供的。
第一个是事务隔离级别Repeatable Read:
此隔离级别可确保一旦事务读取了一组数据,该数据将保持一致,即使其他事务稍后修改它。
即使其他用户在事务期间修改了数据,这些修改在当前事务中也不会可见。
如果一个事务在“可重复读”隔离级别上尝试保存已被另一个事务修改(提交)的数据,则这将导致并发错误或隔离冲突。您只需从头开始重复该过程即可。
选择更新
SELECT ... FOR UPDATE 命令是 PostgreSQL 中的一个子句,它允许用户显式锁定表中的行以进行更新(或读取,如果其他事务也使用 SELECT FOR UPDATE)。这在并发控制的场景中很有用,
乐观锁
乐观锁是数据库中使用的一种技术,允许多个事务同时访问相同的数据,而不会互相阻塞。乐观锁定不是在修改数据时阻塞数据,而是依靠检查数据版本来避免冲突。
想象一下,您正在更新数据库中的一条记录,该数据库具有版本控制列和客户余额列。在执行更新之前,您检查记录的版本是否与您最初读取时的版本相同。如果版本仍然相同,则应用更新。否则,这意味着另一个事务已经修改了数据,您需要处理这种情况,可能是通过重新加载数据并重做操作或通知用户冲突。
这是一个包含两个事务的简单示例:
交易1:
结束交易。
事务 2(在读取之后开始,但在事务 1 更新之前):