浅析Redis实现lock互斥访问资源

 Redis是当前很流行的一种开源键值数据库。目前睿思的后台架构在数据库层采用了Redis和MySQL组合的形式,其中Redis主要用来存储状态信息(比如当前种子的peer)和读写频繁的数据。Redis完全运行在内存之上,无lock设计,速度非常快!通过实测,在睿思服务器上读写速度达到3万次/s。

          在高并发的应用中,很多时候我们需要对某些资源进行竞争访问,比如在很多人下载一个热门资源,就可能存在很多请求去修改某个资源的peer信息(就是保存了当前保种人的ip地址和端口号),需要保证某个请求修改peer信息的时候,不允许其他请求修改,否则就会出现数据覆盖的问题。但是Redis没有提供对数据的加锁,所以需要我们通过Redis提供的命令自己实现:


思路一:

       通过get 和set 命令实现
       这中方式很容易想到,就是当每次请求到来时通过get判断这个锁是否存在,如果不存在则set创建。这种方法有一个弊端,由于get和set是两次Redis请求,二者之间有延时,在高并发的环境下,有可能在get检测到锁不存之后在set之前已经被其他线程set,这时当前线程再set,这样锁就失效了。所以这种方法只能应对并发量不是很高的情况。


思路二:

        通过setnx 和 expire命令实现
       在访问需要互斥访问的资源时,通过setnx命令去设置一个lock 键,setnx的作用是判断锁是否存在,如果不存在则创建,返回成功,如果存在则返回失败,服务器返回给客户端,指示客户端稍后重试。expire命令用于给该锁设定一个过期时间,用于防止线程crash,导致锁一直有效,从而导致死锁。例如:设定锁的有效期为100秒,那么即使线程奔溃,在100秒后锁会自动失效。
  1. > setnx lock "lock"
复制代码

如果成功则设置过期时间
  1. >expire lock 100
复制代码

访问互斥资源结束后,删除锁
  1. >del lock
复制代码



思路三:

      通过watch和Redis的事务命令实现
     这种方式的效果和思路二类似。在请求到时先watch改资源锁,然后再通过在事务执行 创建锁的过程,锁的键值能唯一标识改请求(比如用时间+用户标识)。如果当前还有其他线程请求该资源,当判断该锁存在时则返回错误重试(例如睿思BT tracker返回“服务器过载,自动重试的”的提示就属于此类情况)。如果有多个请求同时判断改锁不存在而创建锁,这样也会由于watch了这个锁,导致之前watch的线程执行事务失败,返回客户端自动重试。这样达最终达到了锁的目的。

欢迎拍砖~~
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值