Redis系列(六)-SortedSets设计技巧
阅读目录:
介绍
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
如果有更复杂的需求,比如通过日期,用户类型等来查询,就比较困难了。 如果用其他数据结构的话,想查询多条时就要多次往返操作,有性能上的损耗。 这里可以用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 = ; j < real; j++)
{
sb.Append((char) );
}
sb.Append(str);
return sb.ToString();
}
因为数据的日期可能跨年,在天位前预留2位,存储年份。现在长度是5位,如15200表示的是15年19号(第200天)。
通过年份+天数计算出当前数据项score的值。
var score= long.Parse(dateTime.Year.ToString().Substring(, ) + AutoCompletion(, dateTime.DayOfYear));
把实际值和分数值存储到redis里面:
ZADD test socre value
查询时把需要查询的日期范围转换到分数,这里查询前10天的数据:
int time1 = DateTime.Now.DayOfYear;
var score1 = AutoCompletion(time1, ) + AutoCompletion(DateTime.Now.DayOfYear, ); int time2 = DateTime.Now.DayOfYear;
var score2 = AutoCompletion(time1, ) + AutoCompletion(DateTime.Now.AddDays(-).ToLocalTime().DayOfYear, );
在redis中查询:
ZRANGEBYSCORE user score1 score2
查询当天(分数)下的信息:
ZRANGEBYSCORE user score2 score2
更多位信息
r64位整数类型有16个位置,意味着还可以存储更多维度信息。这里以日期为主,在增加个类型维度,日期位置左移4位,预留4位来存储类型维度。
如152003456,其3456四位是存储类型的,可以根据类型种类的多少可以增加位或减少位占用。
如果单纯以日期来查询时,类型不用传,后面4位在查询时补千位最小值和最大值即可。
查询前10天的数据:
ZRANGEBYSCORE user
查询15年19号3578类型的数据:
ZRANGEBYSCORE user
查询15年19号1000-4000类型的数据:
ZRANGEBYSCORE user
关于类型往往不是简单的数据类型那么简单,可以做个简单的mapping表。
abcd
dcda
以此类推...
在添加时或查询时注意转换。
总结
需要注意的是score是整数类型按从小到大排序存储的,按照上面的设计是不能在指定类型的情况下,进行日期范围查找的,因为我们定义日期作为主维度。
通常在数据库中有很多层级关系的表,比如大分类、子分类、小分类等一级一级递减。 使用Sorted Sets我们可以模拟这种关系去设计Score值,主维度->次维度->低维度,这样就可以更快的进行范围分类信息的查询,有个前提是64位整数的位置够用。
如果没有类似的需求,可以使用时间戳作为值的分数值,这样就不需要额外的转换了。
简单分享了Sorted Sets存储设计的经验,希望对大家有所帮助。
Redis系列(六)-SortedSets设计技巧的更多相关文章
- Silverlight & Blend动画设计系列六:动画技巧(Animation Techniques)之对象与路径转化、波感特效
当我们在进行Silverlight & Blend进行动画设计的过程中,可能需要设计出很多效果不一的图形图像出来作为动画的基本组成元素.然而在设计过程中可能会出现许多的问题,比如当前绘制了一个 ...
- Redis系列(六):设置/移除键的过期时间
本篇博客是Redis系列的第6篇,主要讲解以下内容: 数据库数量 切换目标数据库 设置键的过期时间 移除键的过期时间 本系列的前5篇可以点击以下链接查看: Redis系列(一):Redis简介及环境安 ...
- Redis系列六 - 浅谈如何设计秒杀系统
前言 设计一个系统之前,我们肯定要先确认系统业务场景是怎样的,下面就以某电商平台上的秒杀活动为场景,一起来探讨一个秒杀系统改如何去设计. 场景 我们现在要卖100件纸尿布,按照系统的用户量及以往经验来 ...
- Redis系列六:redis相关功能
一. 慢查询原因分析 与mysql一样:当执行时间超过阀值,会将发生时间耗时的命令记录 redis命令生命周期:发送 排队 执行 返回慢查询只统计第3个执行步骤的时间 预设阀值:两种方式,默认为10毫 ...
- Redis系列(六)--为什么这么快?
Redis作为一个基于key-value的NoSQL数据库,最显著的特点存取速度非常快,官方说可以达到10W OPS,但是Redis为何这么快? 1.开发语言 Redis使用C语言进行编写的,而Uni ...
- Redis系列六 Redis事务
Redis事务 1.介绍 在Redis事务中可以一次执行多个命令,本质是一组命令的集合.一个事务中的所有命令都会序列化,按顺序地串行化执行而不会被其它命令插入,不许加塞. 2.事务的作用 一个队列中, ...
- Redis系列之key操作命令与Redis中的事务详解(六)
序言 本篇主要目的有二: 1.展示所有数据类型中key的所有操作命令,以供大家学习,查阅,更深入的挖掘redis潜力. 2.掌握redis中的事务,让你的数据完整性一致性拥有更优的保障. redis命 ...
- 【Qt编程】基于Qt的词典开发系列<六>--界面美化设计
本文讲一讲界面设计,作品要面向用户,界面设计的好坏直接影响到用户的体验.现在的窗口设计基本都是扁平化的,你可以从window XP与window 8的窗口可以明显感觉出来.当然除了窗口本身的效果,窗口 ...
- Redis系列(三):Redis的持久化机制(RDB、AOF)
本篇博客是Redis系列的第3篇,主要讲解下Redis的2种持久化机制:RDB和AOF. 本系列的前2篇可以点击以下链接查看: Redis系列(一):Redis简介及环境安装. Redis系列(二): ...
随机推荐
- UWP学习记录1-开端
UWP学习记录1-开端 1.背景 针对不同基础的人,学习的路线自然是不同的.这篇文章记录的是我个人的学习路线,或者说笔记.我对自己的技术状态的定义是: A.有很好的windows平台编程基础: B.有 ...
- Drools 函数学习
Drools 函数学习 函数是定义在规则文件当中一代码块,作用是将在规则文件当中若干个规则都会用到的业务操作封装起来,实现业务代码的复用,减少规则编写的工作量.函数的编写位置可以是规则文件当中 pac ...
- LINUX 忘记root密码如何修改
重启linux系统 3 秒之内要按一下回车,出现如下界面 然后输入e 在 第二行最后边输入 single,有一个空格.具体方法为按向下尖头移动到第二行,按"e"进入编辑模式 在后边 ...
- 【面试题】M
一面: 1.介绍实习项目: 2.计算二叉树叶子节点的数量: 3.排序算法有哪些,手写快排: 4.长度为100的数组,值为1~100,乱序,将其中一个值改为0,找出被更改的值以及位置: 5.输入数值0~ ...
- Java RMI之HelloWorld篇
Java RMI 指的是远程方法调用 (Remote Method Invocation).它是一种机制,能够让在某个 Java 虚拟机上的对象调用另一个 Java 虚拟机中的对象上的方法.可以用此方 ...
- 杨氏矩阵定义及其查找的实现C++
先介绍一下这个数据结构的定义,Young Tableau有一个m*n的矩阵,然后有一数组 a[k], 其中 k<=m*n ,然后把a[k]中的数填入 m*n 的矩阵中,填充规则为: 1. 每一 ...
- C#对象序列化与反序列化zz
C#对象序列化与反序列化(转载自:http://www.cnblogs.com/LiZhiW/p/3622365.html) 1. 对象序列化的介绍........................ ...
- [R语言]R语言计算unix timestamp的坑
R+mongo的组合真是各种坑等着踩 由于mongo中的时间戳普遍使用的是unix timestamp的格式,因此需要对每天的数据进行计算的时候,很容易就想到对timestamp + gap对方式来实 ...
- Linux基础命令-有关于目录的命令
1. 查看帮助: [root@oracle ~]# man cd //查看 cd 指令的帮助文档 2. 显示当前工作目录: [root@oracle ~]# pwd/root 3. 列出当前目录下的内 ...
- haha3
YOU - fhasd - fdks jf > jd sfkjd sf </div><div><span >print "helloworld&qu ...