Redis(二)-基本数据类型

概述

本节主要分析Redis5大数据类型(对应上一节分析的RedisObject中Type属性:String/List/Set/Hash/Sorted Set)的编码/常用操作

1. String

1.1 编码

  • int: 若是整数值并且该整数值可以用long类型表示,则编码为int
  • embstr: 若是字符串值,并且字符串长度小于等于44字节,则编码为embstr
  • raw: 若是字符串值,并且字符串长度大于44字节,则SDS保存字符串值,编码为raw

注意:
1、long/double类型的浮点数是用字符串保存的,对其操作会先转化为浮点型进行操作再转化为字符串保存
2、对int型操作(如APPEND一个字符串),会把int转化为raw
3、embstr字符串为只读,若要对其修改会先转化为raw

1.2 常用操作

SET:为一个key设置value,可以配合EX/PX参数指定key的有效期,通过NX/XX参数针对key是否存在的情况进行区别操作,时间复杂度O(1)
GET:获取某个key对应的value,时间复杂度O(1)
GETSET:为一个key设置value,并返回该key的原value,时间复杂度O(1)
INCR:将key对应的value值自增1,并返回自增后的值。只对可以转换为整型的String数据起作用。时间复杂度O(1)
INCRBY:将key对应的value值自增指定的整型数值,并返回自增后的值。只对可以转换为整型的String数据起作用。时间复杂度O(1)
DECR/DECRBY:同INCR/INCRBY,自增改为自减。
MSET:为多个key设置value,时间复杂度O(N)
MSETNX:同MSET,如果指定的key中有任意一个已存在,则不进行任何操作,时间复杂度O(N)
MGET:获取多个key对应的value,时间复杂度O(N)
BITCOUNT:获取bit位为1的位数
BITOP:操作bit位,BITOP operation destkey key [key ...]
BITPOS:查找bit位,BITPOS key bit [start] [end]
GETBIT:查看bit位,GETBIT key offset
SETBIT:设置bit位,SETBIT key offset value

1.3 小结

  • 最底层数据结构都是基于字节数组,除M*操作时间复杂度为O(N)(N为同时操作的字符串个数),其余命令基本都是O(1)时间复杂度
  • BIT*相关操作实际复杂度为O(N)(N为bit位数)
  • bitmap占用内存小,可以实现很多对内存要求比较敏感的需求,例如:统计用户每天登录情况/签到情况/连续登录情况等

2. List

1.1 编码

  • ziplist(压缩列表):Redis3.2以前,保存的字符串元素都小于64字节,并且元素数量小于512个时,使用ziplist;
  • linkedlist(双向链表):Redis3.2以前,否则使用linkedlist,每个节点保存一个字符串对象
  • quicklist(快速链表):Redis3.2以后,统一使用quicklist编码

1.2 常用操作

LPUSH:向指定List的左侧(即头部)插入1个或多个元素,返回插入后的List长度。时间复杂度O(N),N为插入元素的数量
RPUSH:同LPUSH,向指定List的右侧(即尾部)插入1或多个元素
LPOP:从指定List的左侧(即头部)移除一个元素并返回,时间复杂度O(1)
RPOP:同LPOP,从指定List的右侧(即尾部)移除1个元素并返回
LPUSHX/RPUSHX:与LPUSH/RPUSH类似,区别在于,LPUSHX/RPUSHX操作的key如果不存在,则不会进行任何操作
LLEN:返回指定List的长度,时间复杂度O(1)
LRANGE:返回指定List中指定范围的元素,时间复杂度O(N)
LINDEX:返回指定List指定index上的元素,如果index越界,返回nil。index数值是回环的,即-1代表List最后一个位置,-2代表List倒数第二个位置。时间复杂度O(N)
LSET:将指定List指定index上的元素设置为value,如果index越界则返回错误,时间复杂度O(N),如果操作的是头/尾部的元素,则时间复杂度为O(1)
LINSERT:向指定List中指定元素之前/之后插入一个新元素,并返回操作后的List长度。如果指定的元素不存在,返回-1。如果指定key不存在,不会进行任何操作,时间复杂度O(N)

1.3 小结

  • 基于头/尾操作时间复杂度为O(1);基于范围/中间位置操作时间复杂度为O(n)
  • Redis的List实际是设计来用于实现队列,而不是用于实现类似ArrayList这样的列表的,如果不是想要实现一个双端队列,那么请尽量不要使用List数据结构
  • 通过BLPOP/BLPUSH实现阻塞队列

3. Set

1.1 编码

  • intset(整数集合):所有元素都是整数值,并且数量不超过512个时,使用intset;
  • hashtable(字典):否则使用hashtable,每个键都为一个字符串对象,值为NULL

1.2 常用操作

SADD:向指定Set中添加1个或多个member,如果指定Set不存在,会自动创建一个。时间复杂度O(N),N为添加的member个数
SREM:从指定Set中移除1个或多个member,时间复杂度O(N),N为移除的member个数
SRANDMEMBER:从指定Set中随机返回1个或多个member,时间复杂度O(N),N为返回的member个数
SPOP:从指定Set中随机移除并返回count个member,时间复杂度O(N),N为移除的member个数
SCARD:返回指定Set中的member个数,时间复杂度O(1)
SISMEMBER:判断指定的value是否存在于指定Set中,时间复杂度O(1)
SMOVE:将指定member从一个Set移至另一个Set
SMEMBERS:返回指定Hash中所有的member,时间复杂度O(N)
SUNION/SUNIONSTORE:计算多个Set的并集并返回/存储至另一个Set中,时间复杂度O(N),N为参与计算的所有集合的总member数
SINTER/SINTERSTORE:计算多个Set的交集并返回/存储至另一个Set中,时间复杂度O(N),N为参与计算的所有集合的总member数
SDIFF/SDIFFSTORE:计算1个Set与1或多个Set的差集并返回/存储至另一个Set中,时间复杂度O(N),N为参与计算的所有集合的总member数

1.3 小结

  • 实现/功能/时间复杂度类似HashSet
  • 交集/并集/差集时间复杂度O(n),可以实现统计新增用户数/留存用户数等功能,但是最好在从库上执行

4. Hash

1.1 编码

  • ziplist(压缩列表):所有键值对的键和值的字符串长度都小于64字节,并且键值对数量小于512个,使用ziplist
  • hashtable(字典):否则使用hashtable,键和值都为字符串对象

1.2 常用操作

HSET:将key对应的Hash中的field设置为value。如果该Hash不存在,会自动创建一个。时间复杂度O(1)
HGET:返回指定Hash中field字段的值,时间复杂度O(1)
HMSET/HMGET:同HSET和HGET,可以批量操作同一个key下的多个field,时间复杂度:O(N),N为一次操作的field数量
HSETNX:同HSET,但如field已经存在,HSETNX不会进行任何操作,时间复杂度O(1)
HEXISTS:判断指定Hash中field是否存在,存在返回1,不存在返回0,时间复杂度O(1)
HDEL:删除指定Hash中的field(1个或多个),时间复杂度:O(N),N为操作的field数量
HINCRBY:同INCRBY命令,对指定Hash中的一个field进行INCRBY,时间复杂度O(1)
HGETALL:返回指定Hash中所有的field-value对。返回结果为数组,数组中field和value交替出现。时间复杂度O(N)
HKEYS/HVALS:返回指定Hash中所有的field/value,时间复杂度O(N)

1.3 小结

  • 实现/功能/时间复杂度类似HashMap

5. Sorted Set

1.1 编码

  • ziplist(压缩列表):元素数量小于128个,并且元素成员长度小于64字节,使用ziplist,每个集合元素使用两个压缩列表节点保存,第一个保存成员,第二个保存分数,集合元素按分值从小到大排序
  • skiplist(跳表):否则使用skiplist编码,底层为zset结构,包含一个字典和一个跳跃表;跳跃表按分值进行排序,实现了范围查询;而字典创建了从成员到分数的映射,键为集合元素,值为分数;字典和跳跃表都使用指针指向成员和分数,因此不会造成内存浪费

1.2 常用操作

ZADD:向指定Sorted Set中添加1个或多个member,时间复杂度O(Mlog(N)),M为添加的member数量,N为Sorted Set中的member数量
ZREM:从指定Sorted Set中删除1个或多个member,时间复杂度O(Mlog(N)),M为删除的member数量,N为Sorted Set中的member数量
ZCOUNT:返回指定Sorted Set中指定score范围内的member数量,时间复杂度:O(log(N))
ZCARD:返回指定Sorted Set中的member数量,时间复杂度O(1)
ZSCORE:返回指定Sorted Set中指定member的score,时间复杂度O(1)
ZRANK/ZREVRANK:返回指定member在Sorted Set中的排名,ZRANK返回按升序排序的排名,ZREVRANK则返回按降序排序的排名。时间复杂度O(log(N))
ZINCRBY:同INCRBY,对指定Sorted Set中的指定member的score进行自增,时间复杂度O(log(N))
ZRANGE/ZREVRANGE:返回指定Sorted Set中指定排名范围内的所有member,ZRANGE为按score升序排序,ZREVRANGE为按score降序排序,时间复杂度O(log(N)+M),M为本次返回的member数
ZRANGEBYSCORE/ZREVRANGEBYSCORE:返回指定Sorted Set中指定score范围内的所有member,返回结果以升序/降序排序,min和max可以指定为-inf和+inf,代表返回所有的member。时间复杂度O(log(N)+M)
ZREMRANGEBYRANK/ZREMRANGEBYSCORE:移除Sorted Set中指定排名范围/指定score范围内的所有member。时间复杂度O(log(N)+M)

1.3 小结

  • 按照分数进行排序
  • 增/删/改/查时间复杂度为 log(N)
  • 可实现分页场景

总结

  • Redis 之所以能快速操作键值对,一方面是因为 O(1) 复杂度的哈希表被广泛使用,包括 String、Hash 和 Set,它们的操作复杂度基本由哈希表决定,另一方面,Sorted Set 也采用了 O(logN) 复杂度的跳表
  • 复杂度较高的 List 类型,它的两种底层实现结构:双向链表和压缩列表的操作复杂度都是 O(N)。因此,建议因地制宜地使用 List 类型
  • Redis数据类型丰富,每个类型的操作繁多,无法一下子记住所有操作的复杂度。所以,最好的办法就是掌握原理,以不变应万变
    -------over-------
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,163评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,301评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,089评论 0 352
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,093评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,110评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,079评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,005评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,840评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,278评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,497评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,667评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,394评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,980评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,628评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,649评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,548评论 2 352

推荐阅读更多精彩内容