首页
找靠谱产品
找解决方案
找靠谱公司
找案例
找对的人
专家智库
悬赏任务
SAAS
ToB门户
了解全球最新的ToB事件
论坛
潜水/灌水快乐,沉淀知识,认识更多同行。
ToB圈子
加入IT圈,遇到更多同好之人。
微博
Follow
记录
Doing
博客
Blog
文库
业界最专业的IT文库,上传资料也可以赚钱
下载
分享
Share
排行榜
Ranklist
相册
Album
应用中心
qidao123.com技术社区-IT企服评测·应用市场
»
论坛
›
大数据
›
数据仓库与分析
›
【Redis】数据结构和内部编码
返回列表
发新帖
【Redis】数据结构和内部编码
[复制链接]
发表于
3 天前
|
显示全部楼层
|
阅读模式
先来复习一下之前学过的几个根本的全局命令:
keys:用来查察匹配规则的key
exists:用来判定执行key是否存在
del:删除指定的key
expire:给key设置过期时间
ttl:查询key的过期时间
type:查询key对应的value的范例
一、Redis的数据结构
type命令实际返回的就是当前键的数据结构范例,他们分别是:string(字符串),list(列表),hash(哈希),set(聚集),zset(有序聚集),但是这些只是Redis对外的数据结构。
实际上Redis针对每一个数据结构都有自己的底层内部编码实现,而且是多种实现,如许Redis会在符合的场景选择符合的内部编码。
string范例的raw是最根本的字符串(底层就是持有一个char数组(C++)大概byte数组(Java))【C++里的char是1字节,等价与Java中的byte,而Java中的char是两个字节的】;string范例的int是用来实现“计数”如许的
功能
,当value就是一个整数的时间,此时大概Redis会直接利用int来保存;embstr是针对短字符串进行的特别优化。
hash范例的hashtable是最根本的哈希表;hash范例的ziplist是在哈希表里面的元素比较少的时间大概就优化成ziplist了,压缩列表可以大概节省空间。
list范例的linkedlist是链表;list范例的ziplist是压缩列表;从Redis3.2开始,引入了新的实现方式:quicklist,同时分身了linkedlist和ziplist的长处,quicklist就是一个链表,每一个元素又是一个ziplist把空间和服从都折中的分身到~~~(quicklist比较类似于C++中的std::deque)
set范例的intset聚集中存的都是整数
zset范例的skiplist是跳表~~~
为什么要压缩??
Redis上有许多key,大概某些key的value是hash,此时,假如key特别多,对应的hash也特别多,但是每一个hash又不大的环境下,就只管去压缩,压缩之后就可以让团体占用的内存更小了。
可以看到每一种数据结构都有至少两种以上的内部编码实现,我们可以通过 object encoding 命令查询内部编码:
object encoding key
复制
代码
Redis如许计划有两种利益:
可以改进内部编码,而对外的数据结构和命令没有任何影响,如许一旦开辟出更良好的内部编码,无需改动外部数据结构和命令,比方Redis3.2提供了quicklist,联合了ziplist和linkedlist两者的上风,为列表范例提供了一种更为良好的内部编码实现,而对用户来说根本无感知。
多种内部编码实现可以在不同场景下发挥各自的上风,比方ziplist比较节省内存,但是在列表元素比较多的环境下,
性能
会降落,这时间Redis会根据设置选项将列表范例的内部实现转换为linkedlist,整个过程用户同样无感知。
Redis会主动根据当前的实际环境选择内部的编码方式,主动顺应的,只记思想,不记数字!!类似与如许的“参数”非经常见,都是“可调的”。
二、Redis的单线程架构
Redis利用了单线程架构来实现高
性能
的内存
数据库
服务。Redis只利用一个线程处理全部的命令哀求,不是说一个Redis
服务器
历程内部只有一个线程,实在也有多个线程,多个线程在处理网络IO。
2.1 引出单线程模子
如今开启了三个redis-cli客户端同时执行命令。
客户端1设置一个字符串键值对:
set hello world
客户端2对counter做自增操作:
incr counter
客户端3对counter做自增操作:
incr counter
复制
代码
我们已经知道了从客户端发送的命令履历:发送死令,执行命令,返回结构三个阶段,此中发送死令最告急。Redis是采用单线程模子执行命令的是指:固然三个客户端看起来是同时要求Redis去执行命令的,但是微观角度上,这些命令还是采用线性方法去执行的,只是原则上命令的执行次序是不确定的,但是肯定不会有两条命令被同步执行,可以想象Redis内部只有一个服务窗口,多个客户端按照他们到达的先后次序被列队在窗口前,依次担当Redis的服务,所以两条incr命令无论执行次序,结果肯定是2,不会发生并发标题。
Redis可以大概利用单线程模子很好的工作,缘故因由重要在于Redis的核心业务逻辑,都是短平快的,不太斲丧CPU资源,也就不太吃多核~
Redis必须要特别鉴戒某一个利用占用时间长,就会壅闭其他命令的执行!!!
线程
安全
标题
在多线程中,针对类似如许的场景:两个线程实行同时对一个变量进行自增,表面上看是自增两次,实际上大概只自增一次。
2.2 为什么单线程还能这么快
参照物是
数据库
(MySQL)
纯内存访问。Redis将全部数据放在内存中,内存的相应时长约莫为100纳秒,这是Redis到达每秒万级别访问的告急底子。
非壅闭IO。Redis利用epoll作为I/O多路复用技能的实现,在加上Redis自身的变乱处理模子将epoll中的毗连、读写、关闭都转换为变乱,不在网络IO上浪费过多的时间。
单线程避免了线程切换和竞态产生的斲丧。单线程可以简化数据结构和算法的实现,让步伐模子更简朴;其次多线程避免了在线程竞争同一份共享数据时带来的切换和等候斲丧。
Redis的核心
功能
比
数据库
的核心
功能
更简朴。数据库对于数据的插入删除查询……都有更复杂的功能支持,如许的功能势须要泯灭更多的开销。
固然单线程给Redis带来许多利益,但是另有一个致命的标题:对于单个命令的执行时间都是有要求的。假如某一个命令执行过长,会导致其他命令全部处于等候队列中,迟迟等不到相应,造成客户端的壅闭,对于Redis这种高
性能
的服务来说优劣常告急的,所以Redis是面向快速执行场景的数据库。
三、String字符串
字符串范例是Redis最根本的数据范例,关于字符串必要特别留意:
起首Redis中全部的键的范例都是字符串范例,而且其他几种数据结构也都是在字符串类似底子上构建的,比方列表和聚集的元素范例是字符串范例,所以字符串范例能为其他4中数据结构的学习奠基底子
字符串范例的值实际可以是字符串,包含一样平常格式的字符串大概类似于JSON、XML格式的字符串;数字可以是整形大概浮点型,乃至是二进制数据,比方图片、音频、视频等。不外一个字符串的最大值不能凌驾512MB。
由于Redis内部
存储
字符串美满是按照二进制流的情势保存的,所以Redis是不处理字符集编码标题的,客户端传入的命令中利用的是什么字符集编码,就
存储
什么字符集编码。 (MySQL的默认字符集是拉丁文,插入中文就会失败~)
3.1 常见命令
FLUSHALL
可以把Redis上全部的键值对都带走,以后在公司,尤其是生产环境的数据库中,千万不敢敲。
3.1.1 SET
将string范例的value设置到key中。假如key之前存在,则覆盖;无论原来的数据范例是什么。之前关于此key的TTL也全部失效。语法如下:
SET key value [expiration EX seconds|PX milliseconds] [NX|XX]
复制
代码
Redis
文档
给出的语法格式说明:
[ ] 相称于一个独立的单位,表现可选项(无关紧急的),此中 | 表现“大概”的意思,多个只能出现一个。[ ] 和 [ ] 之间是可以相互同时存在的。
时间复杂度为:O(1)
选项:
SET命令支持多种选项来影响他的举动:
EX——利用秒作为单位设置key的过期时间
PX——利用毫秒作为单位设置key的过期时间
NX——只在key不存在时才进行设置,即假如key之前已经存在,设置不执行
XX ——只在key存在时才进行设置,即假如key之前不存在,设置不执行
留意:由于带选项的SET命令可以被SETNX、SETEX、PSETEX等命令代替,所以之后的
版本
中,Redis大概进行归并。
返回值:
假如设置成功,返回OK
假如由于SET指定了NX大概XX,但是条件不满足,SET不会执行,并返回(nil)
3.1.2 GET
获取key对应的value。假如key不存在,返回nil。假如value的数据范例不是string,会报错。语法如下:
GET key
复制代码
时间复杂度为:O(1)
返回值:key对应的value,大概nil当key不存在
3.1.3 MGET
一次性获取多个key的值。假如对应的key不存在大概对应的数据范例不是string,返回nil。语法如下:
M
GET key [key ...]
复制代码
时间复杂度为:O(N)N是key的数量
返回值:对应value的列表。
3.1.4 MSET
一次性设置多个key的值。语法如下:
MSET key value [key value ...]
复制代码
时间复杂度为:O(N)N是key的数量
返回值:永久是OK
利用mget/mset由于可以有用地镌汰了网络时间,所以性能相较于更高。假设网络耗时1毫秒,命令执行时间耗时0.1毫秒。学会利用批量利用,可以有用提高业务处理服从,但是要留意,每次批量利用所发送的键的数量也不是无控制的,否则大概造成单一命令执行时间过长,导致Redis壅闭。
3.1.5 SETNX
设置key-value,但是只答应在key之前不存在的环境下。语法如下:
SETNX key value
复制代码
时间复杂度为:O(1)
返回值:1表现设置成功。0表现没有设置。
3.1.6 SETEX和PSETEX
设置key的过期时间,单位是秒和毫秒。
3.2 计数命令
INCR
将key对应的string表现的数字加一。假如key不存在,则视为key对应的value是0。假如key对应的string不是一个整形大概范围超出了64位有符号整形,则报错。语法如下:
INCR key
复制代码
时间复杂度为:O(1)
返回值:integer范例的加完后的数值。
INCRBY
将key对应的string表现的数字加上对应的值。假如key不存在,则视为key对应的value是0。假如key对应的string不是一个整形大概范围凌驾了64位有符号整形,则报错。语法如下:
INCRBY key decrement
复制代码
时间复杂度为:O(1)
返回值:integer范例的加完后的数值。
DECR
DECRBY
INCRBYFL
OA
T
将key对应的string表现的浮点数加上对应的值。假如对应的值是负数,则视为减去对应的值。假如key不存在,则视为key对应的value是0,。假如key对应的不是string,大概不是一个浮点数,则报错。答应采用科学计数法表现浮点数。语法如下:
INCRBYFL
OA
T key increment
复制代码
时间复杂度为:O(1)
返回值:加/减完后的数值。
许多
存储
体系和编程语言内部利用CAS机制实现计数功能,会有肯定的CPU开销,但是在Redis中完全不存在这个标题,由于Redis是单线程架构,任何命令到了Redis服务端都要次序执行。
3.3 其他命令
APPEND
假如key已经存在而且是一个string,命令会将value追加到原有string的后边。假如key不存在,则结果等同于SET命令。语法如下:
APPEND KEY VALUE
复制代码
时间复杂度为:O(1),追加的字符串一样平常长度较短,可以视为O(1)
返回值:追加完成之后string的长度。
在启动Redis客户端的时间,加上一个 --raw如许的选项,就可以使Redis客户端可以大概主动把二进制数据实行翻译。利用linux的时间,千万留意不要乱按 crtl + s
ctrl + s 在XShell中的作用是“冻结当前画面”
ctrl + q 排除冻结
GETRANGE
返回key对应的string子串,由start和end确定(左闭右闭)。可以利用负数表现倒数。-1表现倒数第一个字符,-2表现倒数第二个字符,其他的与此类似。凌驾范围的偏移量会根据string的长度调解成准确的值。语法如下:
GETRANGE key start end
复制代码
时间复杂度为:O(N),N为[start,end]区间的长度,由于string通常比较短,可以视为是O(1)
返回值:string范例的子串。
SETRANGE
覆盖字符串的一部门,从指定的偏移开始。语法如下:
SETRANGE key offset value
复制代码
时间复杂度为:O(N),N为value的长度,由于一样平常给的value比较短,通常视为O(1)
返回值:更换后的string的长度。
STRLEN
获取key对应的string的长度。当key存放的类似不是string时,报错。语法如下:
STRLEN key
复制代码
时间复杂度为:O(1)
返回值:string的长度。大概当key不存在时,返回0
单位是字节。
C++中,字符串的长度自己就是用字节为单位;Java中,字符串的长度则是以字符为单位。MySQL的时间,varchar(N)此处的N的单位就是字符,MySQL中的字符也是完备的汉字,如许的一个字符,也大概是多个字节。
Java中的一个char == 2字节,Java中的char基于unicode如许的编码方式可以大概表现中文等符号~~Java中的char是用的unicode,一个汉字利用两个字节,Java中的String则是利用的utf8,一个汉字就是3个字节了,Java的尺度库内部,在进行上述的利用过程中,步伐员一样平常是感知不到编码方式的变换的。
3.4 内部编码
字符串范例的内部编码有3种:
int:8个字节的长整型
embstr:小于即是39个字节的字符串
raw:大于39个字节的字符串
Redis会根据当前值的范例和长度动态决定利用哪种内部编码实现的。
Redis存储小数,本质上还是当做字符串来存储的,这就和整数相比差距很大了,整数直接利用int来存(准确的说是一个long long)比较方便进行算法运算,小数则是利用字符串来存储,意味着每次进行算术运算,都必要把字符串转成小数,进行运算,结果再转为字符串保存。
3.5 典范利用场景
缓存功能
下图是比较典范的缓存利用场景,此中Redis作为缓冲层,MySQL作为存储层,绝大多数哀求的数据都是从Redis中获取的。由于Redis具有支持高并发的特性,所以缓存通常能起到加速读写和低沉后端压力的作用。
计数功能
许多应用都会利用Redis作为计数的底子工具,他可以实现快速计数,查询缓存的功能,同时数据可以异步处理大概落地到其他数据源。如图所示:比方视频网站的视频播放次数可以利用Redis来完成,用户每播放一次视频,相应的视频播放数就会自增1。
实际上要开辟一个成熟,稳固的真实计数体系,要面临的挑衅远不止云云简朴:防作弊、按照不同维度计数,避免单点标题,数据长期化到底层数据源等。
共享会话(Session)
一个分布式Web服务将用户的Session信息(比方用户登录信息)保存在各自的
服务器
中,但如许会造成一个标题:处于
负载
平衡的思量,分布式服务会将用户的反问哀求平衡到不同的
服务器
上,而且通常无法包管用户每次哀求都会被平衡到同一台服务器上,如许当用户革新一次访问是大概会发现必要重新登录,这个标题是用户无法容忍的。
为相识决这个标题,可以利用Redis将用户的Session信息进行集中管理,在这种模式下,只要包管Redis是高可用和可扩展性的,无论用户被平衡到哪一台Web服务器上,都集中从Redis中查询,更新Session信息。
手机验证码
许多应用处于
安全
思量,会在每次进行登录时,让用户输入手机号而且共同给手机号发送验证码,然后让用户再次输入收到的验证码并进行验证,从而确定是否是用户本人。
四、Hash哈希
险些全部的主流编程语言都提供了哈希范例,他们的叫法大概是哈希,字典,关联数组,映射。在Redis中,哈希范例是指值自己又是一个键值对结构,形如key = "key",value = { {} }。
哈希范例中的映射关系通常为field-value,用于区分Redis团体的键值对(key-value),留意这里的value是指field对应的值,不是键(key)对应的值,请留意value在不同上下文的作用。
4.1 根本命令
HSET
设置hash中指定的字段(field)的值(value).语法如下:
HGET
HEXISTS
HDEL
HKEYS
HVALS
HGETALL
HMSET
HSCAN
HLEN
HSETNX
HINCRBY
HINCRBYFL
OA
T
4.2 内部编码
哈希的内部编码有两种:
ziplist(压缩列表):当哈希范例元素个数小于 hash-max-ziplist-entries 设置(默认512个),同时全部值都小于 hash-max-ziplist-value 设置(默认64字节)时,Redis会利用ziplist作为哈希的内部实现,ziplist利用更加紧凑的结构实现多个元素的连续存储,所以在节省内存方面比hashtable更良好
hashtable(哈希表):当哈希范例无法满足ziplist的条件时,Redis会利用hashtable作为哈希的内部实现,由于此时ziplist的读写服从会降落,而hashtable的读写时间复杂度为O(1)
压缩:
rar,zip,gzip,7z等一些具体的压缩算法。
压缩的本质是针对数据进行重新编码,不同的数据有不同的特点,联合这些特点,进行精妙的计划,重写编码之后,就能缩小体积~~
ziplist也是经心计划的,目标是节省内存空间,但是进行读写元素时,速率是比较慢的。假如元素个数少,慢的并不显着;假如元素个数太多了,慢就会雪上加霜。
4.3 利用场景
缓存功能
存储结构化的数据利用hash范例更符合一些~~~
4.4 缓存方式对比
停止如今为止,我们已经有三种方式缓存用户信息,下面给出三种方案的实现方法和优缺点分析:
原生字符串范例——利用字符串范例,每一个属性对应一个键
set user:1:name James
set user:1:age 23
set user:1:city Beijing
复制代码
长处:实现简朴,针对个别属性变更也很灵活
缺点:占用过多的键,内存占用量较大,同时用户信息在Redis中比较分散,缺少内聚性,所以这种方案没有实用性。
序列化字符串范例,比方JSON格式
set user:1 经过序列化后的⽤⼾对象字符串
复制代码
长处:针对总是以团体作为利用的信息比较符合,编程也简朴。同时,假如序列化方案选择符合,内存的利用服从很高。
缺点: 自己序列化和反序列必要肯定开销,同时假如总是利用个别属性则非常不灵活。
哈希范例
hmset user:1 name James age 23 city Beijing
复制代码
长处:简朴,直观,灵活。尤其是针对信息的局部变更大概获取利用。
缺点:必要控制哈希在ziplist和hashtable两种内部编码的转换,大概会造成内存的较大斲丧。
五、list列表
列表范例是用来存储多个有序的字符串,列表中的每一个字符串称为元素,一个列表最多可以存储 2^32 - 1 个元素。在Redis中,可以对列表两头插入和弹出,还可以获取指定范围的元素列表、获取指定索引下标的元素等。列表是一种比较灵活的数据结构,他可以充当栈和队列的脚色,在实际开辟中有许多应用场景。
列表范例的特点:
列表中的元素是有序的,这个有序不是说这个列表中存储的元素是有序的,而是说,不同次序的列表不同,纵然他们的元素是雷同的。
区分获取和删除的区别,删除元素的话,会将这个列表的长度镌汰;但是执行 lindex 4 只会获取元素,但是列表长度是不会厘革的。
列表中的元素是答应重复的。
列表(List)相称于数组大概次序表,留意,list内部的结构(编码方式)并非是一个简朴的数组,而是更靠近于“双端队列”(deque)。由于当前的List,头和为都能高效的插入和删除元素,就可以把这个List当做一个栈大概队列来利用。
Redis有一个典范的应用场景,就是作为消息队列,最早的时间,就是通过List范例~~,厥后,Redis又提供了一个stream范例。
5.1 根本命令
LPUSH
将一个大概多个元素从左侧放入(头插)到list中,语法如下:
LPUSH key element [element ...]
复制代码
时间复杂度:只插入一个元素为O(1),插入多个元素为O(1),N为插入元素的个数。
返回值:插入后list的长度。
LPUSHX
在key存在时,将一个大概多个元素从左侧放入(头插)到list中。不存在,直接返回。语法如下:
LPUSHX key element [element ...]
复制代码
时间复杂度:只插入一个元素为O(1),插入多个元素为O(N),N为插入的元素个数。
返回值:插入后的list的长度。
RPUSH
RPUSHX
LRANGE
获取从start到stop区间的全部元素,左闭右闭。语法如下:
LRANGE key start stop
复制代码
时间复杂度为:O(N)
返回值:指定区间的元素
LPOP
从list左侧取出元素(即头删)。语法如下:
LPOP key
复制代码
时间复杂度为:O(1)
返回值:取出的元素大概nil
RPOP
LINDEX
获取从左边第index位置的元素。语法如下:
LINDEX key index
复制代码
时间复杂度为:O(N)
返回值:取出的元素大概nil
LINSERT
在特定位置插入元素,语法如下:
LINSERT key <BEFORE | AFTER> pivot element
复制代码
时间复杂度:O(N)
返回值:插入后的list长度
LLEN
获取list长度,语法如下:
LLEN key
复制代码
时间复杂度:O(1)
返回值:list的长度
5.2 壅闭
版本
命令
blpop和brpop是lpop和rpop的壅闭
版本
,和对应非壅闭版本的作用根本同等,除了:
在列表中有元素的环境下,壅闭和非壅闭版本体现是同等的。但是假如列表中没有元素,非壅闭版本会立即返回nil,但是壅闭版本会根据timeout,壅闭一段时间,期间Redis可以执行其他命令,但是要求执行该命令的客户端会体现为壅闭状态。
命令中假如设置了多个键,那么会从左向右进行遍历键,一旦有一个键对应的列表中可以弹出元素,命令立即返回。
如多个客户端同时多个键执行pop,则开始执行命令的客户端会得到弹出的元素。
BLPOP
LPOP的壅闭版本,语法如下:
B
LPOP key [key ...] timeout
复制代码
返回值:取出的元素大概nil
BRPOP
RPOP的壅闭版本,语法如下:
BRPOP key [key ...] timeout
复制代码
返回值:取出的元素大概nil
5.3 内部编码
对于如今的列表范例的内部编码已经变为了quicklist,quicklist箱单与链表和压缩列表的联合。团体还是一个链表,链表的每一个节点是一个压缩列表。每一个压缩列表都不让他太大,同时再把多个压缩列表通过链式结构连起来~~
下面先容的编码已经不在利用了:
列表范例的内部编码有两种:
ziplist(压缩列表):当列表的元素个数小于 list-max-ziplist-entries 设置(默认512个),同时列表中每一个元素的长度都小于 list-max-ziplist-value 设置(默认64字节)时,Redis会选用ziplist来作用列表的内部编码实现来镌汰内存斲丧。
linkedlist(链表):当列表范例无法满足 ziplist 的条件时,Redis会利用 linkedlist 作为列表的内部实现。
5.4 利用场景
存储多个元素,进行查询
可以利用列表作为“数组”来存储多个元素,Redis提供的查询功能不像MySQL那样强盛。
消息列表
Redis可以利用 lpush + brpop 命令组合实现经典的壅闭式生产者-消耗者模子队列,生产者客户端利用 lpush 从列表左侧插入元素,多个消耗者客户端利用 brpop 命令壅闭式地从队列中“争抢”队首元素。通过多个客户端来包管消耗的
负载
平衡和高可用性。
只有一个消耗者能“抢到”元素,谁先执行的这个brpop命令,谁就能拿到这个新来的元素,像如许的设定,就能构成一个“轮询”。
分频道的消息列表
Redis同样利用 lpush + brpop 命令,但是通过不同的键模仿频道的概念,不同的消耗者可以通过 brpop 不同的键值,实现订阅不同频道的理念。
多个列表/频道,这种场景非经常见,一样平常利用的一些步伐中,抖音等都有这些。有一个通常来传输短视频数据,还可以有一个通道来传输数据,还可以有频道来传输点赞,转发等,还可以有频道来传输评论和数据。
微博Timeline
每一个用户都有属于自己的Timeline(微博列表),现必要分页展示文章列表。此时可以思量利用列表,由于列表不光是有序的,同时支持按照索引范围获取元素。
选择列表范例时,请参考:
同侧存取(lpush + lpop 大概 rpush + rpop)为栈
异侧存取(lpush + rpop 大概 rpush + lpop)为队列
六、Set聚集
聚集范例也是保存多个字符串范例的元素,但是和列表范例不同的是,在聚集中:
元素之间是无序的
元素不答应重复,一个聚集中最多可以存储2^32 - 1个元素
Redis除了支持聚集内的增删查改利用,同时还支持多个聚集取交集、并集、差集,公道地利用好聚集范例,能在实际开辟中办理许多标题。
6.1 普通命令
SADD
将一个大概多个元素添加到set中。留意,重复的元素无法添加到set中。语法如下:
SADD key member [member ...]
复制代码
时间复杂度为:O(1)
返回值:本次添加成功的元素个数
SMEMBERS
获取一个set中的全部元素,留意,元素间的次序是无序的。语法如下:
SMEMBERS key
复制代码
时间复杂度:O(N)
返回值:全部元素的列表
SISMEMBER
判定一个元素在不在set中,语法如下:
SISMEMBER key member
复制代码
时间复杂度:O(1)
返回值:1表现元素在set中,0表现元素不在set中大概key不存在
SCARD
获取一个set的基数,即set中的元素个数。语法如下:
SCARD key
复制代码
时间复杂度为:O(1)
返回值:set内的元素个数
SPOP
从set中删除并返回一个大概多个元素。留意,由于set内的元素是无序的,所以取出哪一个元素是未界说举动,即可以看做随机的。语法如下:
SPOP key [count]
复制代码
时间复杂度:O(N),N是count
返回值:取出的元素
SMOVE
将一个元素从源set取出并放入目标set中,语法如下:
SMOVE source destination member
复制代码
时间复杂度:O(1)
返回值:1表现移动成功,0表现失败
SREM
将指定的元素从set中删除,语法如下:
SREM key member [member ...]
复制代码
时间复杂度:O(N),N是要删除的元素个数
返回值:本次利用删除的元素个数
6.2 聚集间的利用
SINTER
获取给定set的交集中的元素,语法如下:
SINTER key [key ...]
复制代码
时间复杂度:O(N * M),N是最小的聚集元素个数,M是最大的聚集元素个数
返回值:交集的元素
SINTERSTORE
获取给定set的交集中的元素并保存到目标set中。语法如下:
SINTERSTORE destination key [key ...]
复制代码
时间复杂度:O(N * M),N是最小的聚集元素个数,M是最大的聚集元素个数
返回值:交集的元素个数
SUNION
SUNIONSTORE
SDIFF
SDIFFSTORE
6.3 内部编码
聚集范例的内部编码有两种:
intset(整数聚集)
hashtable(哈希表)
6.4 利用场景
聚集范例比较典范的利用场景是标签。比方A用户对娱乐、体育板块比较感爱好,B用户对汗青、新闻比较感爱好,这些爱好点可以被抽象为标签。有了这数据就可以得到喜好同一个标签的人,以及用户的共同爱好的标签,这些数据对于增强用户体验和用户粘度都非常有资助。比方,一个电子商务网站会对不同标签的用户做不同的产物推荐。
sinter user:1:tags user:2:tags
复制代码
利用Set来盘算用户之间的共同挚友
基于“聚集求交集”
利用Set统计UV
去重
一个互联网产物,怎样衡量用户量,用户规模??
重要的指标是两个方面:
PV(page view):用户每次访问该服务器,每次访问都会产生一个pv
UV(user view) :每一个用户访问服务器,都会产生一个uv,但是同一个用户多次访问,不会使uv增加,uv必要按照用户进行去重,上述的去重过程,就可以利用set去实现。
七、Zset有序聚集
有序聚集相对于字符串、列表、哈希、聚集来说会有一些生疏。他保留了聚集不能有重复成员的特点,但是与聚集不同的是,有序聚集中的每一个元素都有一个唯一的浮点数范例的分数与之关联,使得有序聚集中的元素是可以维护有序性的,但是这个有序不是用下标作为排序依据而是用这个分数。
有序聚集提供了获取指定分数和元素范围查找,盘算成员排名等功能,公道地利用有序聚集,可以资助我们在实际开辟中办理许多标题。
有序聚集中的元素是不能重复的,但是分数答应重复。类比于一次考试之后,每一个人肯定有一个唯一的分数,但是分数答应雷同。
7.1 普通命令
7.2 聚集间的利用
7.3 内部编码
有序聚集范例的内部编码有两种:
ziplist(压缩列表)
skiplist(跳表)
7.4 利用场景
有序即可比较典范的利用场景就是排行榜体系。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
继续阅读请点击广告
本帖子中包含更多资源
您需要
登录
才可以下载或查看,没有账号?
立即注册
×
回复
使用道具
举报
返回列表
水军大提督
+ 我要发帖
×
登录参与点评抽奖,加入IT实名职场社区
去登录
微信订阅号
微信服务号
微信客服(加群)
H5
小程序
快速回复
返回顶部
返回列表