并发——分布式锁质量保障总结
一 背景
二 分布式锁介绍
1 什么是分布式锁
2 实现分布式锁的主流方式
基于数据库实现分布式锁,此处的数据库指的是MySQL关系型数据库
基于MySQL锁表 数据库版本号乐观锁
基于缓存实现分布式锁,此处的缓存指的是Redis
基于zookeeper/etcd实现分布式锁
三 质量保障
1 事前质量保障
评估并发风险
技术选型
2 事中保障
CodeReview
1)Redis缓存分布式锁
Redis缓存分布式锁CodeReview注意点
Redis Key
全面梳理业务场景,对于同一共同资源,key要保持一致; key是识别共享资源的唯一键,key的设计既需要能够锁住当前共享资源又不能影响到其他资源;
锁释放
锁一定需明确释放,try/finally 结构加锁解锁,finally内释放锁; 锁只能被加锁的对象释放,此处是经常出问题的点,如下图所示,A加锁被B释放锁,导致锁失效,锁被C抢占到;
锁超时
一定要设置key的超时时间;例如:客户端A 抢到锁后,系统突然异常,A就无法释放锁,变成死锁;设置超时时间就是为了防止此种情况发生,在时间到期后,自动删除key,间接释放锁; 超时时间的设置一般来讲大于服务的最大执行时间即可,但是服务最大的执行时间会受很多因素影响,是不可控的;例如:A服务一般执行时间是30ms,设置的锁超时时间为100ms,受网络影响服务执行时间变成了200ms,在100ms的时候锁就会被释放了;在大部分场景下,开发不会处理此种情况,此种极端情况是否需要处理,需要进行协商;处理方式如下2种: 可以再开启一个线程,为当前超时时间续时,但增加了系统的复杂度; 将过期时间设置非常长,一定能保证逻辑在锁释放之前能够执行完成;此方案简单但是有缺陷,当遇到系统突发异常时,锁无法被释放,只能等待redis key超时,而超时时间又设置的较长,因此在当前时间内谁都无法获取到锁,阻断业务执行,很有可能造成故障;
锁粒度
获取锁失败
2)MySQL数据库锁CR点
数据库版本号乐观锁
where 条件一定要命中索引(最好是主键或者唯一索引),否则会锁表; update table set 中必须要包含version = version + 1; update 返回结果为0时,一定要根据业务场景进行相应的处理,自主重试或者抛异常;
基于MySQL锁表
并发测试
复杂的并发场景,一次请求共享资源存在多个,且前后存在各种依赖关系,此种场景适合于链路级别压测,压测模型需要精心设计。
单一并发场景,一个共享资源,可以处理多次,例如:扣除某个商品的库存,可以反复调用。
可以通过接口压测的方式进行测试,通过查看最终数据是否会存在与预期不一致情况即可; 压测工具:jmeter 即可进行压测(集团可直接采用pas-server进行压测,方便快捷);
单一并发场景,一个共享资源,且只能处理1次,例如:用户只有一次抽奖机会,连续点2次会不会抽2次;
可以利用JVM的并发函数CountDownLatch,CyclicBarrier等,CountDownLatch片段代码:
publicvoidinvokeAllTask(ConcurrencyRequest request, Runnable task) {
final CountDownLatch startCountDownLatch = new CountDownLatch(1);
final CountDownLatch endCountDownLatch = new CountDownLatch(request.getConcurrency());
for (int i = 0; i < request.getConcurrency(); i++) {
Thread t = new Thread(() -> {
try {
startCountDownLatch.await();
try {
task.run();
} finally {
endCountDownLatch.countDown();
}
} catch (Exception ex) {
log.error("异常", ex);
}
});
t.start();
}
startCountDownLatch.countDown();
try {
endCountDownLatch.await();
} catch (InterruptedException ex) {
log.error("线程异常中断", ex);
}
}
利用jmeter的定时器 Synchronizing Timer也可以实现此功能
3 事后保障
数据对账
互动积分体系每个用户的扣除以及增加积分都会落流水表;每个用户目前有多少积分都会放在积分表;只需要把流水表的积分加总和积分表的积分进行对账;
互动任务体系,一笔订单只能推进一个任务,对账只需要检查任务记录中一笔订单是否存在多条记录;
selectcount(*) as task_count,
scene_code,
order_id
from task_record
where unique_id isnotnull
groupby scene_code,
order_id
havingcount(*)> 1
四 总结
梳理并发场景 带着注意点CR 代码 并发测试(非银弹,不是所有场景都具备可测性) 监控对账进行兜底识别并发问题
招聘
CentOS 8 的用户请注意,请尽快切换镜像源!
由于CentOS 8结束了生命周期,官方已经停止CentOS 8的维护,而阿里云镜像站的CentOS Linux公共镜像来源于CentOS官方,所以阿里云镜像站也移除了相应的CentOS 8镜像源。如果您是阿里云CentOS 8镜像源的用户,并且您的业务过渡期仍需要使用CentOS 8中的一些安装包,为了不影响您的使用,建议您切换至CentOS-Vault源, 具体配置请点击阅读原文。
关键词
数据
分布式锁
问题
系统
线程
最新评论
推荐文章
作者最新文章
你可能感兴趣的文章
Copyright Disclaimer: The copyright of contents (including texts, images, videos and audios) posted above belong to the User who shared or the third-party website which the User shared from. If you found your copyright have been infringed, please send a DMCA takedown notice to [email protected]. For more detail of the source, please click on the button "Read Original Post" below. For other communications, please send to [email protected].
版权声明:以上内容为用户推荐收藏至CareerEngine平台,其内容(含文字、图片、视频、音频等)及知识版权均属用户或用户转发自的第三方网站,如涉嫌侵权,请通知[email protected]进行信息删除。如需查看信息来源,请点击“查看原文”。如需洽谈其它事宜,请联系[email protected]。
版权声明:以上内容为用户推荐收藏至CareerEngine平台,其内容(含文字、图片、视频、音频等)及知识版权均属用户或用户转发自的第三方网站,如涉嫌侵权,请通知[email protected]进行信息删除。如需查看信息来源,请点击“查看原文”。如需洽谈其它事宜,请联系[email protected]。