Redis应用----消息传递

1、摘要

  消息传递这一应用广泛存在于各个网站中,这个功能也是一个网站必不可少的。常见的消息传递应用有,新浪微博中的@我呀、给你评论然后的提示呀、赞赞赞提示、私信呀、甚至是发微博分享的新鲜事;知乎中的私信呀、live发送过来的消息、知乎团队消息呀等等。

 

2、实现方法

  消息传递即两个或者多个客户端在相互发送和接收消息。

  通常有两种方法实现:

  第一种为消息推送。Redis内置有这种机制,publish往频道推送消息、subscribe订阅频道。这种方法有一个缺点就是必须保证接收者时刻在线(即是此时程序不能停下来,一直保持监控状态,假若断线后就会出现客户端丢失信息)

  第二种为消息拉取。所谓消息拉取,就是客户端自主去获取存储在服务器中的数据。Redis内部没有实现消息拉取这种机制。因此我们需要自己手动编写代码去实现这个功能。

  在这里我们,我们进一步将消息传递再细分为一对一的消息传递,多对多的消息传递(群组消息传递)。

【注:两个类的代码相对较多,因此将其折叠起来了】

 

3、一对一消息传递

  例子1:一对一消息发送与获取

  模块要求:

  1、提示有多少个联系人发来新消息

  2、信息包含发送人、时间、信息内容

  3、能够获取之前的旧消息

  4、并且消息能够保持7天,过期将会被动触发删除

  Redis实现思路:

  1、新消息与旧消息分别采用两个链表来存储

  2、原始消息的结构采用数组的形式存放,并且含有发送人、时间戳、信息内容

  3、在推入redis的链表前,需要将数据转换为json类型然后再进行存储

  4、在取出新信息时应该使用rpoplpush来实现,将已读的新消息推入旧消息链表中

  5、取出旧消息时,应该用旧消息的时间与现在的时间进行对比,若超时,则直接删除后面的全部数据(因为数据是按时间一个一个压进链表中的,所以对于时间是有序排列的)

数据存储结构图:

 

PHP的实现代码:

#SinglePullMessage.class.php

  View Code

 

 测试:

  1、发送消息

  #建立test1.php

复制代码
1 include './SinglePullMessage.class.php';
2 $object=new SinglePullMessage('192.168.95.11');
3 #发送消息
4 $sender='boss';     #发送者
5 $to='jane';         #接收者
6 $message='How are you';    #信息
7 $time=time();
8 $arr=array('sender'=>$sender,'message'=>$message,'time'=>$time);
9 echo $object->sendSingle($to,$arr);
复制代码

 

  2、获取新消息

  #建立test2.php

复制代码
 1 include './SinglePullMessage.class.php';
 2 $object=new SinglePullMessage('192.168.95.11');
 3 #获取新消息
 4 $arr=$object->getNewMessage('jane');
 5 if($arr)
 6 {
 7     echo $arr['count']."个联系人发来新消息<br/><hr/>";
 8     $object->dealArr($arr['messageArr']);   
 9 }
10 else
11     echo "无新消息";
复制代码

 

   访问结果:

  3、获取旧消息

  #建立test3.php

复制代码
 1 include './SinglePullMessage.class.php';
 2 $object=new SinglePullMessage('192.168.95.11');
 3 #获取旧消息
 4 $arr=$object->getPreMessage('jane');
 5 if($arr)
 6 {
 7     $object->dealArr($arr);
 8 }
 9 else
10     echo "无旧数据";
复制代码

 

 

 

4、多对多消息传递

  例子2:多对多消息发送与获取(即是群组)

  模块要求:

  1、用户能够自行创建群组,并成为群主

  2、群主可以拉人进来作为群组成员、并且可以踢人

  3、用户可以直接退出群组

  4、可以发送消息,每一位成员都可以拉取消息

  5、群组的消息最大容纳量为5000条

  6、成员可以拉取新消息,并提示有多少新消息

  7、成员可以分页获取之前已读的旧消息

  。。。。。功能就写这几个吧,有需要或者想练习的同学们可以增加其他功能,例如禁言、匿名消息发送、文件发送等等。

  Redis实现思路:

   1、群组的消息以及群组的成员组成采用有序集合进行存储。群组消息有序集合的member存储用户发送的json数据消息,score存储唯一值,将采用原子操作incr获取string中的自增长值进行存储;群组成员有序集合的member存储user,score存储非零数字(在这里这个score意义不大,我的例子代码中使用数字1为群主的score,其他的存储为2。当然这使用这个数据还可以扩展别的功能,例如群组中成员等级)可参考下面数据存储结构简图。

  2、用户所加入的群组也是采用有序集合进行存储。其中,member存储群组ID,score存储用户已经获取该群组的最大消息分值(对应群组消息的score值)

  3、用户创建群组的时候,通过原子操作incr从而获取一个唯一ID

  4、用户在群中发送消息时,也是通过原子操作incr获取一个唯一自增长有序ID

  5、在执行incr时,为防止并发导致竞争关系,因此需要进行加锁操作【redis详细锁的讲解可以参考:Redis构建分布式锁http://www.cnblogs.com/phpstudy2015-6/p/6575775.html

  6、创建群组方法简要思路,任何一个用户都可以创建群组聊天,在创建的同时,可以选择时是否添加群组成员(参数通过数组的形式)。创建过程将会为这个群组建立一个群组成员有序集合(群组信息有序集合暂时不创建),接着将群主添加进去,再将群ID添加用户所参加的群组有序集合中。

数据存储结构图:

 

PHP的代码实现:

#ManyPullMessage.class.php

  View Code

 

测试:

  1、建立createGroupChat.php(测试创建群组功能)

  执行代码并创建568、569群组(群主为jack)

复制代码
1 include './ManyPullMessage.class.php';
2 $object=new ManyPullMessage('192.168.95.11');
3 #创建群组
4 $user='jack';
5 $arr=array('jane1','jane2');
6 $a=$object->createGroupChat($user,$arr);
7 echo "<pre>";
8 print_r($a);
9 echo "</pre>";die;
复制代码

 

 

 

  2、建立addMembers.php(测试添加成员功能)

  执行代码并添加新成员

复制代码
1 include './ManyPullMessage.class.php';
2 $object=new ManyPullMessage('192.168.95.11');
3 $b=$object->addMembers('jack','568',array('jane1','jane2','jane3','jane4'));
4 echo "<pre>";
5 print_r($b);
6 echo "</pre>";die;
复制代码

  3、建立delete.php(测试群主删除成员功能)

复制代码
1 include './ManyPullMessage.class.php';
2 $object=new ManyPullMessage('192.168.95.11');
3 #群主删除成员
4 $c=$object->delMembers('jack', '568', array('jane1','jane4'));
5 echo "<pre>";
6 print_r($c);
7 echo "</pre>";die;
复制代码

  4、建立sendMessage.php(测试发送消息功能)

  多执行几遍,568、569都发几条

复制代码
 1 include './ManyPullMessage.class.php';
 2 $object=new ManyPullMessage('192.168.95.11');
 3 #发送消息
 4 $user='jane2';
 5 $message='go go go';
 6 $groupChatID=568;
 7 $arr=array('sender'=>$user, 'message'=>$message, 'time'=>time());
 8 $d=$object->sendMessage($user,$groupChatID,$arr);
 9 echo "<pre>";
10 print_r($d);
11 echo "</pre>";die;
复制代码

 

  5、建立getNewMessage.php(测试用户获取新消息功能)

复制代码
1 include './ManyPullMessage.class.php';
2 $object=new ManyPullMessage('192.168.95.11');
3 #用户获取新消息
4 $e=$object->getNewMessage('jane2');
5 echo "<pre>";
6 print_r($e);
7 echo "</pre>";die;
复制代码

 

  6、建立getPartMessage.php(测试用户获取某个群组部分消息)

  (多发送几条消息,用于测试。568中共18条数据)

复制代码
1 include './ManyPullMessage.class.php';
2 $object=new ManyPullMessage('192.168.95.11');
3 #用户获取某个群组部分消息
4 $f=$object->getPartMessage('jane2', 568, 1, 10); 
5 echo "<pre>";
6 print_r($f);
7 echo "</pre>";die;
复制代码

 

page=1,size=10

page=2,size=10

测试完毕,还需要别的功能可以自己进行修改添加测试。

这次整理这篇文章相对比较赶,心里已经想着快点整理完赶紧学习其他的技术啦,哈哈22333。各位大神请留步,恳请各位给点学习redis的指导意见,本人职业方向是PHP

转载于:https://www.cnblogs.com/tangshiguang/p/6763139.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值