String
String 的底层数据结构是 int 和 SDS(Simple Dynamic String),相比 C 的原生字符串,增加了以下功能
- 保存二进制文件
- 获取字符串长度的时间复杂度是 O(1)
- SDS API 内存安全,保证不会造成缓冲区溢出
内部编码
int,若字符串保存的是整数值,并且可以转换为 long,那么该字符串对象的编码被设置为
int。
embstr,若字符串长度小于等于 44 字节(博主测试环境为 Redis 7.4.1),那么使用
embstr编码,一次内存分配。只读,修改内容需先转换raw编码。
raw,若字符串长度大于 44 字节,那么使用
raw编码,两次内存分配。
常用指令
设置 key 为字符串值。 如果 key 已有值,无论其类型如何,都会被覆盖。 在 SET 操作成功后,之前与键值相关的任何生存时间都将被丢弃。
1 2SET key value [NX | XX] [GET] [EX seconds | PX milliseconds | EXAT unix-time-seconds | PXAT unix-time-milliseconds | KEEPTTL]EX– 设置指定的过期时间,以秒(正整数)为单位。PX– 设置指定的过期时间,以毫秒(正整数)为单位。EXAT– 设置指定的密钥过期时间,以秒(正整数)为单位。PXAT– 设置密钥过期的 Unix 时间,以毫秒为单位(正整数)。NX– 当且仅当 key 不存在时才设置。XX– 无论如何都会设置 key。KEEPTTL– 继承上一个 key 的有效时间。GET– 返回存储在密钥中的旧字符串,如果密钥不存在,则返回 nil。 如果键值不是字符串,会返回错误并中止 SET。
将给定的键设置为各自的值。 两者都是原子式的,因此所有给定键都会被一次性设置。
1 2MSET key value [key value ...] MSETNX key value [key value ...] # key 必须均不存在对 key 中存储数字进行加法操作,如果键不存在,则在执行操作前将其设置为 0。
1 2INCR key # 将存储在键上的数字递增 1。 INCRBY key increment # 将存储在键上的数字递增 increment对 key 中存储数字进行减法操作,如果键不存在,则在执行操作前将其设置为 0。
1 2DECR key # 将存储在键上的数字递减 1。 DECRBY key increment # 将存储在键上的数字递减 increment获取 key 的值。 如果键不存在,则返回特殊值 nil。
1 2GET key MGET key [key ...]
应用场景
缓存对象
计数器
分布式锁
若 key 不存在,则显示插入成功,表示加锁成功
若 key 存在,则显示插入失败,表示加锁失败
需要配合 Lua 脚本实现原子性
共享 Session 信息
List
List 是简单的字符串列表(按照插入顺序排序),可以从头部或者尾部向 List 添加元素,链表最大长度为 $2^{32}-1$
内部实现
- 3.2 版本之前由双向链表或压缩链表实现。
- 3.2 版本之后由 QuickList 实现。其是多个节点(压缩列表)组成的双向链表,每个元素可以是一个整数或一个字节数组。
常用指令
将所有指定值插入存储在 key 处的列表头部。 如果 key 不存在,则在执行推送操作前将其创建为空列表。 如果 key 持有的值不是 list,则会返回错误信息。
1LPUSH/RPUSH key element [element ...]
![]() LPUSH 命令 | ![]() RPUSH 命令 |
仅在 key 已存在并持有一个列表的情况下,在 key 所在列表的首部插入指定值。 如果 key 不存在,则不会执行任何操作。
1LPUSHX/RPUSHX key element [element ...]删除并返回存储在 key 处的列表的 最初/最后 一个元素。 默认情况下,该命令从列表 头部/尾部 弹出一个元素。 如果提供了可选的 count 参数,则根据列表的长度,回复最多包含 count 个元素。
1LPOP/RPOP key [count]
BLPOP/BRPOP 是一种阻塞列表弹出原语。 它是 LPOP/RPOP 的阻塞版本,因为当没有元素从任何给定列表中弹出时,它会阻塞连接。 元素会从第一个非空列表的 头部/尾部 弹出,并按照给定键的顺序进行检查。
1BLPOP/RLPOP key [key ...] timeout返回存储在 key 中的列表中位于 index 索引处的元素。 索引以 0 为单位,因此 0 表示第一个元素,1 表示第二个元素,以此类推。 负指数可用于指定从列表尾部开始的元素。 这里,-1 表示最后一个元素,-2 表示倒数第二个元素,以此类推。
1LINDEX key index返回存储在 key 处的 list 的长度。 如果 key 不存在,则将其解释为空列表,并返回 0。 如果 key 中存储的值不是 list,则会返回错误信息。
1LLEN key返回存储在 key 处的列表的指定元素。 偏移量 start 和 stop 是基于 0 的索引,0 代表列表的第一个元素(列表的头),1 代表下一个元素,以此类推。 这些偏移量也可以是负数,表示从列表的末尾开始的偏移量。 例如,-1 是列表的最后一个元素,-2 是倒数第二个元素,以此类推。
1LRANGE key start stop从存储在 key 处的列表中移除与元素相同的元素的第一个出现次数。 计数参数对操作的影响如下:count > 0:删除从头部移到尾部的与元素相同的元素。 count < 0:删除从尾部移到头部的与元素相同的元素。 例如,LREM list -2 “hello “将删除存储在 list 中的 “hello “的最后两次出现。 请注意,不存在的键会被当作空 list 处理。
1LREM key count element裁剪现有列表,使其只包含指定范围的元素。 start 和 stop 都是基于 0 的索引,其中 0 代表列表的第一个元素(头部),1 代表下一个元素,依此类推。 例如,LTRIM foobar 0 2 将修改存储在 foobar 处的列表,使其只保留列表的前三个元素: start 和 end 也可以是负数,表示与列表末尾的偏移量,其中 -1 表示列表的最后一个元素,-2 表示倒数第二个元素,依此类推。 超出范围的索引不会产生错误:如果 start 大于列表末尾,或 start > end,结果将是一个空列表(导致键被移除)。 如果 end 大于列表末尾,Redis 会将其视为列表的最后一个元素。
1LTRIM key start stop将索引处的列表元素设置为指定值。
1LSET key index element将元素插入存储在 key 处的列表中的参考值 pivot 之前或之后。 如果 key 不存在,则视为空列表,不执行任何操作。 如果 key 存在但不包含列表值,则返回错误信息。
1LINSERT key <BEFORE | AFTER> pivot elementBRPOPLPUSH 是 RPOPLPUSH 的阻塞变体。 当源代码包含元素时,该命令的行为与 RPOPLPUSH 完全相同。 在 MULTI/EXEC 块内使用时,该命令的行为与 RPOPLPUSH 完全相同。 当源为空时,Redis 会阻塞连接,直到有其他客户端向其推送或超时。 如果超时为零,则会无限期阻塞。
1BRPOPLPUSH source destination timeout
应用场景
- 消息队列
- 消息保存:LPUSH + RPOP / RPUSH+LPOP 实现消息队列(使用 BRPOP 命令进行阻塞式读取,减少消费者性能损失)
- 重复消息处理:生产者实现全局唯一 ID
- 消息可靠性:BRPOPLPUSH(使得消费者从一个 List 中读取消息,同时 Redis 还会把消息再插入到另一个 List 留存)
- List 不支持多个消费者消费同一条信息
Hash
Hash 是一个 key-value 集合,
内部实现
![]() listpack | ![]() hashtable |
- 如果 Hash 元素小于 512(默认) 个,所有值小于 64 字节(默认)时,Redis 会使用 listpack 作为底层数据结构。
- 剩余情况,Redis 会使用 hashtable实现
常用命令
将指定字段的值设置为存储在 key 的哈希值中各自的值。 HSET 会覆盖哈希值中存在的指定字段的值,HSETNX 对于已存在的字段操作无效。 如果 key 不存在,则会创建一个新的散列键。
1 2HSET key field value [field value ...] HSETNX key field valueHGET/HMGET 返回键存储的哈希值中与字段相关的值。 对于散列中不存在的每个字段,都会返回一个 nil 值。 由于不存在的键被视为空哈希值,因此针对不存在的键运行 HMGET 将返回一个 nil 值列表。
HGETALL 返回存储在 key 处的哈希值的所有字段和值。
1 2 3HGET key field HMGET key field [field ...] HGETALL key从存储在 key 中的哈希值中删除指定字段。 不存在于散列中的指定字段将被忽略。 如果没有字段,则删除散列。 如果键不存在,则将其视为空散列,此命令返回 0。
1HDEL key field [field ...]返回存储在 key 中的哈希值所包含字段的数量。
1HLEN key如果字段是存储在 key 处的哈希值中的现有字段,则返回 1,否则返回 0。
1HEXISTS key fieldHKEYS 返回存储在 key 处的哈希值中的所有字段名。
HVALS 返回键存储的哈希值中的所有值。
1 2HKEYS key HVALS keyHINCRBY 按增量递增存储在 key 的哈希值中的字段数字。 如果 key 不存在,则会创建一个新的哈希值键。 如果字段不存在,则在执行操作前将其值设置为 0。
HINCRBYFLOAT 按指定增量递增存储在键值处的散列指定字段,该字段代表一个浮点数。 如果增量为负值,结果是哈希字段值递减而不是递增。 如果字段不存在,则在执行操作前将其设置为 0。
1 2HINCRBY key field increment HINCRBYFLOAT key field increment
应用场景
- 缓存对象
- (key,field,value) 对应 (对象,属性,值)
- 购物车
- 添加商品:HSET cart:{user_id}{goods_id} 1
- 增加数量:HINCRBY cart:{user_id}{goods_id} 2
- 商品总数:HLEN cart:{user_id}
- 删除商品:HDEL cart:{user_id} {goods_id}
- 获取所有商品:HGETALL cart:{usert_id}
Set
Set 是一个集合(最多支持存储 $2^{32}-1$ 个元素),其中元素无序、唯一。除了支持集合内的增删改查,还支持多个集合交集、并集、差集。
内部实现
- 如果集合元素都是整数,并且元素个数小于 512(默认),Redis 会使用 整数集合作为底层数据结构。
- 其他情况,Redis 会使用 listpack 作为底层数据结构
![]() intset | ![]() listpack |
常用命令
将指定的成员添加到存储在 key 处的集合中。 如果指定的成员已经是这个集合的成员,则会被忽略。 如果 key 不存在,则会先创建一个新集合,然后再添加指定的成员。 如果存储在 key 中的值不是一个集合,则会返回错误信息。
1SADD key member [member ...]从存储在 key 处的集合中删除指定的成员。 不属于此集合的指定成员将被忽略。 如果 key 不存在,则将其视为空集,此命令返回 0。
1SREM key member [member ...]返回存储在 key 处的集合值的所有成员。
1SMEMBERS key返回成员是否是存储在 key 中的集合的成员。
1SISMEMBER key member返回存储在 key 处的集合的元素个数。
1SCARD keySRANDMEMBER 将从存储在 key 处的集合值中随机返回 count 个元素,元素不从 key 中删除。
SPOP 将从存储在 key 处的集合值中随机返回 count 个元素,元素从 key 中删除。
1 2SRANDMEMBER key [count] SPOP key [count]将成员从源集合移动到目标集合。 该操作是原子操作。 如果源集合不存在或不包含指定元素,则不执行任何操作,并返回 0。 否则,该元素将从源集合中删除,并添加到目标集合中。 如果指定的元素已存在于目标集合中,则只会从源集合中移除。 如果源集合或目标集合中不存在集合值,则会返回错误信息。
1SMOVE source destination memberSINTER 返回所有给定集合的交集所产生的集合的成员。
SINTERSTORE 该命令等同于 SINTER,但不是返回结果集,而是将其存储在目的地中。 如果目的地已经存在,则会被覆盖。
1 2SINTER key [key ...] SINTERSTORE destination key [key ...]
应用场景
- 点赞(元素唯一)
- 共同好友(集合运算)
- 数据量较大时,可以让从库进行集合运算,将结果返回给客户端,防止 Redis 阻塞。
- 抽奖(元素唯一,去重)
Zset
Zset 相较于 Set 多了个排序属性 score,每个存储元素相当于两个值组成,一个是有序集合的元素值,一个是排序值。
内部实现
- 若 Zset 中元素小于 128 个,且每个元素小于 64 字节,Redis 使用 listpack 作为底层数据结构。
- 剩余情况,Redis 会使用
![]() listpack | ![]() skiplist |
常用命令
将具有指定分数的所有指定成员添加到存储在 key 处的排序集合中。 可以指定多个分数/成员对。 如果指定的成员已经是排序集合的成员,则会更新得分,并将元素重新插入正确的位置,以确保排序正确。 如果 key 不存在,则会创建一个新的排序集合,并将指定的成员作为唯一成员,就像排序集合为空一样。 如果键存在,但没有排序集,则会返回错误信息。 分数值应是双精度浮点数的字符串表示。 +inf 和 -inf 值也是有效值。
1ZADD key [NX | XX] [GT | LT] [CH] [INCR] score member [score member ...]- XX: 只更新已存在的元素,不添加新元素。
- NX: 只添加新元素,不更新已存在的元素。
- LT: 只在新分数小于当前分数时更新现有元素。此标记不会阻止添加新元素。
- GT: 仅在新分数大于当前分数时更新现有元素。 此标记不会阻止添加新元素。
- CH: 将返回值从增加的新元素数量修改为改变的元素总数(CH 是 changed 的缩写)。 更改的元素是指新增的元素和已存在的元素,这些元素的分值已被更新。 因此,命令行中指定的元素如果得分与过去相同,则不计算在内。 注意:通常情况下,ZADD 的返回值只计算新增元素的数量。
- INCR: 指定该选项时,ZADD 的作用与 ZINCRBY 类似。 在这种模式下,只能指定一个分数元素对。
从存储在 key 中的排序集合中删除指定的成员。 如果 key 存在但没有排序集,则会返回错误信息。
1ZREM key member [member ...]返回排序集合中 key 处成员的得分。 如果排序集合中不存在成员或 key 不存在,则返回 nil。
1ZSCORE key member返回存储在 key 处的排序集的元素个数。
1ZCARD key用增量递增键值存储的排序集合中成员的得分。 如果成员不存在于排序集合中,则会以增量作为其得分(就像它之前的得分是 0.0)。 如果 key 不存在,则会创建一个以指定成员为唯一成员的新排序集。 如果 key 存在但不包含排序集,则会返回错误信息。 分数值应是数值的字符串表示,并接受双精度浮点数。 可以提供一个负值来递减分数。
1ZINCRBY key increment member返回存储在 key 中的排序集合中元素的指定范围。 ZRANGE 可以执行不同类型的范围查询:按索引(秩)、按分数或按词典顺序。
默认情况下,该命令执行索引范围查询。 start 和 stop 参数代表基于零的索引,其中 0 代表第一个元素。 这些参数指定了一个包含范围,例如,ZRANGE myzset 0 1 将同时返回排序集的第一个和第二个元素。 索引也可以是负数,表示从排序集末尾开始的偏移量,-1 表示排序集的最后一个元素。
当提供 BYSCORE 选项时,命令的行为与 ZRANGEBYSCORE 类似,返回排序集中分数等于或介于 start 和 stop 之间的元素范围。
使用 REV 选项会反转排序集,索引 0 将作为得分最高的元素。
当使用 BYLEX 选项时,命令的行为与 ZRANGEBYLEX 类似,并返回排序集合中 start 和 stop 之间的元素范围。 请注意,词典排序依赖于所有元素具有相同的分数。 有效的 start 和 stop 必须以 ( 或 [ 开头,以便分别指定范围区间是排他的还是包含的。
1ZRANGE key start stop [BYSCORE | BYLEX] [REV] [LIMIT offset count] [WITHSCORES]1 2ZUNIONSTORE destination numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE <SUM | MIN | MAX>] # 并集 ZDIFFSTORE destination numkeys key [key ...] # 第一个集合和之后集合的差集
应用场景
排行榜(有序唯一)
电话、姓名排序
BitMap
BitMap 是一串连续的二进制数组,可以通过偏移量定位元素,适合数据量大且使用二值统计的场景。
内部实现
String 类型是会保存为二进制的字节数组
常用命令
设置或清除存储在 key 处字符串值偏移量的位。 位的设置或清除取决于值,值可以是 0 或 1。当 key 不存在时,将创建一个新的字符串值。 字符串的增长是为了确保它能容纳偏移量处的位。 偏移参数必须大于或等于 0,且小于 2^32(这将位图限制在 512MB)。
1SETBIT key offset value返回存储在 key 处的字符串值中偏移量处的比特值。
1GETBIT key offset获取指定范围内值为 1 的个数,默认以字节为单位。
1BITCOUNT key [start end [BYTE | BIT]]在多个键(包含字符串值)之间执行位操作,并将结果存储到目标键中。
1BITOP <AND | OR | XOR | NOT> destkey key [key ...]
应用场景
签到统计
判断用户登陆态
HyperLogLog
HyperLogLog 是一种用于统计基数的数据集合类型,基数统计就是指统计一个集合中不重复的元素个数。HyperLogLog 的统计规则基于概率完成,标准误算率为 0.81%。
内部实现
^ - ^
常见命令
将所有元素参数添加到存储在作为第一个参数指定的变量名下的 HyperLogLog 中。
1PFADD key [element [element ...]]使用单键调用时,返回存储在指定变量中的 HyperLogLog 的基数估算值,如果变量不存在,则返回 0。 使用多键调用时,通过内部合并存储在所提供键中的 HyperLogLog 成一个临时的 HyperLogLog,返回所传递的 HyperLogLog 联合的基数估算值。
1PFCOUNT key [key ...]将多个 HyperLogLog 值合并为一个 HyperLogLog 。如果目标 HyperLogLog 不存在(默认为空 HyperLogLog),则创建。 如果存在,则将其视为源集之一。
1PFMERGE destkey [sourcekey [sourcekey ...]]
应用场景
- 网页用户访问(UV)计数
GEO
主要用于存储地理信息
内部实现
底层复用 Zset,使用 GeoHash 实现了经纬度到 Zset 中元素的权重分数的转换,关键机制是 二维地图区间划分 和 区间编码 。地理位置转换为经纬度后,使用区间编码标识,并将编码值作为 Zset 的权重分数。
常用命令
存储指定的地理位置信息,将经度,纬度,位置名称添加到指定的 key 中
1GEOADD key [NX | XX] [CH] longitude latitude member [longitude latitude member ...]- XX: 只更新已存在的元素,从不添加元素。
- NX: 不更新已存在的元素。
- CH: 不更新已存在的元素。 总是添加新元素: 将返回值从添加的新元素数修改为更改的元素总数。 更改的元素是指新增的元素和坐标已更新的已有元素。
返回关键字处排序集所代表的地理空间索引中所有指定成员的位置(经度、纬度)。
1GEOPOS key [member [member ...]]返回排序集所代表的地理空间索引中两个成员之间的距离。 单位必须是以下之一,默认为米:m 表示米。 km 表示公里。 mi 表示英里。 ft 表示英尺。
1GEODIST key member1 member2 [M | KM | FT | MI]返回使用 GEOADD 填充了地理空间信息的排序集合的成员,这些成员位于以中心位置和距中心最大距离(半径)指定的区域边界内。
1 2 3GEORADIUS key longitude latitude radius <M | KM | FT | MI> [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count [ANY]] [ASC | DESC] [STORE key | STOREDIST key]
应用场景
- 位置信息服务
Stream
专为消息队列设计的数据类型,支持消息持久化、自动生成全局唯一 ID、支持 ACK 确认消息、支持消费组模式
内部实现
^ - ^
常见命令
将指定的数据流条目添加到指定键的数据流中。 如果键值不存在,则使用流的值创建键值。 可以使用 NOMKSTREAM 选项禁用创建数据流键。
1 2XADD key [NOMKSTREAM] [<MAXLEN | MINID> [= | ~] threshold [LIMIT count]] <* | id> field value [field value ...]返回数据流中的条目数。 如果指定的键不存在,命令将返回 0。
1XLEN keyXREAD 从一个或多个数据流中读取数据,只返回 ID 大于调用者报告的最后接收 ID 的条目。 该命令有一个选项,可在项目不可用时阻塞。
XREADGROUP 命令是 XREAD 命令的一个特殊版本,支持消费者组。
1 2XREAD [COUNT count] [BLOCK milliseconds] STREAMS key [key ...] id [id ...] XREADGROUP GROUP group consumer [COUNT count] [BLOCK milliseconds] [NOACK] STREAMS key [key ...] id [id ...]从数据流中删除指定条目,并返回已删除条目的数量。
1XDEL key id [id ...]该命令返回与给定 ID 范围匹配的数据流条目。
1XRANGE key start end [COUNT count]XPENDING 查询每个消费组内所有消费者 已读取、尚未确认 的消息。
XACK 向消息队列确认消息处理已完成
1 2XPENDING key group [[IDLE min-idle-time] start end count [consumer]] XACK key group id [id ...]







