主要思路是用一个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实现的一个优先级去重队列的更多相关文章

  1. 带优先级的队列 - PHP实现

    很久以前写的一个功能,当时需要一个优先级的队列,特用新学的swoole写了一个简单的demo,仅满足当时的需求. 功能说明: 完全参考httpsqs增加优先级参数level 例:           ...

  2. Redis学习之实现优先级消息队列

    很久没有写博客了,最近简单的学习了一下Redis,其中学习了一下用Redis实现优先级消息队列.关于更多更为详细的可以在www.redis.cn找到相关资料. 对于熟悉Redis的童鞋提到队列很自然的 ...

  3. 使用deque模块固定队列长度,用headq模块来查找最大或最小的N个元素以及实现一个优先级排序的队列

    一. deque(双端队列) 1. 使用 deque(maxlen=N)会新建一个固定大小的队列.当新的元素加入并且这个队列已满的时候,最老的元素会自动被移除掉 >>> from c ...

  4. [PY3]——实现一个优先级队列

    import heapq class PriorityQueue: def __init__(self): self._queue=[] self._index=0 def push(self,ite ...

  5. 一个用消息队列 的人,不知道为啥用 MQ,这就有点尴尬

    消息队列 为什么写这篇文章? 博主有两位朋友分别是小A和小B: 小A,工作于传统软件行业(某社保局的软件外包公司),每天工作内容就是和产品聊聊需求,改改业务逻辑.再不然就是和运营聊聊天,写几个SQL, ...

  6. RabbitMQ学习笔记五:RabbitMQ之优先级消息队列

    RabbitMQ优先级队列注意点: 1.只有当消费者不足,不能及时进行消费的情况下,优先级队列才会生效 2.RabbitMQ3.5以后才支持优先级队列 代码在博客:RabbitMQ学习笔记三:Java ...

  7. Redis 竟然能用 List 实现消息队列

    分布式系统中必备的一个中间件就是消息队列,通过消息队列我们能对服务间进行异步解耦.流量消峰.实现最终一致性. 目前市面上已经有 RabbitMQ.RochetMQ.ActiveMQ.Kafka等,有人 ...

  8. 使用LinkedList模拟一个堆栈或者队列数据结构

    使用LinkedList模拟一个堆栈或者队列数据结构. 堆栈:先进后出  如同一个杯子. 队列:先进先出  如同一个水管. import java.util.LinkedList; public cl ...

  9. 使用Condition Variables 实现一个线程安全队列

    使用Condition Variables实现一个线程安全队列 测试机: i7-4800MQ .7GHz, logical core, physical core, 8G memory, 256GB ...

随机推荐

  1. tomcat7.0 的配置

    一.安装JDK 1.7 1.添加环境变量:在 我的电脑->属性->高级->环境变量 2.新建系统变量,变量名:JAVA_HOME 变量值:C:\Program Files\Java\ ...

  2. ASP.NET 设计模式中依赖倒置原则

    依赖倒置原则 A.高层次的模块不应该依赖于低层次的模块,他们都应该依赖于抽象. B.抽象不应该依赖于具体,具体应该依赖于抽象. 依赖倒置原则 A.高层次的模块不应该依赖于低层次的模块,他们都应该依赖于 ...

  3. linux x64下编译libjpeg,libpng,zlib

    libJpeg编译: 下载libjpeg源码:http://www.ijg.org/,下载jpegsrc.v9a.tar.gz 解压源码,命令:tar -zxvf jpegsrc.v9a,源码文件夹为 ...

  4. ios PromiseKit

    简介: 高级开发是高度异步的,PromiseKit收集了一些帮助函数,让我们开发过程中使用的典型异步模式更加令人愉悦. 1.通过pod安装promisekit: 2. promise.h介绍 @imp ...

  5. java之内存管理

    对于JVM的垃圾回收机制来说,是否回收一个对象的标准在于:是否还有引用变量引用该对象,只要有引用变量引用该对象,垃圾回收机制就不会回收它. 强引用:创建一个对象,并把这个对象赋给一个引用变量.这种引用 ...

  6. 数学符号π (Pi)、Σ(Capital Sigma)、μ (Mu) 、σ(sigma)、∏(capital pi), ∫(Integral Symbol)的来历

    1.π (Pi; periphery/周长) March 14 marks Pi Day, the holiday commemorating the mathematical constant π ...

  7. docker 中搭建tomcat

    关于docker中tomcat的搭建,没有什么多说的,直接下载官方镜像 docker pull tomcat  (可能会下载到好几个镜像,就是tag不同,有知道为什么的可以告诉我) 然后我看的  ht ...

  8. spring的基本配置

    一:web.xml (1)spring mvc的配置 <servlet> <description>spring mvc servlet</description> ...

  9. 数据库开发 MySQL

    MySQL是Web世界中使用最广泛的数据库服务器.SQLite的特点是轻量级.可嵌入,但不能承受高并发访问,适合桌面和移动应用.而MySQL是为服务器端设计的数据库,能承受高并发访问,同时占用的内存也 ...

  10. 网站开发常用jQuery插件总结(11)折叠插件Akordeon

    实现折叠菜单,可以完全不使用插件.如果使用jquery的话,实现起来也比较简单,我们只需要定义折叠菜单的样式,然后使用jquery中的渐隐渐现就可以了.如果我们自己写折叠菜单,可以方便的使用我们自己的 ...