Redis专题(四) ——Redis排序、消息队列、优化存储

Redis专题(四)

——Redis排序、消息队列、优化存储

(原创内容,转载请注明来源,谢谢)

一、排序

1、命令

SORTkey [ALPHA] [DESC] [LIMIT start end],对列表、集合和有序集合进行排序,当加上alpha参数后,则可以按照字典顺序排序,加上desc则倒序排序,加上limit则支持分页。

2、关键参数

by参数:by key:*->val,可以指定排序的标准,可以自己传入一个list,也可以指定某个列进行排序。

get参数:getkey:*->val,可以指定sort排序的返回结果,而不是将整个集合进行返回,要多个参数时采用多个get,另外get#会返回元素本身的键值。

store参数:store key2,可以将前面排序的结果保存在另外一个key里面。

3、性能问题

sort的时间复杂度O(n+mlogm),n是待排序的基数,m是排序后的值。另外redis会在排序前用一个空间为n的容器进行存储排序期间的临时数据。

因此,需要注意几个问题:

1)尽可能减少待排序的集合数量,以减少n

2)如果不需要全部结果,则用limit,以减少m

3)如果要排序的结果大,则用store进行存储。

二、消息队列

redis消息队列可以分为两类,生产者和消费者,当生产者产生的数据会放入消息队列中,消费者监测到消息队列内有数据的时候,可以进行后续的处理。

1、命令

redis提供一个命令叫BRPOP,与RPOP的区别在于,当使用命令对key进行操作时,如果key没有值,则会阻塞等待,直到等到有值后取出进行操作。另外,和brpop相似的,也有BLPOP命令。

2、优先级

由于brpop命令可以支持多个键,并且当每个键都有未处理的数据时,会从最左边的键开始处理。例如有两个邮件提醒业务,一个是开通账号的验证,一个是新消息提醒。则如果太多的不采用优先级,新消息提醒的业务会让开通账号的业务阻塞。因为开通账号的时效性要求更高,因此需要将其放在左边。

3、发布订阅模式

发布订阅模式有特殊的命令,发布的命令是PUBLISH channel message,订阅的命令是SUBSCRIBEchannel message,不过由于redis的发布命令不会对消息进行持久化,即后面订阅的无法查看到发布者之前发布的消息。

subscribe命令后,会让客户端进入订阅状态,此后只能输入四种命令:subscribe、unsubscribe、psubscribe、punsubscribe,其他命令会报错。

处于订阅状态后,客户端会收到3种类型的回复,每个回复有三个值,第一个值是回复的类型,根据类型不同,二三两个值也不同。消息类型如下:

1)subscribe 表示订阅成功的反馈,此时第二个返回值是订阅的频道名称,第三个值是当前客户端订阅的频道数量。

2)message 表示收到的订阅消息,也是此模式的核心,其第二个值是频道的名称,第三个值是消息的内容。

3)unsubscribe 表示成功取消订阅某个频道,第二个值是取消的频道名称,第三个是剩余的订阅频道数量,如果是0,则此时会取消订阅模式,后面就可以继续输入其他非订阅的命令。

4、批量订阅模式

命令psubscribe,支持blob模式,即类似正则的模式,如psubscribechannel.*,则订阅所有channel开头的频道。

与此相应的,punsubscribe命令支持批量取消订阅。

三、管道

redis和客户端是用tcp进行的连接,因此来回传送消息都要经过网络,来回的总耗时称为消息时延。当执行多个命令时,每条命令需要执行完毕有返回的时候,下一条才会执行。

当需要一起执行时,redis底层的通信对管道提供了支持,当一组命令中每条命令都不依赖于前一条时,可以一起发送请求,一起返回,以减少网络通信的次数。

四、空间消耗

1、复杂度

redis为每种数据类型都提供两种编码方式,例如hash,当元素很多的时候会使用散列表的方式进行存储,时间复杂度仅O(1);但是当元素很少时,O(n)和O(1)差距不大,为了节约内存,redis会采用内部编码方法,用时间换空间。

redis可以使用OBJECTENCODING key的方式,查看每个键的内部编码类型。

2、编码

redis在内部编码采用结构体类型,如下:

         typedefstruct redisObject{
         unsigned type:4;
         unsigned notuse:2;
         unsigned encoding:4;
         unsigned lru:22;
         int refcount;
         void *ptr;
}

type代表类型,用数字0-4表示五种类型;notuse是预留空间,未使用;ptr指针指向具体存储的数据;encoding有9种,0-8,包括原生编码、整型、哈希表、zipmap、双向链表、ziplist、skiplist、字符串。针对redis的五种数据类型,分别有不同的encoding方式,如下图所示:(来自网络)

3、字符串优化

字符串存储在一个结构体,包括字符串长度、具体内容、剩余空间。当执行set命令,要占用30字节,而当键值是64位的整数,则ptr指针会直接指向值,而不是指向结构体,可以节约到16字节。

当存储的是0-9999时,redis由于会默认存储这些数字,则ptr指针直接指向引用,占用0字节的空间。

4、散列优化

在配置文件中设置hash-max-ziplist-entries和hash-max-ziplist-value,当散列的键的个数少于entiries值,且每个键值都小于value值,则会使用ziplist的方式编码,否则用哈希表来编码。ziplist牺牲时间换空间,哈希表牺牲空间换时间,因此数据少用ziplist,多的时候用哈希表。

因此,两个参数不宜设置的太大。

5、列表优化

列表和散列相似,有list-max-ziplist-entries和list-max-ziplist-value来配置。编码方式包括ziplist、双向链表、quicklist,quicklist结合ziplist和双向链表的有点,达到减少空间的同时适当减少时间。

6、集合优化

配置文件配置set-max-intset-entries,小于时采用intset编码,否则用哈希表。intset使得集合内部有序排列,便于用二分法进行查找,但是添加和删除则需要进行排序,元素多的时候速度慢。

7、有序集合优化

配置文件配置zset-max-ziplist-entries和zset-max-ziplist-value。包括ziplist和skiplist编码方式,skiplist是使用哈希表和跳跃列表两种结构来存储,哈希表用来存储分数的映射,跳跃列表用来存储分数和元素值的映射。

——written by linhxx 2017.08.06

原文发布于微信公众号 - 决胜机器学习(phpthinker)

原文发表时间:2017-08-06

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

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Python

python并发编程之多进程理论部分

一 并发与并行   无论是并行还是并发,在用户看来都是'同时'运行的,不管是进程还是线程,都只是一个任务而已,真是干活的是cpu,cpu来做这些任务,而一个cp...

1785
来自专栏我是攻城师

理解Spark的运行机制

3539
来自专栏性能与架构

nginx location配置

location在nginx中起着重要作用,对nginx接收到的请求字符串进行处理,如地址定向、数据缓存、应答控制、代理转发等 location语法 locat...

3206
来自专栏java一日一条

Java 理论与实践: 正确使用 Volatile 变量

Java 语言中的 Volatile 变量可以被看作是一种 “程度较轻的 synchronized”;与 synchronized 块相比,volatile 变...

522
来自专栏柠檬先生

你不知道的javaScript笔记(7)

异步:现在与将来   分块的程序     可以把JavaScript 程序写在单独的js 文件中,这个程序是由多个块组成的,这些块     中只有一个是现在执行...

1885
来自专栏海天一树

小朋友学C++(13):引用

(一)C语言中的“&” 在C语言里,我们碰到过“&”这个符号。“&”的使用场景有两种: (1)位运算符 int a = 5; int b = 10; int c...

2659
来自专栏算法channel

hadoop|计算框架从MapReduce1.0到Yarn

01 — HDFS 前面介绍了hadoop的分布式存储框架(HDFS),这个框架解决了大数据存储的问题,这是第一步。知道海量数据如何存储后,脚步不能停留,下一步...

3386
来自专栏Golang语言社区

由Go语言并发模型想到游戏服务器并发

这段时间看了一些Go语言相关的东西,发现Go语言的最大特性并发模型类似于C++里面的线程池,正好我们项目服务器也是用的线程池,记录下。   Go语言的并发单位是...

3538
来自专栏老司机的技术博客

golang学习笔记7:指针

不像 Java 和 .NET,Go 语言为程序员提供了控制数据结构的指针的能力;但是,你不能进行指针运算。通过给予程序员基本内存布局,Go 语言允许你控制特定集...

464
来自专栏IT技术精选文摘

Kafka 数据可靠性深度解读

1 概述 Kakfa起初是由LinkedIn公司开发的一个分布式的消息系统,后成为Apache的一部分,它使用Scala编写,以可水平扩展和高吞吐率而被广泛使用...

27310

扫码关注云+社区