Redis系列(六)-SortedSets设计技巧

阅读目录:

  1. 介绍
  2. Score占位
  3. 更多位信息
  4. 总结

介绍

Redis Sorted Sets是类似Redis Sets数据结构,不允许重复项的String集合。不同的是Sorted Sets中的每个成员都分配了一个分数值(score),它用于在Sorted Sets中进行成员排序,从最小值到最大值。Sorted Sets中所有的成员都是唯一的,其分数(score)是可以重复的,即是说一个分数可能会对应多个值。

用Sorted Sets可以非常快的进行添加、删除、或更新成员,其复杂度是O(m*log(n)),m是添加或查询的成员数量。因为成员是按照顺序添加的,所以可以非常快的通过score或者索引进行范围查询。访问Sorted Sets中间的元素也是非常快的,因此可以用sort sets作为一个不重复的小型有序列表。 通过Sorted Sets可以快速操作任何你想做的事情:排序的成员,判断成员是否在集合中,快速访问集合中间的成员。

如果多次添加相同的值到Sorted Sets上,redis会以最后一次的值分数为准。

总的来说,在其他数据库比较难完成的任务,用Sorted Sets可以更快更优性能的完成。

更多Sorted Sets的用法可以查看官方文档。

Score占位

Sorted Sets中的Score是个64位整数类型,其范围在-9007199254740992到9007199254740992之间,这是一个非常有用的关键点。

我们通常可以用它进行简单的范围查询,比如把年龄当分数,通过ZRANGEBYSCORE查询某个年龄段的所有用户。 查询18-35年龄的用户:

ZRANGEBYSCORE user 18 35

如果有更复杂的需求,比如通过日期,用户类型等来查询,就比较困难了。 如果用其他数据结构的话,想查询多条时就要多次往返操作,有性能上的损耗。 这里可以用Score整数类型的长度特性,来存储查询的条件信息。

比如有些数据需要通过日期范围查询,这是个很常见的场景。

使用Sorted Sets当存储的数据结构,添加key时把日期进行简单的转码。

一年有365天,在score中预留三位来存储天份,通过DayOfYear计算出一年第多少天:

var time1=DateTime.Now.DayOfYear

因为第100天前的数据不满三位,需要进行用0补全,写个方法:

string AutoCompletion(int length, int num)
    {
        string str = num.ToString();
        if (str.Length > length)
            throw new Exception("max length");
        var real = length - str.Length;
        var sb = new StringBuilder(length);
        for (int j = 0; j < real; j++)
        {
            sb.Append((char) 48);
        }
        sb.Append(str);
        return sb.ToString();
    }

因为数据的日期可能跨年,在天位前预留2位,存储年份。现在长度是5位,如15200表示的是15年19号(第200天)。 

通过年份+天数计算出当前数据项score的值。

var score= long.Parse(dateTime.Year.ToString().Substring(2, 2) + AutoCompletion(3, dateTime.DayOfYear));

把实际值和分数值存储到redis里面:

ZADD test socre value

查询时把需要查询的日期范围转换到分数,这里查询前10天的数据:

        int time1 = DateTime.Now.DayOfYear;
        var score1 = AutoCompletion(time1, 2) + AutoCompletion(DateTime.Now.DayOfYear, 3);

        int time2 = DateTime.Now.DayOfYear;
        var score2 = AutoCompletion(time1, 2) + AutoCompletion(DateTime.Now.AddDays(-10).ToLocalTime().DayOfYear, 3);

在redis中查询:

ZRANGEBYSCORE user score1 score2

查询当天(分数)下的信息:

ZRANGEBYSCORE user score2 score2 

更多位信息

r64位整数类型有16个位置,意味着还可以存储更多维度信息。这里以日期为主,在增加个类型维度,日期位置左移4位,预留4位来存储类型维度。

如152003456,其3456四位是存储类型的,可以根据类型种类的多少可以增加位或减少位占用。

如果单纯以日期来查询时,类型不用传,后面4位在查询时补千位最小值和最大值即可。

查询前10天的数据:

ZRANGEBYSCORE user 151900000 152009999

查询15年19号3578类型的数据:

ZRANGEBYSCORE user 152003578 152003578 

查询15年19号1000-4000类型的数据:

ZRANGEBYSCORE user 152001000 152004000

关于类型往往不是简单的数据类型那么简单,可以做个简单的mapping表。

abcd 1000
dcda 1001
以此类推...

在添加时或查询时注意转换。

总结

需要注意的是score是整数类型按从小到大排序存储的,按照上面的设计是不能在指定类型的情况下,进行日期范围查找的,因为我们定义日期作为主维度。

通常在数据库中有很多层级关系的表,比如大分类、子分类、小分类等一级一级递减。 使用Sorted Sets我们可以模拟这种关系去设计Score值,主维度->次维度->低维度,这样就可以更快的进行范围分类信息的查询,有个前提是64位整数的位置够用。

如果没有类似的需求,可以使用时间戳作为值的分数值,这样就不需要额外的转换了。

简单分享了Sorted Sets存储设计的经验,希望对大家有所帮助。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏小灰灰

基于ForkJoin构建一个简单易用的并发组件

基于ForkJoin构建一个简单易用的并发组件 在实际的业务开发中,需要用到并发编程的知识,实际使用线程池来异步执行任务的场景并不是特别多,而且一般真的遇到了需...

43580
来自专栏Android 研究

Android插件化基础1-----加载SD上APK

大致的意思是: ClassLoader 是一个负责加载classes的对象,ClassLoader类是一个抽象类,需要给出类的二进制名称,ClassLoader...

32230
来自专栏北京马哥教育

做到这二十条,Python程序性能轻松翻倍!

算法的时间复杂度对程序的执行效率影响最大,在Python中可以通过选择合适的数据结构来优化时间复杂度,如list和set查找某一个元素的时间复杂度分别是O(n)...

15450
来自专栏文大师的新世界

Java面试

自己经验有限,篇幅也有限,这里只是记录一些比较容易混淆或有难度和一些易忘的技术知识点,里面有一些也是面试阿里经常会被问到的问题,但是不保证答案全部正确,有错误的...

28030
来自专栏企鹅号快讯

Bruce.Wang-记一次对JS木马分析

0×00 前言 随着 javascript 这类脚本语言的快速发展,它能展现的内容越来越多样,所运用的功能变得越来越强大。当运用在 web 开发上时,增加了更多...

28260
来自专栏安恒网络空间安全讲武堂

记一次JS木马分析

记一次JS木马分析 0x00 前言 随着 javascript 这类脚本语言的快速发展,它能展现的内容越来越多样,所运用的功能变得越来越强大。当运用在 web ...

62880
来自专栏数据小魔方

Python可视化笔记之folium交互地图

leftlet给R语言提供了很好用的交互式动态地图接口,其在Python中得API接口包名为folium(不知道包作者为何这样起名字,和leaflet已经扯不上...

69140
来自专栏程序员与猫

Go Code Review Comments 译文(截止2018年7月27日)

持续更新中… 原文最新链接 https://github.com/golang/go/wiki/CodeReviewComments/5a40ba36d38...

26530
来自专栏IT派

Python 性能优化的20条招数

算法的时间复杂度对程序的执行效率影响最大,在 Python 中可以通过选择合适的数据结构来优化时间复杂度,如 list 和 set 查找某一个元素的时间复杂度分...

11530
来自专栏对角另一面

lodash源码分析之chunk的尺与刀

以不正义开始的事情,必须用罪恶使它巩固。 ——莎士比亚《麦克白》 最近很多事似乎印证了这句话,一句谎言最后要用一百句谎言来圆谎。 本文为读 lodash...

24200

扫码关注云+社区

领取腾讯云代金券