目录
Redis中的数据结构
Redis7 中支持的数据结构类型
数据类型 | 类型名称 | 特征说明 | 场景使用 |
String | 字符串 | String 是 redis 最基本的类型,一个 key 对应一个 value String 是二进制安全的,redis 的 String 可以包含任何数据。如 jpg 图片或者序列化对象 String 类型是 Redis 最基本的数据类型,String 类型的值最大能存储 512MB | 非常多,万物皆可 String |
Hash | 哈希 | Redis Hash 是一个键值(key=>value)对集合。 Redis Hash 特别适合用于存储对象 | 存储带有属性的对象 |
List | 列表 | Redis 列表是简单的字符串列表,按照插入顺序排序 我们可以添加一个元素到列表的头部(左边)或者尾部(右边) | 1、最新消息排行等功能 2、消息队列 |
Set | 集合 | Redis 的 Set 是 string 类型的无序集合 集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1) 为集合提供了求交集、并集、差集等操作 | 1、共同好友 2、分布式统计&计数 |
sored Set | 有序集合 | Redis 的 Set 是 string 类型的有序集合 | 1、排行榜 2、带权重的消息 |
HyperLogLogs | 基数 | 用来做基数统计的,即计算在一批数据中,不重复元素有多少个 | 1. 登陆用户总 2. 销售产品数 |
Bitmaps | 位图 | Bitmap 即位图数据结构,都是操作二进制位来进行记录 | 1、存储状态(只有 0、1) |
Geospatial | 地理 | Redis GEO 主要用于存储地理位置信息,并对存储的信息进行操作 | 1、两地之间的距离 2、方圆几里的人 |
Redis 内部结构类型
RedisObject对象
Redis 内部所有存储的数据都使用 redisObject 来封装。
struct redisObject { unsigned type:4; // 对象类型如 zset/set/hash 等等 unsigned encoding:4; // 对象编码如 ziplist/intset/skiplist 等等 unsigned lru:24; // 对象的「热度」 int refcount; // 引用计数 void *ptr; // 数据指针 } ;
SDS对象结构
Redis 的字符串叫着 SDS,也就是 Simple Dynamic String。它的结构是一个带长度信息的字节数组
struct SDS<T> { T capacity; // 数组容量 T len; // 数组长度 byte flags; // 特殊标识位,不理睬它 byte[] content; // 数组内容 }
embstr 编码方式
embstr 编码方式,当 String 类型(非 int)长度小于或等于 44 时,默认采用 embstr 编码方式,如下图所示字符串的 SDS 对象就紧挨着 ptr 指针存放
raw编码方式
当 String 类型长度大于 44 时,会使用 raw 编码方式,如下图所示 SDS 与 redisObject 内存不连续
压缩列表 ziplist
Redis 为了节约内存的使用,当元素个数与元素大小比较小时,对于 hash、zset、list,会使用 ziplist 编码方式节约内存。ziplist 通过将每个值紧 挨着存储同时避免使用 redisObject 与 SDS,节约大量内存空间(PS: 这里说的避免使用SDS和redisObj 指的是ziplist中存储的元素,而不是指ziplist本身)
struct ziplist<T> { int32 zlbytes; // 整个压缩列表占用字节数 int32 zltail_offset; // 最后一个元素距离压缩列表起始位置的偏移量,用于快速定位到最后一个节点 int16 zllength; // 元素个数 T[] entries; // 元素内容列表,挨个挨个紧凑存储 int8 zlend; // 标志压缩列表的结束,值恒为 0xFF }
从 Redis7 开始,ziplist 统一由 listpack 进行替换,listpack 与 ziplist 极为类似,可以理解为 ziplist 的升级版
- 头比ziplist少了4字节
- 每个元素中只有自己的总长度来实现逆序遍历,更新时不会出现级联更新
跳跃链表skiplist
skiplist 采用了多级索引,末端采用原始单链表进行存储
快速列表quicklist
quicklist 是 ziplist 和 linkedlist 的混合体,它将 linkedlist 按段切分,每一段使用 ziplist 来紧凑存储,多个 ziplist 之间使用双向指针串接起来
String数据结构
基本介绍
String 类型是 Redis 最基本的数据类型,一个 key 对应一个 value
String 是二进制安全的,redis 的 String 可以包含任何数据。如 jpg 图片或者序列化对象
String 类型的值最大能存储 512MB
内部实现
Redis 提供了命令 OBJECT ENCODING key 来查询内部编码方式。
Redis 在使用的时候,Value 值不宜过大,当超过 10K 的时候,就要特别注意性能的问题。(会导致big key)
常用命令
- SET key value,指定 key 的值
- GET key,获取指定 key 的值
- SETRANGE key offset value,用 value 参数覆写给定 key 所储存的字符串值, 从偏移量 offset 开始
- GETRANGE key start end,返回 key 中字符串值的子字符
- GETSET key value,将给定 key 的值设为 value,并返回 key 的旧值
- GETDEL key,获取某个 key 的值,将删除
- MSET key value [key value ...],同时设置一个或多个 key-value 对
- MGET key1 [key2..],获取所有(一个或多个)给定 key 的值
- GETBIT key offset,对 key 所储存的字符串值,获取指定偏移量上的位(bit)
- SETBIT key offset value,设置或清除指定偏移量上的位(bit)
- SETEX key seconds value,将值 value 关联到 key,并设定过期时间 seconds
- GETEX key ……获取 key 的值,并设置过期时间
- PSETEX key milliseconds value,这个命令和 SETEX 命令相似,但它以毫秒为单位设置 key 的生存时间,而不是像 SETEX 命令那样,以秒为单位
- SETNX key value,只有在 key 不存在时设置 key 的值
- STRLEN key,返回 key 所储存的字符串值的长度。
- MSETNX key value [key value ...],同时设置一个或多个 key-value 对,当且仅当所有给定 key 都不存在
- APPEND key value,将指定的 value 追加到该 key 值的末尾。
Hash数据结构
基本介绍
Redis Hash 是一个键值(key=>value)对集合。
Redis Hash 特别适合用于存储对象
内部实现
1. hashTable 大家很熟悉,和 java 里的 hashMap 很像,用 hashTable 编码的话,则会花费至少大于存储的数据 25%的空间才能存下这些数据
2. zipList,又叫压缩链表,zipList 最大的特点就是,它不是 hash 结构,而是一个比较长的字符串,将 key-value 都按顺序依次摆放到一个长长的字
符串里来存储,从内存占用上讲,zipList 可比 hashTable 降低了极多
3. listPack,与 zipList 极为相似,可以理解为 zipList 的优化版
4. 那么何时用 hashTable、ziplist/listPack 呢?
在 redis.conf 文件中可以找到(Redis 7 版本):
hash-max-listpack-entries 512
hash-max-listpack-value 64
如果是 6 或以前的版本:
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
常用命令
HSET key field value,将哈希表 key 中的字段 field 的值设为 value
HGET key field,获取存储在哈希表中指定字段的值
HDEL key field1 [field2],删除一个或多个哈希表字段
HEXISTS key field,查看哈希表 key 中,指定的字段是否存在
HMGET key field1 [field2],获取所有给定字段的值
HMSET key field1 value1 [field2 value2 ],同时将多个 field-value (域-值)对设置到哈希表 key 中
HGETALL key,获取在哈希表中指定 key 的所有字段和值
HINCRBY key field increment,为哈希表 key 中的指定字段的整数值加上增量 increment
HVALS key,获取哈希表中所有值
HKEYS key,获取所有哈希表中的字段
HLEN key,获取哈希表中字段的数量
HSCAN key cursor [MATCH pattern] [COUNT count],迭代哈希表中的键值对
List数据结构
基本介绍
Redis 列表是简单的字符串列表,按照插入顺序排序
我们可以添加一个元素到列表的头部(左边)或者尾部(右边)
内部实现
1. redis 的 list 数据类型最早使用的是一个双向链表 linkedlist,但双向链表的 prev 与 next 指针会占用大量的内存空间。为了节约内存开销,redis 从 3.2 版本开始,使用一个快速列表 quicklist 保存数据
2. quicklist 是 ziplist/listpack 和 linkedlist 的混合体,它将 linkedlist 按段切分,每一段使用 ziplist/listpack 来紧凑存储,多个 ziplist/listpack 之间使用 双向指针串接起来
常用命令
LPUSH key value1 [value2],将一个或多个值插入到列表头部
RPUSH key value1 [value2],在列表中添加一个或多个值
LPOP key,移出并获取列表的第一个元素
RPOP key,移除列表的最后一个元素,返回值为移除的元素
LPUSHX key value,将一个值插入到已存在的列表头部
RPUSHX key value,为已存在的列表添加值
LSET key index value,通过索引设置列表元素的值
LINDEX key index,通过索引获取列表中的元素
LINSERT key BEFORE|AFTER pivot value,在列表的元素前或者后插入元素
LREM key count value,移除列表元素
LRANGE key start stop,获取列表指定范围内的元素
LLEN key,获取列表长度
BLPOP key1 [key2 ] timeout,移出并获取列表的第一个元素,如果 列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。
BRPOP key1 [key2 ] timeout,移出并获取列表的最后一个元素, 如 果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。
LTRIM key start stop,对一个列表进行修剪(trim),就是说,让列 表只保留指定区间内的元素,不在指定区间之内的元素都将被删除。
BRPOPLPUSH source destination timeout,从列表中弹出一个值,将 弹出的元素插入到另外一个列表中并返回它; 如果列表没有元素会阻 塞列表直到等待超时或发现可弹出元素为止。
RPOPLPUSH source destination,移除列表的最后一个元素,并将该 元素添加到另一个列表并返回
set数据结构
基本介绍
Redis 的 Set 是 string 类型的无序集合
集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)
为集合提供了求交集、并集、差集等操作
内部实现
- redis 为了节省内存开销,对于集合类型,如果集合的数据都是整数,且个数比较少的情况下,会优先使用 inset 实现
- inset 实现时,内部数量不宜过大,默认为 512 以下
常用命令
SADD key member1 [member2],向集合添加一个或多个成员
SREM key member1 [member2],移除集合中一个或多个成员
SMEMBERS key,返回集合中的所有成员
SCARD key,获取集合的成员数
SISMEMBER key member,判断 member 元素是否是集合 key 的成员
SINTER key1 [key2],返回给定所有集合的交集
SINTERSTORE destination key1 [key2],返回给定所有集合的交集并存储 在 destination 中
SUNION key1 [key2],返回所有给定集合的并集
SDIFF key1 [key2],返回第一个集合与其他集合之间的差异。
SPOP key,移除并返回集合中的一个随机元素
SRANDMEMBER key [count],返回集合中一个或多个随机数
SoredSet 数据结构
基本介绍
Redis 的 Set 是 string 类型的有序集合
内部实现
1. redis 为了节省内存开销,对于集合类型,如果集合的数据都是整数,且个数比较少的情况下,会优先使用 ziplist/listpack 实现
2. inset 实现时,内部数量不宜过大,默认为 128 以下
常用命令
ZADD key score1 member1 [score2 member2],向有序集合添加一个或多个成员,或者更新已存在成员的分数
ZREM key member [member ...],移除有序集合中的一个或多个成员
ZCARD key,获取有序集合的成员数
ZINCRBY key increment member,对指定成员的分数加上增量 increment
ZCOUNT key min max,计算指定分数区间的成员数
ZLEXCOUNT key min max,计算指定字典区间内成员数量
ZRANGE key start stop [WITHSCORES],通过索引区间返回区间内的成员
ZRANGEBYLEX key min max [LIMIT offset count],通过字典区间返回有序集合的成员
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT],通过分数返回有序集合指定区间内的成员
ZREMRANGEBYRANK key start stop,移除有序集合中给定排名区间所有成员
ZREMRANGEBYLEX key min max,移除有序集合中给定的字典区间的所有成员
ZREMRANGEBYSCORE key min max,移除有序集合中给定分数区间的所有成员
ZREVRANGE key start stop [WITHSCORES],返回有序集中指定区间内的成员,通过索引,分数从高到低
ZREVRANGEBYLEX key max min,返回有序集中指定区间内的成员,通过字典区间,分数从高到低
ZREVRANGEBYSCORE key max min [WITHSCORES],返回有序集中指定分数区间内的成员,分数从高到低排序
ZRANK key member,返回有序集合中指定成员的索引