Redis数据结构之Zset实现微博排行榜(五)

2,347 阅读2分钟

一、特性说明

  • ZSet采用了一种跳跃表的实现。
  • ZSet数据是有序的

二、常用命令

(一)ZADD

命令格式: zadd key score member [[score member]...]

功能:往有序集合key中存入带分值元素

demo说明:

image.png

(二)ZREM

命令格式: zrem key member [member..]

功能:从有序集合key中删除元素

demo说明:

image.png

(三)ZSCORE

命令格式: zscore key member

功能:返回有序集合key中元素member的分值

demo说明:

image.png

(四)ZINCRBY

命令格式: zincrby key increment member

功能:为有序集合key中的元素member的分值加上increment

demo说明:

image.png

(五)ZCARD

命令格式: zcard key

功能:返回元素集合key中元素个数

demo说明:

image.png

(六)ZRANGE

命令格式: zrange key start stop [WITHSCORES]

功能:正序获取有序集合key从start下标到stop下标的元素

demo说明:

image.png

(七)ZREVRANGE

命令格式: zrevrange key start stop [member]

功能:倒序获取有序集合key从start下标到stop下标的元素

demo说明:

image.png

(八)ZUNIONSTORE

命令格式: zunionstore destkey numkeys member [member]

功能:并集运算

demo说明: image.png

(九)ZINTERSTORE

命令格式: zinterstore destkey numkeys key [key]

功能:交集运算

demo说明:

image.png

三、应用场景

(一)微博热点排行版

类似需要有个数值排序的都可以考虑该方案

1、需求

实现每分钟当天的热点资讯排行榜
实现查看七天热点资讯排行榜

2、设计

  • 每条的资讯键设计为 {date}:hotnews:{id}
  • 用户点击一次则累计一次
  • 查看排行榜则取当日集合按分值排序
  • 查看七天排行榜则取七日做一个并集处理,然后再按分值排序取出

3、开发

查看资讯接口

@ApiOperation("查看资讯")
@PostMapping(value = "/viewNews")
public void viewNews(Long newsId) throws Exception{

    LocalDate localDate = LocalDate.now();

    String todayKey = localDate.plusDays(0).toString().replace("-", "") + "hotnews";

    redisTemplate.opsForZSet().incrementScore(todayKey,newsId,1);

}

获取当日热点排行榜接口

@ApiOperation("获取当日热点排行榜")
@PostMapping(value = "/getHotNewsList")
public void getHotNewsList(Long newsId) throws Exception{

    LocalDate localDate = LocalDate.now();

    String todayKey = localDate.plusDays(0).toString().replace("-", "") + "hotnews";

    Set set = redisTemplate.opsForZSet().reverseRange(todayKey, 0, 9);

    //得到资讯id再查询资讯信息
    System.out.println(set);

}

用个定时任务隔几分钟计算一次七日排行

//用个定时任务隔几分钟计算一次
public void  countLastSevenHotNews(){

    LocalDate localDate = LocalDate.now();
    //今日
    String todayKey = localDate.plusDays(0).toString().replace("-", "") + "hotnews";

    //七日排行结果数据key
    String destKey =localDate.plusDays(-6).toString().replace("-", "") +"-"+ todayKey +"hotnews";
    //过去6天的key
    List<String> list = new LinkedList<>();
    for (int i = -1; i >= -6; i--) {
        String key = localDate.plusDays(i).toString().replace("-", "")+"hotnews";
        list.add(key);
    }
    //将今日和过去六天的key集合取并集  把结果放入七天结果集合
    Long aLong = redisTemplate.opsForZSet().unionAndStore(localDate.plusDays(-1).toString().replace("-", "") + "hotnews", list, destKey);
}

获取最近七天热点排行榜接口

@ApiOperation("获取最近七天热点排行榜")
@PostMapping(value = "/getLastSevenHotNewsList")
public void getLastSevenHotNewsList() throws Exception{

    LocalDate localDate = LocalDate.now();

    //七日排行结果数据key
    String destKey =localDate.plusDays(-6).toString().replace("-", "") +"-"+ todayKey +"hotnews";
   
    //取出七天排行榜
    Set set = redisTemplate.opsForZSet().reverseRange(destKey, 0, 9);

    System.out.println(set);

}