内容简介:我最近一直在研究一个新项目,它需要在并发访问之间保持强大的数据一致性。为了更好地理解这个问题,你可以考虑:你应该想知道管理这些问题的复杂性是什么。为此,让我向您介绍更新丢失和脏读的问题。
我最近一直在研究一个新项目,它需要在并发访问之间保持强大的数据一致性。为了更好地理解这个问题,你可以考虑:
- 始终保持您的银行帐户余额正确
- 正确处理货架上的产品数量
- 视频或文章的喜欢或观看次数
你应该想知道管理这些问题的复杂性是什么。为此,让我向您介绍更新丢失和脏读的问题。
这个问题在计算机科学领域是众所周知的,就像名称所说的那样,由于并发访问而丢失了更新。如您所见,库存中可用物品的最终数量为5,其实应为2。
要解决这个问题,我们需要考虑锁,锁的定义为
“一种机制,可以同时将多个用户同时访问同一条数据”。
我们可以通过数据库锁定轻松解决这个问题,但是当我们谈论分布式系统时,它会变得更加棘手。
数据库锁定
关于隔离级别的说明:隔离确定了其他用户和系统对事务完整性的可见性。但是必须了解这还不能解决本文中描述的问题,这点是非常重要的。
将默认值更改为Repeatable Read可能会使跟踪问题变得更加困难,并会引导您进入一个全新的不一致世界。
即使您允许脏读,也会有一个时刻,您访问的数据却不会在并发事务之间同步。
悲观和乐观的锁
解决丢失更新问题的最简单方法就是在实际更新之前锁定要更新的行(悲观锁定)。大多数数据库支持以下语句:
SELECT * FROM products WHERE id = 1 FOR UPDATE;
这意味着其他会话可以读取该行,但在您的事务提交之前无法修改它。因此,我们可以通过...排除并发访问来轻松解决并发访问!数据库可以解决大小公司的大多数问题,并且可以在大量的事务中工作,但有时这可能会导致性能问题。
乐观锁人为冲突是可能的,但是非常罕见的。允许快速性能和高并发性,代价是:偶尔拒绝这些写入:最初接受但在最后一秒发现与另一个用户的更改冲突的数据。
我们知道,前面UPDATE语句已经锁定了写入行,因此它一次只更新一行。这样我们可以在更新时添加旧值的检查:
UPDATE products SET units=5 WHERE units=10;
其他并发事务将不满足该WHERE子句,因此只能更新零行(不更新)。如果发生这种情况,您需要进行回滚并通知用户UPDATE失败,或者您可以再次执行整个事务。
分布式系统
让我向您介绍一些新问题:
- 我们无法使用本机支持锁定或事务的数据库
- 我们正在使用的是需要锁定对共享资源的访问权限的分布式系统
首先,让我提醒您分布式对象的第一定律:不要分发您的对象(感谢 Martin Fowler )。如果您可以避免进入分布式系统,那么就这样做。这将需要解决比上面列出的问题更多的问题,例如:故障处理(分布式回滚),数据一致性和复制,容错,弹性,限制/速率限制,重试等等......
外部锁定
如果你只能进入分布式系统,那么你就需要外部锁定。以下是一些可以帮助您完成这一新冒险的文章和工具:
- Apache Zookeeper ,像软件 的Apache的Hadoop (数据的分布式处理), Apache Kafka (分布式流媒体平台)和 Apache Mesos (分布式系统内核)使用动物园管理员为分布式协调和同步。
- 使用 Redis 的分布式锁 ,Redis是一个内存数据库,具有许多现成的数据结构和算法。本文介绍如何使用称为Redlock的算法来实现DLM(分布式锁管理器)。您还可以使用带有 SETNX命令 的单节点Redis (不鼓励使用第一个)。
- 如何使用 MySQL 的GET_LOCK协调分布式工作 。 高性能MySQL (由O'Reilly Media出版)的合着者 Baron Schwartz 撰写的一篇非常好的文章,讨论了一个名为 GET_LOCK 的MySQL函数,它能够锁定用户定义的字符串。当然你不应该使用它来锁定行(MySQL已经做得很好)但可能锁定外部资源。
- 如何进行分布式锁定 ,这是由 设计数据密集型应用程序 (也由O'Reilly Media出版)的作者 Martin Kleppmann 撰写的一篇非常好的文章,讨论了锁定的有用性,关于Redlock算法和防护令牌的一些注意事项。
分布式数据存储
CAP定理:如上所述,有几种方法可以进行锁定并避免不一致。 RDBMS 已经被认为是这项工作的好工具,它们就是所谓的CP系统,即它们提供了一个具有C onsistency和Partition的环境。
CAP定理 指出,在网络分区的存在,只能在一致性和可用性之间进行选择。
分布式数据存储更侧重于提供可靠性而非一致性,并且具有一些可以帮助我们以不同方式处理并发访问的功能。
冲突解决和最终的一致性
性能和可用性需要付出代价。您可以在群集的同一资源和不同节点中进行多个更新。当发生这种情况时,你最终会得到两个不同版本的数据(也称为兄弟姐妹),它们可以(或不能)最终收敛。
解决冲突的一些方法是:
最后两项是根据逻辑时间而不是按时间顺序跟踪对象更新的机制(与时间戳一样),从而实现更好的冲突解决。但如果冲突无法解决,则应用程序有责任处理冲突。
CRDT T可以很容易地解决问题。它们是可以在没有协调的情况下独立和同时更新的数据结构,并且在数学上总是可以解决可能导致的不一致问题。 Riak数据类型 就是一个很好的例子。
这里的要点是:
您可以设计系统以了解最终的一致性和冲突解决方案。无需显式锁定即可轻松建模和解决某些问题。
结论
关系数据库是一种长期存在的技术,是处理所有这些问题的非常准确的方法。另一方面,可能具有更高的成本但更高的性能,可用性等,是分布式系统和分布式数据存储,以非常不同的方式处理问题。
以上所述就是小编给大家介绍的《浅谈分布式锁 - Eduardo Colabardini》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 分布式锁原理——redis分布式锁,zookeeper分布式锁
- 漫谈分布式系统(十):初探分布式事务
- 漫谈分布式系统(十):初探分布式事务
- 漫谈分布式系统(二十三):分布式数据仓库
- 分布式系统中的BASE 和 ACID、幂等性、分布式锁、分布式事务与异步消息处理
- 分布式ID系列(4)——Redis集群实现的分布式ID适合做分布式ID吗
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。