分布式锁滥用线上事故回顾

分布式锁概念

分布式锁是控制分布式系统之间同步访问共享资源的一种方式。在分布式系统中,常常需要协调他们的动作。如果不同的系统或是同一个系统的不同主机之间共享了一个或一组资源,那么访问这些资源的时候,往往需要互斥来防止彼此干扰来保证一致性,在这种情况下,便需要使用到分布式锁。在分布式系统中,常常需要协调他们的动作。如果不同的系统或是同一个系统的不同主机之间共享了一个或一组资源,那么访问这些资源的时候,往往需要互斥来防止彼此干扰来保证一致性,这个时候,便需要使用到分布式锁。

事故详情

背景:最近发生一个线上问题,A系统tomcat到codis的连接数几分钟内就能从飙升到200,因为连接数超限会被自动踢出可用服务序列,导致A系统几台tomcat陆续无法提供服务,页面端显示产品列表无数据。导致tomcat和codis连接数只增不减,原因是:

A系统给B系统提供的一个接口(从方法名看是推荐产品),用户一进入App就调用该接口,所以调用频率较高。这个接口使用分布式锁在lock和unlock代码中间处理的业务逻辑是从数据库读出推荐商品list然后放到缓存里面。某种原因(如:线程死掉、服务器重启、该tomcat和codis之间断网)导致没执行到unlock,redis锁的默认失效时间300秒,所以这个锁(也就是redis的key)这300秒内一直存活,如果说获取锁失败后立即释放链接也没问题,但是框架里面有个sleep 3秒后继续重试获取锁,这样就有个问题:

如果获取锁失败那么这个codis连接就一直存在,并不断尝试获取锁,所以重试机制应该有个度。当新的用户访问到来tomcat一直再建连接,导致5分钟后连接数到200个。

解决措施

首先这个因为逻辑不应该使用分布式锁,分布式锁是为分布式系统的多进程在处理共享资源时使用,互斥来防止彼此干扰来保持一致性,此时需要利用锁的技术控制某一时刻修改数据的进程。需求是把推荐的公共数据缓存不应该采用用户触发的被动式,应该采用主动刷新缓存的方式(调用次数比用户触发可控)。这个操作只是select数据放缓存不涉及数据干扰的问题,所以不应该画蛇添足的用锁。

设置codis的key默认过期时间为20秒,使锁尽快释放;

各个系统梳理使用分布式锁的地方进行改进,并根据情况设置一个小于20秒的锁失效时间;

类似数据库、codis的连接不能把connection一直持有做自己的业务逻辑,后续操作(比如重试)宁可断开后从连接池再获取,虽然耗费点资源也不能一直占有,因为自己的业务逻辑不知什么时候就超时或者异常。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20181214F16ISX00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

同媒体快讯

扫码关注云+社区

领取腾讯云代金券