`
Everyday都不同
  • 浏览: 723496 次
  • 性别: Icon_minigender_1
  • 来自: 宇宙
社区版块
存档分类
最新评论

用redis实现仿新浪微博“查看会话”功能

阅读更多

本人最近需要实现一个功能,就是类似新浪微博评论的“查看会话”的功能:一个大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(会话流水号)作为参数,把上述代码抽离出一个方法来。

 

2
2
分享到:
评论
1 楼 jayung 2015-08-17  
顶。。。。。。。

相关推荐

    .新浪微博.构建高性能的微博系统

    - **Redis**:作为一种高性能的键值存储系统,Redis在新浪微博的架构中扮演了重要角色。它不仅可以作为缓存,还被用于实现复杂的业务逻辑,如排行榜、计数器等功能。 #### 消息队列 - **消息队列中间件**:如...

    Python-新浪微博相册大图多线程爬虫

    在爬取新浪微博相册时,开发者可能需要模拟登录,使用`requests.Session`对象保持会话状态,以便于处理cookies和session。同时,为了防止被网站封禁,可能采用了延迟策略(如`time.sleep()`)或者随机等待时间,以及...

    新浪微博源代码weiboitcast02

    在分析"weiboitcast02"这个压缩包中的源代码时,我们可以深入了解微博系统的架构、功能实现以及优化策略。 一、系统架构 微博系统的架构设计是整个平台稳定运行的基础。从源代码中,我们可以看到它可能采用了...

    redis教案.docx

    知名公司如 GitHub、Stack Overflow、Flickr、新浪微博、知乎网等都在其服务中运用了 Redis。 Redis 的历史发展快速,自开源以来,其用户群体不断扩大,尤其是在 2012 年 Hacker News 的调查中,Redis 已成为约 12%...

    Redis 学习教程1

    在新浪微博中,Redis 的部署场景包括应用程序直接访问Redis数据库和应用程序直接访问Redis,只有当Redis访问失败时才访问MySQL。 ### Redis 数据备份与恢复 Redis 的数据备份与恢复可以确保数据的安全。Redis 的...

    Redis如何上手,基本操作,新手必看

    随着时间的推移,Redis 的普及度显著提高,被广泛应用于许多知名网站,如新浪微博、街旁网、知乎网、GitHub 和 Stack Overflow。VMware 公司自 2010 年起赞助 Redis 的开发,使其进一步成熟和完善。 Redis 的核心...

    Flask+Redis维护Cookies池.pptx

    在现代Web爬虫技术中,面对需要登录才能访问或者频繁抓取可能导致封号的网站,如新浪微博,维护一个“Cookies池”成为了解决问题的关键。本文将深入探讨如何使用Python的Flask框架与Redis数据库来构建这样的系统,以...

    论文改一1

    本文中,作者使用Scrapy-Redis构建了一个多线程、高并发且具有强鲁棒性的网络爬虫,以应对“新浪微博”的反爬策略。具体来说,对于微博的验证码识别,可能需要集成OCR(光学字符识别)技术;URL去重防止循环,可以...

    非关系型数据库redis

    redis是一种nosql数据库,他的数据是保存...还有一些文章阅读量的技术,或者新浪微博的点赞数等。作为消息队列:比如celery就是使用redis作为中间人。当前在线人数:还是之前的秀场例子,会显示当前系统有多少在线人数。

    基于PHP的Xweibo PHP微博博客程序.zip

    这个程序允许用户创建和管理自己的微型博客平台,类似于知名的微博服务,如新浪微博或Twitter。它集成了发布、分享、评论、关注等功能,为用户提供了一个互动性强、实时信息交流的网络平台。 【描述】中的".zip...

    新浪PHP面试题新浪PHP面试题

    4. **MySQL数据库交互**:SQL查询、连接管理、预处理语句、事务处理等,以及PDO或mysqli扩展的使用。 5. **PHP与Web服务器交互**:如$_GET、$_POST、$_SERVER全局变量,以及HTTP头的设置和处理。 6. **PHP安全**:...

    iBase4J分布式系统-其他

    10、QQ、微信、新浪微博第三方登录。11、工具类:excel导入导出,汉字转拼音,身份证号码验证,数字转大写人民币,FTP/SFTP/fastDFS上传下载,发送邮件,redis缓存,加密等等。技术选型:核心框架:Sring boot + ...

Global site tag (gtag.js) - Google Analytics