redis是什么东西就不多说了,网上文章一搜一大堆。
首先来说一下我要实现的功能:
类似一个消息中转站吧,如果有人要发送消息,先将消息发到我这里来,然后我这边进行转发,为的就是有一个统一的管理和修改时方便,
而且所有的消息有优先级,也会有定时发送(如果同一时间消息过多,则会有延迟)
思路:
首先一个是将这两个分为两个队列来实现, 一个用来实现消息优先级,一个来实现定时发送
用的是redis的有序集合,用zadd添加时,将score比做是优先级,也可以用时间戳来当做score,用来表示时间
PHP 版本简易实现
将消息加入优先级的队列,将1,2替换为时间就是定时发送的队列了
1 |
<span style="color:#008080;line-height:1.5 !important;">1</span> <span style="color:#800080;line-height:1.5 !important;">$redis</span> = <span style="color:#0000FF;line-height:1.5 !important;">new</span><span style="line-height:1.5 !important;"> Redis(); </span><span style="color:#008080;line-height:1.5 !important;">2</span> <span style="color:#800080;line-height:1.5 !important;">$redis</span>->connect('127.0.0.1', 6379<span style="line-height:1.5 !important;">); </span><span style="color:#008080;line-height:1.5 !important;">3</span> <span style="color:#800080;line-height:1.5 !important;">$redis</span>->zAdd('zset1', 1, 'message'<span style="line-height:1.5 !important;">); </span><span style="color:#008080;line-height:1.5 !important;">4</span> <span style="color:#800080;line-height:1.5 !important;">$redis</span>->zAdd('zset1', 2, 'message2'); |
从队列中取出数据
1 |
<span style="color:#008080;line-height:1.5 !important;">1</span> <span style="color:#800080;line-height:1.5 !important;">$redis</span>->zRevRangeByScore('zset1, '+inf', '-inf', array('withscores'=>false, 'limit'=>array(0,20))); |
这条语句表示从zset1这个队列里按照score从最大(+inf)到最小(-inf)的排序中取出20条,不带score,如果想要从小到大可以用 zRangeByScore
如果你想让这些都运行在命令行下,可以参考下面来,当然这些是经过删减的
1 |
<span style="color:#008080;line-height:1.5 !important;"> 1</span> <?<span style="line-height:1.5 !important;">php </span><span style="color:#008080;line-height:1.5 !important;"> 2</span> <span style="color:#0000FF;line-height:1.5 !important;">while</span> (<span style="color:#0000FF;line-height:1.5 !important;">true</span><span style="line-height:1.5 !important;">) { </span><span style="color:#008080;line-height:1.5 !important;"> 3</span> <span style="color:#800080;line-height:1.5 !important;">$pid</span> =<span style="line-height:1.5 !important;"> pcntl_fork(); </span><span style="color:#008080;line-height:1.5 !important;"> 4</span> <span style="color:#0000FF;line-height:1.5 !important;">if</span> (<span style="color:#800080;line-height:1.5 !important;">$pid</span> == -1<span style="line-height:1.5 !important;">) { </span><span style="color:#008080;line-height:1.5 !important;"> 5</span> <span style="color:#0000FF;line-height:1.5 !important;">echo</span> <span style="color:#008080;line-height:1.5 !important;">date</span>('Y-m-d H:i:s') . "fork失败!\n"<span style="line-height:1.5 !important;">; </span><span style="color:#008080;line-height:1.5 !important;"> 6</span> } <span style="color:#0000FF;line-height:1.5 !important;">else</span> <span style="color:#0000FF;line-height:1.5 !important;">if</span> (<span style="color:#800080;line-height:1.5 !important;">$pid</span> == 0<span style="line-height:1.5 !important;">) { </span><span style="color:#008080;line-height:1.5 !important;"> 7</span> <span style="color:#800080;line-height:1.5 !important;">$redis</span> = <span style="color:#0000FF;line-height:1.5 !important;">new</span><span style="line-height:1.5 !important;"> Redis(); </span><span style="color:#008080;line-height:1.5 !important;"> 8</span> <span style="color:#800080;line-height:1.5 !important;">$redis</span>->connect('127.0.0.1', 6379<span style="line-height:1.5 !important;">); </span><span style="color:#008080;line-height:1.5 !important;"> 9</span> <span style="color:#800080;line-height:1.5 !important;">$redis</span>->zRevRangeByScore('zset1', '+inf', '-inf', <span style="color:#0000FF;line-height:1.5 !important;">array</span>('withscores'=><span style="color:#0000FF;line-height:1.5 !important;">false</span>, 'limit'=><span style="color:#0000FF;line-height:1.5 !important;">array</span>(0,20<span style="line-height:1.5 !important;">))); </span><span style="color:#008080;line-height:1.5 !important;">10</span> <span style="color:#0000FF;line-height:1.5 !important;">exit</span><span style="line-height:1.5 !important;">; </span><span style="color:#008080;line-height:1.5 !important;">11</span> } <span style="color:#0000FF;line-height:1.5 !important;">else</span><span style="line-height:1.5 !important;"> { </span><span style="color:#008080;line-height:1.5 !important;">12</span> pcntl_wait(<span style="color:#800080;line-height:1.5 !important;">$status</span><span style="line-height:1.5 !important;">); </span><span style="color:#008080;line-height:1.5 !important;">13</span> <span style="line-height:1.5 !important;"> } </span><span style="color:#008080;line-height:1.5 !important;">14</span> } |
pcntl_fork是PHP中的生成子进程,当调用该函数时,会返回一个进程pid,当pid为0时表明是在子进程中,所以把要执行的东西全放这里
线上的一个项目,运行几个月了,用子进程方式还没有出过问题,也没挂过,相当不错