主要思路是用一个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. python中关于正则表达式四

    []   用来暗示一个字符串集合, 1.在这个集合中:字符串可以被 独特列出,例如[amk]将会匹配'a','m'或者'k'. 2.字符串的范围可以被暗示通过给两个字符串和分开它们用一个'-':例如[ ...

  2. Android TabHost的使用

    标签显示界面的主要特点是可以在一个窗口中显示多组标签栏的类容. 在Android系统中,每个标签栏称为一个Tab,而包含多个标签栏的内容就称为TabHost. 通过TabHost的继承结构来看,Tab ...

  3. 类库探源——System.Drawing

    一.System.Drawing 命名空间简述 System.Drawing 命名空间提供访问 GDI+ 的基本功能,更高级的功能在 System.Drawing.Drawing2D,System.D ...

  4. Ngen生成Native代码实战及优缺点分析

    先科普一下,.Net是一个用于Windows的托管代码模型,用于高效构建具有视觉上引人注目的用户体验的应用程序.但这个模型生成的代码并非可执行代码,而是由.Net公共语言运行库环境执行的IL代码.所以 ...

  5. scrapy, 自带命令行调用工具.

    #-*- coding:utf-8 -*- from scrapy import cmdline cmdline.execute("scrapy crawl dmoz".split ...

  6. 04_天气查询_JAX-WS方式_服务端

    [简述] WebService的Java实现共有三种方式:JAX-WS(JAX-RPC).JAXM&SAAJ.JAX-RS. JAX-WS: JAX-WS  的全称为 Java API for ...

  7. 无责任共享 Coursera、Udacity 等课程视频

    本文转载自网络,原作者不详. (本文是用 markdown 写的,访问 https://www.zybuluo.com/illuz/note/71868 获得更佳体验) 程序语言 interactiv ...

  8. C++类的成员初始化列表的相关问题

    在以下四中情况下,要想让程序顺利编译,必须使用成员初始化列表(member initialization list): 1,初始化一个引用成员(reference member): 2,初始化一个常量 ...

  9. zlib压缩解压示例

    #include <stdio.h> #include <string.h> #include <assert.h> #include "zlib.h&q ...

  10. 在阿里云服务器ubuntu14.04运行netcore

    从netcore1.0正式发布就很激动,想要赶紧学习. 最近博客园的一篇文章给了完整的指导非常感谢,但是在实际实现到发布到阿里云服务器遇到一些问题,记录下来. 首先上基础文章http://www.cn ...