redis实战系列4--使用redis+springboot构建社交app后台(4)

说明:

这是本系列的最终章,主要讲解如何更新用户的时间线,包括:
1动态发布时更新发布者以及关注者的时间列表
2动态删除时更新发布者以及关注者的时间列表
3辅助函数:syndicateStatus(用于更新关注者的时间列表)
4获取单人时间线里的具体内容
代码:

1辅助函数syndicateStatus

//如果type=0,表示从关注者里增加发布者发布动态的信息
//为1,就是删除
public static void syndicateStatus(RedisTemplate template, long uid, long postId, long postTime,int type){
    Set<String> followers=template.opsForZSet().range("followers:"+uid,0,-1);
    //先获取发布者的被其他用户关注的列表,获取关注者的id集合
    template.setEnableTransactionSupport(true);
    template.multi();
    for(String f:followers){
        if(type==0){
        //为0,就往关注者home:id集合里增加时间线,,注意,这是home:id,不是profile:id,profile:id只保存着自己的时间线,Home:id还包括了所关注的人的动态时间线
            template.opsForZSet().add("home:"+f,String.valueOf(postId),postTime);
            template.opsForZSet().removeRange("home:"+f,1000,10000);
            //删除超过范围的数据,防止内存占用过大
        }else{
          template.opsForZSet().remove("home:"+f,String.valueOf(postId));
        }
    }
    template.exec();
}

2辅助函数create_status,也即第二篇文章提到的函数,用于创建动态表
3主函数:postStatus–
1用于调用create_status创建动态,更新个人时间线
2以及调用syndicateStatus函数更新关注着的时间线
3这里还用到了future模式,已进行并发运行,防止堵塞

//更新个人时间线:创建新的动态+更新时间线
 public long postStatus(RedisTemplate template, long uid, String message, Map<String,String> data){
     long id=create_status(template,uid, message, null);//创建动态
     if(id==-1)return -1;
     String posted= (String) template.opsForHash().get("status:"+id,"posted");
     long post=Long.parseLong(posted);
     service.submit(()->{
         template.setEnableTransactionSupport(true);
         template.multi();
         template.opsForZSet().add("home:"+uid,String.valueOf(id),post);
         //更新个人时间线
         template.opsForZSet().add("profile:"+uid,String.valueOf(id),post);
         template.exec();
     },MoreExecutors.directExecutor());
     service.submit(()->{
         this.syndicateStatus(template,uid,id,post,0);
     },MoreExecutors.directExecutor());
     return id;
 }

4主函数deleteStatus
顾名思义及删除status,操作和上面那个函数相反即可

//删除动态
public boolean deleteStatus(RedisTemplate template,String uid, String statusId) throws InterruptedException {
    String key="status:"+uid;
    String lock=lockUtil.acquire_lock_with_timeou(key,1,10);
    try {
        if(lock==null)return false;
        if(!uid.equals(template.opsForHash().get("user:"+uid,"id")))return false;
        service.submit(()->{
            template.setEnableTransactionSupport(true);
            template.multi();
            template.opsForZSet().remove("home:"+uid,statusId);
            template.opsForZSet().remove("profile:"+uid,statusId);
            template.delete("status:"+statusId);
            template.exec();
        },MoreExecutors.directExecutor());
        service.submit(()->{
            this.syndicateStatus(template,Long.parseLong(uid),Long.parseLong(statusId),0,1);
        },MoreExecutors.directExecutor());
        return true;
    }finally {
        lockUtil.release_lock(key,lock);
    }
}

5函数getStatusMessages
用于获取status的具体内容:

public List<Map<String,String>> getStatusMessages(long uid, int page, int count){
    HashOperations<String,String,String>operations=template.opsForHash();
    List<Map<String,String>> list=new ArrayList<>();
    //这个List用来保存结果,里面是map,当然你也可以创建一个实体类来保存答案,=
    Set<String> ids=template.opsForZSet().reverseRange("home:"+uid,(page - 1) * count, page * count - 1);
    //获取对应的时间线的status的id值,page和count用于分页操作
    template.setEnableTransactionSupport(true);
    template.multi();
    for(String id:ids){
        operations.entries("status:"+id);
        //这个操作会把status:id对应具体内容给找出来,然后保存起来,下面的操作就是遍历这个结果
    }
    for(Object object:template.exec()){//从事务中获取数据,并把键值对转化成map形式
        Map<String,String> status = (Map<String,String>)object;
        if(status!=null&&status.size()>0){
            list.add(status);//往List里面加数据
        }
    }
    return list;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值