redis -- 信号量

信号量

什么是信号量

信号量(Semaphore),有时被称为信号灯,是在多线程环境下使用的一种设施,是可以用来保证两个或多个关键代码段不被并发调用。在进入一个关键代码段之前,线程必须获取一个信号量;一旦该关键代码段完成了,那么该线程必须释放信号量。其它想进入该关键代码段的线程必须等待直到第一个线程释放信号量。

如何使用redis实现信号量

  1. 实现一个简单的信号量

我们使用一个zset(SIGNAL_LOCK_TIMESET_KEY)来保存对某个资源的信号量。使用不同的uuid作为value来标识使用者,使用时间来作为score来进行排序。
(1)将过期的信号量清除掉

jedis.zremrangeByScore(LockUtils.signalLockTimeKey(lockName),0,getEndDate(timeUnit,timeOut).getTime());

(2)将新的信号量插入

jedis.zadd(LockUtils.signalLockTimeKey(lockName),new Date().getTime(),uuid);

(3)获取信号量所在的排名

if(jedis.zrank(LockUtils.signalLockTimeKey(lockName),uuid) < limit){
                return uuid;
            }

(4)如果信号量不在限定的排名,那么移除该信号量

//移除过期的判断
jedis.zrem(LockUtils.signalLockTimeKey(lockName),uuid);

但是这样会有一个问题,如果在分布式系统中有A、B两个用户分别在A、B两台机器上争夺信号量(假设只能有一个人获得到)。B机器和A机器在获取时间的时候是完全相同的,这个时候score就一样,那么不论A用户先获取到信号量还是B用户先获取到信号量,后插入的那个用户因为score和前一个用户相同,那么总会排在前一个用户前面。导致系统就会有两个人获取到信号量。如果在高并发情况下,我们完全不能掌握有多少个用户可以获取到信号量。
2. 实现一个公平的信号量
我们使用三个KEY,一个与前一个相同ZSET(SIGNAL_LOCK_TIMESET_KEY,用来存储key的时间,用来过期),第二个ZSET(SIGNAL_LOCK_SORTED_KEY,value为uuid,score则为一个自增长的值),第三个String(SIGNAL_LOCK_INCR_KEY,一个自增长的key)。自增长的key可以为不同的用户提供不同的排序值,这样就会保证所有的用户都

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值