本人最近需要实现一个功能,就是类似新浪微博评论的“查看会话”的功能:一个大V发布一则微博,评论下面会有N多个fans进行评论。而当网友A评论时,网友B回复A,网友C又可能回复B,网友A还可能回复B或C,现在只考虑A,B,C(甚至会有更多的网友参与回复)……这时候,网友A,B,C之间就构成了一个“会话”了。而当你点击“查看会话”后,则会弹出一个按时间轴排序的对话框,会把会话相关的网友及其评论或回复内容组织起来。类似的情形还常见于各大社群网站,如在QQ空间发布说说,各个好友相互回复的情形等等……
下面是查看会话的情形截图:
现在我做的借鉴了查看会话的功能,最后也实现了,最主要的灵魂是“时间戳”,因为它是排列各个消息的依据;而标识会话的字段则是会话流水号,它是每条消息都会有且都相同的。
首先,我把每一条消息抽象成map的数据结构,每条消息包括消息发送者,会话流水号(每条消息都相等,在一个消息会话中唯一,消息ID,消息内容,发布时间等):
//会话的发起者 Map poster = new HashMap(); poster.put("userid", "user001"); poster.put("userName", "Lily"); poster.put("infoSeqNo", "INFO20150815"); poster.put("postTime", "2015-08-15 20:26:30"); poster.put("info", "今天很开心"); poster.put("infoId", "info001"); Map respondent1 = new HashMap(); respondent1.put("userid", "user002"); respondent1.put("userName", "Tom"); respondent1.put("infoSeqNo", "INFO20150815"); respondent1.put("answerTime", "2015-08-15 20:28:40"); respondent1.put("info", "是吗"); respondent1.put("replyTarget", "user001"); respondent1.put("infoId", "info002"); Map respondent2 = new HashMap(); respondent2.put("userid", "user003"); respondent2.put("userName", "Kay"); respondent2.put("infoSeqNo", "INFO20150815"); respondent2.put("answerTime", "2015-08-15 20:30:27"); respondent2.put("info", "她肯定很开心啦,因为……"); respondent2.put("replyTarget", "user002"); respondent2.put("infoId", "info003"); Map respondent3 = new HashMap(); respondent3.put("userid", "user001"); respondent3.put("userName", "Lily"); respondent3.put("infoSeqNo", "INFO20150815"); respondent3.put("answerTime", "2015-08-15 20:38:40"); respondent3.put("info", "恩,今天去玩了"); respondent3.put("replyTarget", "user003"); respondent3.put("infoId", "info004");
下面把他们存入redis
Jedis jedis = xxx.getRedis();//从池中得到redis实例,具体方法略。。 //以会话流水号以及消息id作为key,消息map作为value jedis.hmset((String)respondent1.get("infoSeqNo") + respondent1.get("infoId"), respondent1); jedis.hmset((String)respondent2.get("infoSeqNo") + respondent2.get("infoId"), respondent2); jedis.hmset((String)respondent3.get("infoSeqNo") + respondent3.get("infoId"), respondent3); jedis.hmset((String)poster.get("infoSeqNo") + poster.get("infoId"), poster);
接下来就是根据会话流水号来得到按时间戳排序出一个消息会话了<测试刚刚存入redis的消息,以会话流水号infoSeqNo=INFO20150815为入口:
Jedis jedis = xxx.getJedis(); String infoSeqNo = "INFO20150815"; Set<String> keys = jedis.keys(infoSeqNo + "*"); List<String> keyss = new ArrayList<String>(keys); String postTime = ""; List<String> times = new ArrayList<String>();//存放所有时间(发帖以及回复)的集合 Set<String> users = new HashSet<String>(); Map<String, Map> msg = new HashMap<String, Map>(); Map<String, String> target = new HashMap<String, String>(); List<String> routes = new ArrayList<String> (); for(String key : keys) { Map dto = jedis.hgetAll(key); if(dto.containsKey("postTime")) {//表明是会话的发起者 postTime = jedis.hget(key, "postTime"); // times.add(postTime); String userName = jedis.hget(key, "userName"); keyss.remove(key); target.put(jedis.hget(key, "userid"), jedis.hget(key, "username")); routes.add("【" + postTime + "】 " + userName + ": " + jedis.hget(key, "info")); // System.out.println("【" + postTime + "】 " + userName + ": " + msg); }else{ String answerTime = jedis.hget(key, "answerTime"); target.put(jedis.hget(key, "userid"), jedis.hget(key, "userName")); msg.put(answerTime, jedis.hgetAll(key)); times.add(answerTime); } } // System.out.println("发帖时间:" + postTime + " 所有时间的集合:" + times // + "时间map:" + msg + " target的对应关系: " + target); // int size = keyss.size(); String time = ""; for(int i=0; i<size; i++ ) { String answerTime = ""; if(i == 0) { answerTime = getCloseTime(postTime, times); }else { answerTime = getCloseTime(time, times); } time = getCloseTime(answerTime, times); Map info = msg.get(answerTime); String username = (String) info.get("userName"); String targetUser = target.get(info.get("replyTarget")); routes.add("【" + answerTime + "】 " + username + " 回复 " + targetUser + " :" + info.get("info")); times.remove(answerTime); } for(String str : routes) { System.out.println(str); }
其中,getCloseTime方法用于从一个时间集合中找到与给定时间最为接近的时间:
//此方法是用来找到距离给定时间最相近的时间 public static String getCloseTime(String time, List<String> times) { String df = "yyyy-MM-dd hh:mm:ss"; String closeTime = times.get(0); Date date = StringToDate(time, df);//具体方法略 Date dateTmp = StringToDate(times.get(0), df); double dif = Math.abs(date.getTime() - dateTmp.getTime()); for(int i=1; i<times.size(); i++) { Date d = StringToDate(times.get(i), df); double diff = Math.abs(date.getTime() - d.getTime()); if(diff <= dif) { closeTime = times.get(i); } dif = diff; } return closeTime; }
测试结果:
【2015-08-15 20:26:30】 Lily: 今天很开心
【2015-08-15 20:28:40】 Tom 回复 Lily :是吗
【2015-08-15 20:30:27】 Kay 回复 Tom :她肯定很开心啦,因为……
【2015-08-15 20:38:40】 Lily 回复 Kay :恩,今天去玩了
说明,用redis做的仿“查看会话”的功能得以实现!
可以把infoSeqNo(会话流水号)作为参数,把上述代码抽离出一个方法来。
相关推荐
亿级流量新浪微博与微信Redis架构实战
大纲 • Redis 简介 • 新浪微博中的Redis实践 • 好友关系 • 计数器 • 经验教训
redis使用用及优化建议 redis不是万能的:合理的业务选型 明确redis业务使用规范 按照业务线独立部署:避免混用 线上版本尽量统一 拥抱需求,持续优化
新浪微博开放平台中的Redis实践_大数据时代feed架构_微博消息系统架构演进_互联网公司技术架构资料.新浪微博.微博架构与平台安全_构建高性能的微博系统——再谈新浪微博架构 演讲视频,PPT,一些收集的博客地址等
Redis 31.构建微博(中).flv
Redis 32.构建微博(下).flv
Redis 30.构建微博(上).flv
新浪微博大规模redis集群方案优化历程,技术经验分享。
新浪微博开放平台redis 实践,,,,,为点资源分..上传资料..
本文实例讲述了PHP使用redis消息队列发布微博的方法。分享给大家供大家参考,具体如下: 在一些用户发布内容应用中,可能出现1秒上万个用户同时发布消息的情况,此时使用mysql可能会出现” too many connections”...
本文实例讲述了redis+php实现微博发布与关注功能。分享给大家供大家参考,具体如下: 数据结构: set post:postid:3:time timestamp set post:postid:3:userid 5 set post:postid:3:content 测试发布哈哈哈哈 incr...
微博的Redis定制之路 微博的Redis定制之路 微博的Redis定制之路
新浪微博redis技术演化,介绍新浪在使用Redis过程的经验与总结,值得所有使用Redis的同学学习。
本文实例讲述了redis+php实现微博列表功能。分享给大家供大家参考,具体如下: 个人主页显示微博列表(自己及关注人的微博列表) /*获取最新的50微博信息列表,列出自己发布的微博及我关注用户的微博 *1.根据推送的...
主要介绍了redis+php实现微博注册与登录功能,结合实例形式分析了php结合redis实现微博注册及登录相关操作步骤与实现技巧,需要的朋友可以参考下
唐福林,新浪微博开放平台资深工程师, 新浪微博开放平台中的Redis实践.pdf
基于SpringBoot+Redis实现的仿QQ伪桌面聊天系统,完美运行,适合个人研究学习,本科毕设、课程设计等 基于SpringBoot+Redis实现的仿QQ伪桌面聊天系统,完美运行,适合个人研究学习,本科毕设、课程设计等 基于...