当前位置:   article > 正文

Redis的zset集合_redis中的zset集合

redis中的zset集合

一、定义

        zset 是 set 的一个升级版本,它在 set 的基础上增加了一个顺序属性, 它和 set 一样,zset也是 string 类型元素的集合,且不允许重复的成员。

        不同的是每个元素都会关联一个 double类型的 score。 集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。 】

        集合中最大的成员数为 2的(32 - 1)次方 (4294967295, 每个集合可存储40多亿个成员)。 zset 最经典的应用场景就是排行榜。

二、ZSET的基本命令

1、ZADD  key   score1  member1  score2  member2  score3  member3

                将一个或多个member元素及其score值加入到有序集key当中。

2、ZRANGE  KEY  start  end   WITHSCORES

            返回 [start,end] 这个区间的所有值

  1. 本地:0>zadd lxh 1 a 2 b 3 c 4 d 5 e
  2. "5"
  3. 本地:0>zrange lxh 0 -1
  4. 1) "a"
  5. 2) "b"
  6. 3) "c"
  7. 4) "d"
  8. 5) "e"
  9. 本地:0>zrange lxh 0 -1 withscores
  10. 1) "a"
  11. 2) "1"
  12. 3) "b"
  13. 4) "2"
  14. 5) "c"
  15. 6) "3"
  16. 7) "d"
  17. 8) "4"
  18. 9) "e"
  19. 10) "5"
  20. 本地:0>zrevrange lxh 0 -1
  21. 1) "e"
  22. 2) "d"
  23. 3) "c"
  24. 4) "b"
  25. 5) "a"
  26. 本地:0>zrevrange lxh 0 -1 withscores
  27. 1) "e"
  28. 2) "5"
  29. 3) "d"
  30. 4) "4"
  31. 5) "c"
  32. 6) "3"
  33. 7) "b"
  34. 8) "2"
  35. 9) "a"
  36. 10) "1"

3、zrem  key  member1  member2 ...

           移除有序集key中的一个或多个成员,不存在的成员将被忽略。

  1. 本地:0>zrange lxh 0 -1 withscores
  2. 1) "a"
  3. 2) "1"
  4. 3) "b"
  5. 4) "2"
  6. 5) "c"
  7. 6) "3"
  8. 7) "d"
  9. 8) "4"
  10. 9) "e"
  11. 10) "5"
  12. 本地:0>zrem lxh a
  13. "1"
  14. 本地:0>zrange lxh 0 -1 withscores
  15. 1) "b"
  16. 2) "2"
  17. 3) "c"
  18. 4) "3"
  19. 5) "d"
  20. 6) "4"
  21. 7) "e"
  22. 8) "5"

4、zcard  key     

        返回有序集key的基数。

  1. 本地:0>zrange lxh 0 -1 withscores
  2. 1) "b"
  3. 2) "2"
  4. 3) "c"
  5. 4) "3"
  6. 5) "d"
  7. 6) "4"
  8. 7) "e"
  9. 8) "5"
  10. 本地:0>zcard lxh
  11. "4"

5、zcount  key  min  max

        返回有序集key中,score值在min和max之间(默认包括score值等于min或max)的成员。

  1. 本地:0>zrange lxh 0 -1 withscores
  2. 1) "b"
  3. 2) "2"
  4. 3) "c"
  5. 4) "3"
  6. 5) "d"
  7. 6) "4"
  8. 7) "e"
  9. 8) "5"
  10. 本地:0>zcount lxh 1 5
  11. "4"
  12. 本地:0>zcount lxh 2 3
  13. "2"

6、zscore  key member 

                查找指定值,返回有序集key中,成员member的score值。

  1. 本地:0>zrange lxh 0 -1 withscores
  2. 1) "b"
  3. 2) "2"
  4. 3) "c"
  5. 4) "3"
  6. 5) "d"
  7. 6) "4"
  8. 7) "e"
  9. 8) "5"
  10. 本地:0>zscore lxh 2
  11. null
  12. 本地:0>zscore lxh b
  13. "2"
  14. 本地:0>zscore lxh e
  15. "5"

7、zincrby  key  increment   member

                为有序集key的成员member的score值加上增量increment。

  1. 本地:0>zrange lxh 0 -1 withscores
  2. 1) "b"
  3. 2) "2"
  4. 3) "c"
  5. 4) "3"
  6. 5) "d"
  7. 6) "4"
  8. 7) "e"
  9. 8) "5"
  10. 本地:0>zincrby lxh 10 b
  11. "12"
  12. 本地:0>zrange lxh 0 -1 withscores
  13. 1) "c"
  14. 2) "3"
  15. 3) "d"
  16. 4) "4"
  17. 5) "e"
  18. 6) "5"
  19. 7) "b"
  20. 8) "12"

8、zrevrange   key start stop    [WITHSCORES]    

                       返回有序集key中,指定区间内的成员,降序。

        zrange   key start stop    [WITHSCORES]   

                       返回有序集key中,指定区间内的成员,升序。

  1. 本地:0>zrange lxh 0 -1 withscores
  2. 1) "c"
  3. 2) "3"
  4. 3) "d"
  5. 4) "4"
  6. 5) "e"
  7. 6) "5"
  8. 7) "b"
  9. 8) "12"
  10. 本地:0>zrevrange lxh 0 -1 withscores
  11. 1) "b"
  12. 2) "12"
  13. 3) "e"
  14. 4) "5"
  15. 5) "d"
  16. 6) "4"
  17. 7) "c"
  18. 8) "3"

9、zrangebyscore  key   min  max   limit   offset   count

               返回指定集合【min ,max】区间的值,并进行分页-------返回值是升序排列

        

        zrevrangebyscore  key   min  max   limit   offset   count

               返回指定集合【min ,max】区间的值,并进行分页-------返回值是降序排列

  1. 本地:0>zrange lxh 0 -1 withscores
  2. 1) "c"
  3. 2) "3"
  4. 3) "d"
  5. 4) "4"
  6. 5) "e"
  7. 6) "5"
  8. 7) "b"
  9. 8) "12"
  10. 本地:0>zrangebyscore lxh 0 10 limit 0 10
  11. 1) "c"
  12. 2) "d"
  13. 3) "e"
  14. -- 降序排列的话, 就不是【min,max】 而是 【max,min】
  15. 本地:0>zrevrangebyscore lxh 0 10 limit 0 10
  16. 本地:0>zrevrange lxh 0 -1 withscores
  17. 1) "b"
  18. 2) "12"
  19. 3) "e"
  20. 4) "5"
  21. 5) "d"
  22. 6) "4"
  23. 7) "c"
  24. 8) "3"
  25. 本地:0>zrevrangebyscore lxh 10 0 limit 0 10
  26. 1) "e"
  27. 2) "d"
  28. 3) "c"
  29. -- 升序排列的话, 就不是【max,min】 而是 【min,max】
  30. 本地:0>zrangebyscore lxh 10 0 limit 0 10

10、zrank  key  member

                查看这个member 在key集合里面排名(升序的排名)

        

  1. 本地:0>zrange lxh 0 -1 withscores
  2. 1) "c"
  3. 2) "3"
  4. 3) "d"
  5. 4) "4"
  6. 5) "e"
  7. 6) "5"
  8. 7) "b"
  9. 8) "12"
  10. -- 排序最开始值是 0开始的
  11. 本地:0>zrank lxh b
  12. "3"

        zrevrank  key  member

                查看这个member 在key集合里面排名(降序的排名)

  1. 本地:0>zrevrange lxh 0 -1 withscores
  2. 1) "b"
  3. 2) "12"
  4. 3) "e"
  5. 4) "5"
  6. 5) "d"
  7. 6) "4"
  8. 7) "c"
  9. 8) "3"
  10. 本地:0>zrevrank lxh b
  11. "0"

11、zremrangebyrank  key  start  end

                移除key集合里面【start,end】这个排名区间的值

  1. 本地:0>zrange lxh 0 -1 withscores
  2. 1) "c"
  3. 2) "3"
  4. 3) "d"
  5. 4) "4"
  6. 5) "e"
  7. 6) "5"
  8. 7) "b"
  9. 8) "12"
  10. 本地:0>zremrangebyrank lxh 0 1
  11. "2"
  12. 本地:0>zrange lxh 0 -1 withscores
  13. 1) "e"
  14. 2) "5"
  15. 3) "b"
  16. 4) "12"

12、zremrangebyscore  key  min  max

                移除key集合里面【min  ,max】这个区间的值

  1. 本地:0>zadd lxh 1 a 2 b 3 c 10 d 100 e 500 f
  2. "6"
  3. 本地:0>zrange lxh 0 -1 withscores
  4. 1) "a"
  5. 2) "1"
  6. 3) "b"
  7. 4) "2"
  8. 5) "c"
  9. 6) "3"
  10. 7) "d"
  11. 8) "10"
  12. 9) "e"
  13. 10) "100"
  14. 11) "f"
  15. 12) "500"
  16. 本地:0>zremrangebyscore lxh 1 100
  17. "5"
  18. 本地:0>zrange lxh 0 -1 withscores
  19. 1) "f"
  20. 2) "500"

13、zinterstore  key  num  key1  key2  key3   

                取key1,key2,key3的集合的交集放到key集合里面,由于需要取3个集合的交集,则num是3。返回值是交集的数量。也就是 key   集合的数量。

                取交集的时候,会将相同的member的source值合并的。(求和)       

  1. 本地:0>zrange lxh 0 -1 withscores
  2. 1) "a"
  3. 2) "1"
  4. 3) "b"
  5. 4) "2"
  6. 5) "f"
  7. 6) "500"
  8. 本地:0>zrange lxh1 0 -1 withscores
  9. 1) "a"
  10. 2) "1"
  11. 3) "b"
  12. 4) "2"
  13. 本地:0>ZINTERSTORE lxh2 2 lxh lxh1
  14. "2"
  15. 本地:0>zrange lxh2 0 -1 withscores
  16. 1) "a"
  17. 2) "2"
  18. 3) "b"
  19. 4) "4"
  20. zinterstore lxh3 3 lxh lxh1 lxh2
  21. "2"

14、zunionstore  key   key1  key2  key3

                取key1,key2,key3的集合的并集放到key集合里面,,由于需要取3个集合的并集,则num是3。返回值是并集的数量,也就是 key   集合的数量。    

        取交集的时候,会将相同的member的source值合并的。(求和)            

  1. 本地:0>zrange lxh 0 -1 withscores
  2. 1) "a"
  3. 2) "1"
  4. 3) "b"
  5. 4) "2"
  6. 5) "dd"
  7. 6) "25"
  8. 7) "f"
  9. 8) "500"
  10. 本地:0>zrange lxh2 0 -1 withscores
  11. 1) "a"
  12. 2) "2"
  13. 3) "b"
  14. 4) "4"
  15. 本地:0>zrange lxh1 0 -1 withscores
  16. 1) "a"
  17. 2) "1"
  18. 3) "b"
  19. 4) "2"
  20. 5) "dd"
  21. 6) "25"
  22. 本地:0>zunionstore lxh8 3 lxh lxh1 lxh2
  23. "4"
  24. 本地:0>zrange lxh8 0 -1 withscores
  25. 1) "a"
  26. 2) "4"
  27. 3) "b"
  28. 4) "8"
  29. 5) "dd"
  30. 6) "50"
  31. 7) "f"
  32. 8) "500"

三、ZSET的代码实例

需求一:完成热搜排行帮查询功能。

实现步骤:

        1、当前毫秒数 / (1000*60*60)  =时间块

        2、获取得到每个热搜的时间块-----(时间块,热搜热度,热搜id),热搜热度 = 点赞+转发+阅读。

        3、每隔1个小时,将从现在开始得到的时间块,和前23个小时时间块的24个集合取交集,将交集的结果给  到一个新集合,这个新集合就每日热搜的集合。

核心代码:

        初始化数据+刷新数据

  1. package com.redis.zset;
  2. /*
  3. * 本类用来实现微博热搜
  4. *
  5. * 1、微博的榜单分为 小时榜,日榜,周榜,月榜
  6. * 2、我们现在需要做的是两件事情,一个是造出微博的数据
  7. * 3、查看指定榜单
  8. *
  9. *
  10. * */
  11. import lombok.extern.slf4j.Slf4j;
  12. import org.springframework.beans.factory.annotation.Autowired;
  13. import org.springframework.data.redis.core.RedisTemplate;
  14. import org.springframework.web.bind.annotation.PostMapping;
  15. import org.springframework.web.bind.annotation.RequestMapping;
  16. import org.springframework.web.bind.annotation.RestController;
  17. import javax.annotation.PostConstruct;
  18. import java.util.ArrayList;
  19. import java.util.List;
  20. import java.util.Random;
  21. import java.util.Set;
  22. import java.util.concurrent.TimeUnit;
  23. @RestController
  24. @RequestMapping("WB")
  25. @Slf4j
  26. public class WBRedisController {
  27. private static final String REDIS_WB_HOUR = "redisWB_hour";
  28. private static final String REDIS_WB_DAY = "redisWB_day";
  29. private static final String REDIS_WB_WEEK = "redisWB_week";
  30. private static final String REDIS_WB_MONTH = "redisWB_month";
  31. @Autowired
  32. private RedisTemplate redisTemplate;
  33. @PostConstruct
  34. public void init() {
  35. new Thread(() -> {
  36. try {
  37. initWbData();
  38. } catch (InterruptedException e) {
  39. e.printStackTrace();
  40. }
  41. }).start();
  42. }
  43. @PostMapping("refreshWBData")
  44. public String getDayWBData() {
  45. // 每小时统计一次每天的数据
  46. refreshDayData();
  47. // 每小时统计一次每周的数据
  48. refreshWeekData();
  49. // 每小时统计一次每月的数据
  50. refreshMonthData();
  51. return "数据刷新成功";
  52. }
  53. private void initWbData() throws InterruptedException {
  54. // 由于没有热搜事件,通过26个字母来代替热搜事件,同时存储每个小时每个热搜(字母)的数据
  55. // 获取当前小时的时间块
  56. long key = System.currentTimeMillis() / (1000 * 60 * 60);
  57. // 获取当月的时间块,组装为key值
  58. for (int i = 0; i < 24 * 30; i++) {
  59. String redisKey = REDIS_WB_HOUR + (key - i);
  60. for (int j = 0; j < 26; j++) {
  61. int source = new Random().nextInt(10);
  62. // 添加的是 key , member,source(member这个属性对应的数值--double类型)
  63. redisTemplate.opsForZSet().add(redisKey, String.valueOf((char)(96+i)), source);
  64. }
  65. }
  66. log.info("" +
  67. "一个月内的数据初始化完成");
  68. // 开始定时刷新数据
  69. while (true) {
  70. // 每隔5秒钟开始刷新数据
  71. // 初始化数据完成之后,每隔5秒刷新一次数据,模拟用户的访问
  72. Thread.sleep(5000);
  73. refreshData();
  74. log.info("数据刷新成功");
  75. }
  76. }
  77. /*
  78. * 刷新数据----统计每小时的数据之和
  79. * 定时统计数据---每次要统计的单位是一个小时
  80. * */
  81. private void refreshDayData() {
  82. long key = System.currentTimeMillis() / (1000 * 60 * 60);
  83. List<String> list = new ArrayList<>();
  84. // 获取当天内的所有的集合
  85. for (int i = 0; i < 24; i++) {
  86. String redisKey = REDIS_WB_HOUR + (key - i);
  87. this.redisTemplate.expire(redisKey, 40, TimeUnit.DAYS);
  88. list.add(redisKey);
  89. }
  90. redisTemplate.opsForZSet().unionAndStore(null, list, REDIS_WB_DAY);
  91. }
  92. /*
  93. * 刷新数据----统计每周的数据之和
  94. *
  95. * */
  96. private void refreshWeekData() {
  97. long key = System.currentTimeMillis() / (1000 * 60 * 60);
  98. List<String> list = new ArrayList<>();
  99. // 获取当天内的所有的集合
  100. for (int i = 0; i < 168; i++) {
  101. String redisKey = REDIS_WB_HOUR + (key - i);
  102. list.add(redisKey);
  103. }
  104. redisTemplate.opsForZSet().unionAndStore(null, list, REDIS_WB_WEEK);
  105. }
  106. /*
  107. * 刷新数据----统计每月的数据之和
  108. *
  109. * */
  110. private void refreshMonthData() {
  111. long key = System.currentTimeMillis() / (1000 * 60 * 60);
  112. List<String> list = new ArrayList<>();
  113. // 获取当天内的所有的集合
  114. for (int i = 0; i < (24 * 30); i++) {
  115. String redisKey = REDIS_WB_HOUR + (key - i);
  116. list.add(redisKey);
  117. }
  118. redisTemplate.opsForZSet().unionAndStore(null, list, REDIS_WB_MONTH);
  119. }
  120. /*
  121. * 定时刷新数据---模拟用户的请求
  122. * */
  123. private void refreshData() throws InterruptedException {
  124. long key = System.currentTimeMillis() / (1000 * 60 * 60);
  125. for (int i = 0; i < 26; i++) {
  126. // 添加的是 key , member,source(member这个属性对应的数值--double类型)
  127. redisTemplate.opsForZSet().incrementScore(REDIS_WB_HOUR + key, String.valueOf((char)(96+i)), new Random().nextInt(5));
  128. }
  129. }
  130. }

获取排行榜数据信息

  1. package com.redis.zset;
  2. import lombok.extern.slf4j.Slf4j;
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import org.springframework.data.redis.core.RedisTemplate;
  5. import org.springframework.web.bind.annotation.PostMapping;
  6. import org.springframework.web.bind.annotation.RequestMapping;
  7. import org.springframework.web.bind.annotation.RestController;
  8. import java.util.Set;
  9. /*
  10. * 本类用来查询热搜排行榜的展示
  11. *
  12. * */
  13. @RestController
  14. @RequestMapping("WB")
  15. @Slf4j
  16. public class GetRdisWB {
  17. private static final String REDIS_WB_HOUR = "redisWB_hour";
  18. private static final String REDIS_WB_DAY = "redisWB_day";
  19. private static final String REDIS_WB_WEEK = "redisWB_week";
  20. private static final String REDIS_WB_MONTH = "redisWB_month";
  21. @Autowired
  22. private RedisTemplate redisTemplate;
  23. @PostMapping("getHourWBData")
  24. public Set getHourWBData() {
  25. long hour = System.currentTimeMillis() / (1000 * 60 * 60);
  26. Set set = redisTemplate.opsForZSet().rangeWithScores(REDIS_WB_HOUR+hour, 0, -1);
  27. return set;
  28. }
  29. @PostMapping("getDayWBData")
  30. public Set getDayWBData() {
  31. long hour = System.currentTimeMillis() / (1000 * 60 * 60);
  32. Set set = redisTemplate.opsForZSet().rangeWithScores(REDIS_WB_DAY, 0, -1);
  33. return set;
  34. }
  35. @PostMapping("getWeekWBData")
  36. public Set getWeekWBData() {
  37. long hour = System.currentTimeMillis() / (1000 * 60 * 60);
  38. Set set = redisTemplate.opsForZSet().rangeWithScores(REDIS_WB_WEEK, 0, -1);
  39. return set;
  40. }
  41. @PostMapping("getMonthWBData")
  42. public Set getMonthWBData() {
  43. long hour = System.currentTimeMillis() / (1000 * 60 * 60);
  44. Set set = redisTemplate.opsForZSet().rangeWithScores(REDIS_WB_MONTH, 0, -1);
  45. return set;
  46. }
  47. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/432686
推荐阅读
相关标签
  

闽ICP备14008679号