redis+PHP实现的一个优先级去重队列
主要思路是用一个set做前端去重缓冲, 若干个list做后端的多优先级消息队列, 用一个进程来进行分发, 即从set中分发消息到队列.
set缓冲的设计为当天有效, 所以有个零点问题,有可能在零点前set中刚放进去的消息没有分发即失效, 这一点可以用另一个进程弥补处理前一天的遗留消息和删除前一天的缓冲
<?php /**
* @author
*
*/
class MsgQuery {
// TODO - Insert your code here
const KEY_CACHE_PREFIX = 'mass.query.cache'; // 消息缓冲key前缀
const KEY_QUERY_PREFIX = 'mass.query.lv'; // 消息key
const KEY_CACHE_DEAL_PREFIX = 'mass.query.deal'; // 已处理缓冲key前缀
const SCORE_NUM = 5; // 优先级划分数目
const MIN_SCORE = 1; // 最小优先级
static $MAX_SCORE;
static $instance = null;
private $redis; public static function getInstance($redis) {
if (null == self::$instance) {
self::$instance = new MsgQuery ( $redis );
}
return self::$instance;
} /**
* 添加消息到消息缓冲区
* @param int $score 优先级(1-5)
* @param string $msg 消息
*/
public function add($score, $msg) {
// 添加到消息缓冲
$socre = intval ( $score );
if ($socre < self::MIN_SCORE) {
$score = self::MIN_SCORE;
}
if ($score > self::$MAX_SCORE) {
$score = self::$MAX_SCORE;
}
$cacheKey = self::KEY_CACHE_PREFIX . date ( 'Ymd' );
$cacheData = array (
'score' => $score,
'msg' => $msg
);
$this->redis->sAdd ( $cacheKey, serialize ( $cacheData ) );
} /**
* 将消息从缓冲区移动到相应的优先级队列中
*/
public function moveToQuery() {
// 获取当前缓冲区没有入队列的消息
$dealKey = self::KEY_CACHE_DEAL_PREFIX.date('Ymd');
$cacheKey = self::KEY_CACHE_PREFIX.date('Ymd');
$msgs = $this->redis->sDiff($cacheKey, $dealKey);
foreach ($msgs as $cachedData){
// 放入已处理集合
$this->redis->sAdd ( $dealKey, $cachedData );
// 压入相应的优先级队列
$cachedData = unserialize($cachedData);
$score = $cachedData['score'];
$msg = $cachedData['msg'];
$queryKey = self::KEY_QUERY_PREFIX.$score;
$this->redis->rPush($queryKey, $msg);
}
unset($cachedData);
} /**
* 从队列阻塞式出栈一个最高优先级消息
* @return string msg
*/
public function bPop(){
$queryKeys = array();
for($score=self::$MAX_SCORE;$score>=self::MIN_SCORE;$score--){
$queryKeys[] = self::KEY_QUERY_PREFIX.$score;
}
$msg = $this->redis->blPop($queryKeys, 0);
return $msg[1];
} private function __construct($redis) {
$this->redis = $redis;
$this->redis->connect ();
self::$MAX_SCORE = self::MIN_SCORE + self::SCORE_NUM - 1;
} private function __destruct() {
$this->redis->close ();
}
} ?>
redis+PHP实现的一个优先级去重队列的更多相关文章
- 带优先级的队列 - PHP实现
很久以前写的一个功能,当时需要一个优先级的队列,特用新学的swoole写了一个简单的demo,仅满足当时的需求. 功能说明: 完全参考httpsqs增加优先级参数level 例: ...
- Redis学习之实现优先级消息队列
很久没有写博客了,最近简单的学习了一下Redis,其中学习了一下用Redis实现优先级消息队列.关于更多更为详细的可以在www.redis.cn找到相关资料. 对于熟悉Redis的童鞋提到队列很自然的 ...
- 使用deque模块固定队列长度,用headq模块来查找最大或最小的N个元素以及实现一个优先级排序的队列
一. deque(双端队列) 1. 使用 deque(maxlen=N)会新建一个固定大小的队列.当新的元素加入并且这个队列已满的时候,最老的元素会自动被移除掉 >>> from c ...
- [PY3]——实现一个优先级队列
import heapq class PriorityQueue: def __init__(self): self._queue=[] self._index=0 def push(self,ite ...
- 一个用消息队列 的人,不知道为啥用 MQ,这就有点尴尬
消息队列 为什么写这篇文章? 博主有两位朋友分别是小A和小B: 小A,工作于传统软件行业(某社保局的软件外包公司),每天工作内容就是和产品聊聊需求,改改业务逻辑.再不然就是和运营聊聊天,写几个SQL, ...
- RabbitMQ学习笔记五:RabbitMQ之优先级消息队列
RabbitMQ优先级队列注意点: 1.只有当消费者不足,不能及时进行消费的情况下,优先级队列才会生效 2.RabbitMQ3.5以后才支持优先级队列 代码在博客:RabbitMQ学习笔记三:Java ...
- Redis 竟然能用 List 实现消息队列
分布式系统中必备的一个中间件就是消息队列,通过消息队列我们能对服务间进行异步解耦.流量消峰.实现最终一致性. 目前市面上已经有 RabbitMQ.RochetMQ.ActiveMQ.Kafka等,有人 ...
- 使用LinkedList模拟一个堆栈或者队列数据结构
使用LinkedList模拟一个堆栈或者队列数据结构. 堆栈:先进后出 如同一个杯子. 队列:先进先出 如同一个水管. import java.util.LinkedList; public cl ...
- 使用Condition Variables 实现一个线程安全队列
使用Condition Variables实现一个线程安全队列 测试机: i7-4800MQ .7GHz, logical core, physical core, 8G memory, 256GB ...
随机推荐
- ImageButton 在IE 10 下的异常
最近在项目中遇到一个棘手问题,在IE10中,一些图片按钮点了毫无反应,其他浏览器(包括IE9)都正常:查看后台,发现如下异常信息: Input string was not in a correct ...
- 强大的游戏开发工具Unity3D推出2D开发工具,unity将混合3D与2D开发
2013 Unity全球开发者大会(Unite 2013)于2013年8月28日在温哥华隆重开幕,会上Unity全球CEO David Helgason在Keynote上宣布Unity 4.3版本即将 ...
- 记:mysql 连接超时解决办法
错误描述:Timeout in IO operation 原连接字符串为:Server=182.180.50.118;port=3306;Database=test;Uid=root;Pwd=123; ...
- 八卦某 G 的前端开发方式及流程
他山之石,可以攻玉. 话说本人从毕业到现在一直在某 B 公司工作,前些年折腾过不少开发方式和工具,但总觉得或许有更好的方案,所以很好奇其它公司内部是如何工作的,我曾经浏览过某 Y 公司内部无所不包 ...
- MySql免安装版配置方法
第1步:下载如下图安装包 第2步:解压mysql压缩包,然后进入解压后的安装包 将my-default.ini复制一份,并改名为my.ini(我已经完成) 把下面内容复制到my.ini,并保存 [cl ...
- Hibernate不同DB的日期查询
Java web项目开发,ORM层用的是Hibernate,用HQL语句查询不同数据库时,日期时间比较还是有所区别的. 1.在Mysql数据库时,是这样写的: 上面是个代码拼串截图,翻译一下是这样的: ...
- (转 部分修改) IOS 手势密码(简单版)
// // Created by wangtouwang on 15/4/7. // Copyright (c) 2015年 wangtouwang. All rights reserved. // ...
- 解决Mysql的主从数据库没有同步的两种方法
今天发现Mysql的主从数据库没有同步 先上Master库: mysql>show processlist; 查看下进程是否Sleep太多.发现很正常.show master status; ...
- 网站开发常用jQuery插件总结(八)标签编辑插件Tagit
一.Tagit插件功能 提高网站交互性,增加用户体验.至于其它的功能,还真没有.用一个input text就可以替换了它.但是text没有输入提示功能,而tagit拥有这个功能.官方示例如下图: 将关 ...
- SQL Cursor(游标)
1.游标在数据表没有id(identity(1,1))时好用,但是游标会吃更多的内存,减少可用的并发,占用宽带,锁定资源,当然还有更多的代码量 2.如果能不用游标,尽量不要使用游标,用完用完之后一定要 ...