基于redis的微博个人首页
微博个人首页业务场景分析
微博个人首页的redis技术方案
用户发的文章是hash存储,key为postId
用户的关注的人set存储,fowlee
用户的被关注的人set存储,follower
我的主页是一个list,userId 后面是postId
关注的页面是一个list,userId后面是关注人之前发过的postId
用户发了文章,首先将文章以hash方式存储在缓存
存储被关注人的set
存储到自己的个人主页,list postId
找到自己被关注的人,将被关注人的list postId
3.案例实战:基于push技术,实现微博个人列表
步骤1:发微博后,写入个人主页-队列
/**
* push到个人主页
*/
public void pushHomeList(Integer userId,Integer postId){
String key= Constants.CACHE_MY_POST_BOX_LIST_KEY+userId;
this.redisTemplate.opsForList().leftPush(key,postId);
}
步骤2:查看个人列表
/**
* 获取个人主页列表
*/
public PageResult<Content> homeList(Integer userId,int page, int size){
PageResult<Content> pageResult=new PageResult();
List<Integer> list=null;
long start = (page - 1) * size;
long end = start + size - 1;
try {
String key= Constants.CACHE_MY_POST_BOX_LIST_KEY+userId;
//1.查询用户的总数
int total=this.redisTemplate.opsForList().size(key).intValue();
pageResult.setTotal(total);
//2.采用redis list数据结构的lrange命令实现分页查询。
list = this.redisTemplate.opsForList().range(key, start, end);
//3.去拿明细
List<Content> contents=this.getContents(list);
pageResult.setRows(contents);
}catch (Exception e){
log.error("异常",e);
}
return pageResult;
}
protected List<Content> getContents(List<Integer> list){
List<Content> contents=new ArrayList<>();
//发布内容的key
List<String> hashKeys=new ArrayList<>();
hashKeys.add("id");
hashKeys.add("content");
hashKeys.add("userId");
HashOperations<String, String ,Object> opsForHash=redisTemplate.opsForHash();
for (Integer id:list){
String hkey= Constants.CACHE_CONTENT_KEY+id;
List<Object> clist=opsForHash.multiGet(hkey,hashKeys);
//redis没有去db找
if (clist.get(0)==null && clist.get(1)==null){
Content obj=this.contentMapper.selectByPrimaryKey(id);
contents.add(obj);
}else{
Content content=new Content();
content.setId(clist.get(0)==null?0:Integer.valueOf(clist.get(0).toString()));
content.setContent(clist.get(1)==null?"":clist.get(1).toString());
content.setUserId(clist.get(2)==null?0:Integer.valueOf(clist.get(2).toString()));
contents.add(content);
}
}
return contents;
}
步骤3:体验
用户和id的数据库对应关系
阿甘->id=1
雷军->id=2
王石->id=3
潘石岂->id=4
关注顺序
阿甘关注:雷军 王石 潘石岂
雷军关注:王石 潘石岂
王石关注: 雷军
潘石岂关注:王石
雷军发微博:
第一条微博:123
第二条微博: abc
第一条微博:wwww
体验步骤:
1.雷军先发微博
2.查看雷军的个人主页
4.案例实战:基于push技术,实现微博关注列表
步骤1:发一条微博,批量推送给所有粉丝
/**
* 发一条微博,批量推送给所有粉丝
*/
private void pushFollower(int userId,int postId){
SetOperations<String, Integer> opsForSet = redisTemplate.opsForSet();
//读取粉丝集合
String followerkey=Constants.CACHE_KEY_FOLLOWER+userId;
//千万不能取set集合的所有数据,如果数据量大的话,会卡死
// Set<Integer> sets= opsForSet.members(followerkey);
Cursor<Integer> cursor = opsForSet.scan(followerkey, ScanOptions.NONE);
try{
while (cursor.hasNext()){
//拿出粉丝的userid
Integer object = cursor.next();
String key= Constants.CACHE_MY_ATTENTION_BOX_LIST_KEY+object;
this.redisTemplate.opsForList().leftPush(key,postId);
}
}catch (Exception ex){
log.error("",ex);
}finally {
try {
cursor.close();
} catch (IOException e) {
log.error("",e);
}
}
}
步骤2:查看关注列表
/**
* 获取关注列表
*/
public PageResult<Content> attentionList(Integer userId,int page, int size){
PageResult<Content> pageResult=new PageResult();
List<Integer> list=null;
long start = (page - 1) * size;
long end = start + size - 1;
try {
String key= Constants.CACHE_MY_ATTENTION_BOX_LIST_KEY+userId;
//1.设置总数
int total=this.redisTemplate.opsForList().size(key).intValue();
pageResult.setTotal(total);
//2.采用redis,list数据结构的lrange命令实现分页查询。
list = this.redisTemplate.opsForList().range(key, start, end);
//3.去拿明细数据
List<Content> contents=this.getContents(list);
pageResult.setRows(contents);
}catch (Exception e){
log.error("异常",e);
}
return pageResult;
}
步骤3:体验
用户和id的数据库对应关系
阿甘->id=1
雷军->id=2
王石->id=3
潘石岂->id=4
关注顺序
阿甘关注:雷军 王石 潘石岂
雷军关注:王石 潘石岂
王石关注: 雷军
潘石岂关注:王石
雷军发微博:
第一条微博:今天出太阳了
第二条微博: 下雨了
第一条微博:出现彩虹了
体验步骤:
1.雷军先发微博
2.查看雷军的个人主页
3.阿甘查看推荐首页