设为首页 收藏本站
查看: 1101|回复: 0

[经验分享] 用redis实现仿新浪微博“查看会话”功能

[复制链接]

尚未签到

发表于 2016-12-21 07:36:47 | 显示全部楼层 |阅读模式
  本人最近需要实现一个功能,就是类似新浪微博评论的“查看会话”的功能:一个大V发布一则微博,评论下面会有N多个fans进行评论。而当网友A评论时,网友B回复A,网友C又可能回复B,网友A还可能回复B或C,现在只考虑A,B,C(甚至会有更多的网友参与回复)……这时候,网友A,B,C之间就构成了一个“会话”了。而当你点击“查看会话”后,则会弹出一个按时间轴排序的对话框,会把会话相关的网友及其评论或回复内容组织起来。类似的情形还常见于各大社群网站,如在QQ空间发布说说,各个好友相互回复的情形等等……
  下面是查看会话的情形截图:
  
DSC0000.png
 
  现在我做的借鉴了查看会话的功能,最后也实现了,最主要的灵魂是“时间戳”,因为它是排列各个消息的依据;而标识会话的字段则是会话流水号,它是每条消息都会有且都相同的。
  首先,我把每一条消息抽象成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=[size=1em]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(会话流水号)作为参数,把上述代码抽离出一个方法来。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-317061-1-1.html 上篇帖子: [转]Cassandra、MongoDB、CouchDB、Redis、Riak、HBase比较 下篇帖子: 三、Java内存数据库实践之深入浅出Redis
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表