redis实战之计数信号量(未完)
来源:互联网 发布:mt4 一键下单脚本源码 编辑:程序博客网 时间:2024/05/22 02:21
计数信号量是一种锁,可以让用户限制一项资源最多能够同时被多少个用户访问
计数信号量有如下几个特征:
1. 使用前必须要获取到资源,使用结束后必须要释放资源
2. 获取资源失败后立即将失败结果返回给用户
示例:
构建基本的计数信号量
使用有序集合来构建基本的计数信号量,使用当前时间戳作为分值,将标识值添加到有序集合里面,程序在将标识符添加到有序集合前,清理有序集合中时间戳大于超时数值的标识符
public String acquireSemaphore(Jedis conn,String semname,int limit,long timeout){ String identifier=UUID.randomUUID().toString(); long now=System.currentTimeMillis(); Pipeline pip=conn.pipelined(); pip.zremrangeByScore(semname, 0, now-timeout*1000); pip.zadd(semname, now, identifier); Response<Long>rank=pip.zrank(semname, identifier); pip.syncAndReturnAll(); if ((long)rank.get()<limit) { return identifier; } conn.zrem(semname, identifier); System.out.println("remove:"+identifier); return null; }
释放信号量public Long releaseSemaphore(Jedis conn,String semname,String identifier){ return conn.zrem(semname, identifier); }
这个基本的计数信号量存在一定的问题,在集群或者分布式系统当中,每台计算机的时间都有细微的差异。比如说A机器比B机器慢了10毫秒,在A取走最后一个计数信号量后,B只要在10毫秒内就能取走A所持有的资源
公平信号量
为了消除时间造成的误差,我们需要另外两个数据结构,一个是全局计数器,另一个是记录获得获得资源的顺序sorted set,获取取得资源排名的时候不再利用时间作为分值排名而是利用全局计数器的到的值
一定要注意时间单位的换算,否则会导致超时数据漏删或者多删的情况
//获取资源public String acquireFairSemaphore(Jedis conn,String semname,int limit,long timeout){ String identifier=UUID.randomUUID().toString(); //资源拥有者sorted set String czset=semname+":owner"; //全局计数器 String ctr=semname+":counter"; long now=System.currentTimeMillis(); Transaction trans=conn.multi(); trans.zremrangeByScore(semname.getBytes(), "0".getBytes(), String.valueOf(now-timeout*1000).getBytes()); //trans.zremrangeByScore(semname, 0, now-timeout*1000); ZParams params=new ZParams(); params.weights(1,0); //czset和semname的交集计算 trans.zinterstore(czset, params, czset,semname); trans.incr(ctr); List<Object>results=trans.exec(); int counter=((Long)results.get(results.size()-1)).intValue(); trans=conn.multi(); trans.zadd(semname, now, identifier); trans.zadd(czset, counter,identifier); trans.zrank(czset, identifier); results=trans.exec(); int result=((Long)results.get(results.size()-1)).intValue(); if (result<limit) { return identifier; } trans=conn.multi(); trans.zrem(semname, identifier); trans.zrem(czset, identifier); trans.exec(); return null; }//释放资源public boolean releaseFairSemaphore(Jedis conn,String semname,String identifier){ Transaction trans=conn.multi(); trans.zrem(semname, identifier); trans.zrem(semname+":owner", identifier); List<Object>results=trans.exec(); return (long)results.get(results.size()-1)==1; }
阅读全文
0 0
- redis实战之计数信号量(未完)
- java并发之Semaphore(计数信号量)
- Java并发编程实战--计数信号量(Semaphore)
- Redis实战之Redis + Jedis
- Redis实战之Redis + Jedis
- Redis实战之Redis + Jedis
- Redis实战之Redis + Jedis
- Redis实战之Redis + Jedis
- Redis实战之Redis + Jedis
- Redis实战之Redis + Jedis
- Redis实战之微博点赞
- redis -- 信号量
- Hadoop 实战之单词计数WordCount
- Hadoop 实战之单词计数wordcount
- threads4 计数信号量
- ucos 计数信号量
- 计数信号量__Demo
- JAVA 计数信号量SEMAPHORE
- resultMap(12)
- HDU 1069 dp??
- 【linux 命令】环境启动时访问的配置文件顺序
- 欢迎使用CSDN-markdown编辑器
- hdu5463---King's Game
- redis实战之计数信号量(未完)
- Java中的Lambda表达式
- RAISR(Rapid and Accurate Super Image Resolution)
- 过滤器的原理及配置
- 链表划分
- 算法实现:二进制老鼠测毒
- Android 应用内分屏查看(使用fragment)
- Linux服务(DNS)
- 【SpringCloud】(十四):Feign对Hystrix的支持 fallbackFactory