编程培训网站,有哪些免费做简历的网站,自己做的网站如何用手机去查看,外贸公司应该怎样做外贸网站源宝导读#xff1a;大型的信息化系统对数据准确性的要求很高#xff0c;所以经常会使用事务、锁、队列等技术#xff0c;保障高并发下的数据一致性问题。本文将讨论在分布式部署模式下#xff0c;如何利用锁机制保证业务数据准确的技术探索与实践。一、背景分布式场景下的… 源宝导读大型的信息化系统对数据准确性的要求很高所以经常会使用事务、锁、队列等技术保障高并发下的数据一致性问题。本文将讨论在分布式部署模式下如何利用锁机制保证业务数据准确的技术探索与实践。一、背景 分布式场景下的数据一致性问一直是一个非常重要的话题在很多场景中我们需要使用各种技术方案来保证数据的一致性比如分布式事务、分布式存储、分布式锁等。有些业务场景中我们需要保证一个方法在同一时间内只能被一个线程执行来解决一些譬如商品超卖我们ERP中的一房多卖、财务票据号跳票重复等问题。在单机环境中各种语言其实提供了较多并发处理相关的特性比如.Net中的lock、Monitor、Mutex等但是这些特性在分布式场景中就有问题了。针对分布式锁的实现目前比较常用的有这样几种数据库实现、缓存实现redismemcached、Zookeeper实现、以及etcd等。二、利用数据库实现分布式锁基于数据库唯一约束 应该是分布式锁最简单的方式之一创建一张锁表通过数据库的唯一约束当我们需要锁住某个场景时插入一条数据插入成功则获锁成功可以执行后续操作操作完成后删除记录来释放锁资源。我们老系统即提供了此种类型的锁来处理各类锁场景。数据库约束实现的锁问题强依赖数据库单点无高可用数据库宕掉则业务不可用。并发支撑不够单点的数据库成为瓶颈。非阻塞的没有获得锁的无法排队直接失败。非重入的同一线程无法再次获取已经得到的锁。没有失效时间如果解锁失败则业务受阻。利用数据库特性实现 利用SQL Server提供的应用锁来实现锁定使用sp_getapplock加锁sp_releaseappLock释放锁随事务提交或回滚 相对于数据库唯一约束实现来说更加简便好控制不占用数据库空间而且支持阻塞特性实现排队等待且业务失败自动释放回滚目前ERP使用此方案来实现锁控制开箱即用不依赖其他服务。三、利用缓存实现分布式锁 相比于数据库实现基于缓存的锁实现性能更好可以支撑更高的并发同时缓存的集群部署可以保证高可用。MemCached 利用Memcached的原子命令add操作只有add成功才表示获取到锁。由于MemCached采用LUR置换策略可能导致并未过期的锁信息被删除且无持久化。Redis 同样利用其原子操作来处理锁定场景官方也提供了Relock的dotnet实现。 RedLock算法提出通过N/2 1半数以上实例获取到锁并且获取时间小于锁过期时间则认为获取到锁来解决Master-Slave模式下主从同步失败导致的锁安全问题但实际上还是可能由于某一节点未落盘宕机或则时钟不同步导致多客户端获锁成功的问题本身AP想完全CP就比较别扭了这也是RedLock被质疑的地方。 同时通过retry机制实现阻塞间隔一段时间重试获锁过程不过重试间隔不好把握这一点java的实现Redisson提供了另外的方式在申请锁失败后阻塞线程通过订阅解锁消息来释放阻塞并重试获锁过程同时也可以利用watch dog来实现锁延时。四、利用Zookeeper实现分布式锁 可以通过其有序临时节点监听节点删除来实现分布式锁通过仅监听上一个节点的删除事件避免羊群效应具体流程如下图可基于Zookeeper的客户端按照上述流程实现也可以使用ZookeeperNet.Recipes提供的锁相比于redis性能弱于redis但健壮性更好更能保障数据一致。五、利用etcd实现分布式锁 etcd可能没有ZK那么被大众熟知但说它为K8s提供状态配置存储就明白了。 和ZK功能相似使用Raft保证数据一致性相较于zookeeperecd使用GO编写更加轻便其效率也更高在etcd v3版本中已提供了lock的封装。官方推荐的dotnet的客户端如下dotnet-etcd使用google的gRPC框架封装了客户端各操作包括V3提供的锁六、总结 没有完美的技术,只有合适的选择,就如CAP原则最多只能同时满足两种特性一样,复杂性、高可用、高性能等方面很难同时满足选择适合当前业务要求的即可。怕的是没有意识到并发情况会产生数据不一致的问题导致的超卖现象以及跳号重复等问题的产生之前处理过比较多的反馈希望通过此篇文章让大家意识到分布式环境下可能出现的数据不一致的问题并选择合适的方案来解决。------ END ------作者简介王同学 架构师目前负责售楼产品的相关架构规划和设计工作。也许您还想看.NET Core MVC扩展实践如何使用有序GUID提升数据库读写性能.Net最小工作线程对应用程序性能的影响ERP缓存实践经验分享