《玩转Redis》系列文章 by zxiaofan主要讲述Redis的基础及中高级应用,穿插企业实战案例。本文是《玩转Redis》系列第【2】篇, 最新系列文章请前往 公众号 “zxiaofan”(点我点我)查看,或 百度搜索 “玩转Redis zxiaofan”(点我点我)即可。
最新思维导图原图可联系公众号【zxiaofan】后台获取。
本文更适合用于复习总结,阅读》实战》阅读 更有效果哟,主要包含以下内容:
- String(字符串);
- List(列表);
- Set(集合);
- Hash(散列);
后续会介绍其他高级数据结构:
- Sorted Set(有序集合);
- Bitmap(位图);
- HyperLogLog;
- Streams(流);
文章思路:
- 数据结构应用场景及注意事项;
- 数据结构各命令对比分析;
异常统一说明:
error(out of range)导图简写@EOOR;
负数偏移量表示倒数第几,导图简写@LBN(last but number);
1、String
1.1、String应用场景及注意事项
1.1.1、String应用场景
String可以说是Redis中最常见的数据结构,没有之一。
String结构可存储字符串或者各种类型的二进制数据。
- 分布式锁;
- 计数器;
- 分布式全局唯一ID;
1.1.2、String注意事项
String底层结构是动态字符串,可修改指定位置数据,通过预分配冗余空间减少内存的频繁分配,实际分配的空间capacity一般要高于实际字符串长度len。当字符串长度小于1M时,扩容都是加倍现有的空间,如果超过1M,扩容时一次只会多扩1M的空间。字符串最大长度为512M(512 1024 1024个字符)。
数字及浮点数在Redis中以字符串形式存储。
// 如何证明 String最大长度是512M;
// 512M=512*1024*1024;
127.0.0.1:6379> setrange ran 536870911 a
(integer) 536870912
127.0.0.1:6379> strlen ran
(integer) 536870912
127.0.0.1:6379> append ran a
(error) ERR string exceeds maximum allowed size (512MB)
1.2、String各命令对比分析
String命令支持以下操作类型:单一操作、批量操作、字符操作、位操作、计数操作。
1.2.1、String单元素操作
【核心命令】:SET、SETNX、SETEX、PSETEX、GET、GETSET、APPEND、STRLEN;
注意:
- 【SET】:Redis2.6.12 版本支持设置value值时,同时设置过期时间,此操作为原子操作;
- 【PSETEX】:Redis2.6.0 版本支持,可将过期时间精确到毫秒;
【Redis-String单元素操作】命令简述:
命令 | 功能 | 参数 |
---|---|---|
SET | 设置value值,支持选项 | key value [expiration EX seconds/PX milliseconds] [NX/XX] |
SETNX | key不存在才允许设置 | key value |
SETEX | 设置value及过期时间(秒) | key seconds value |
PSETEX | 设置value及过期时间(毫秒) | key milliseconds value |
GET | 查询指定key | key |
GETSET | 查询返回旧值设置新值 | key value |
APPEND | value追加字符串 | key value |
STRLEN | 查询value长度 | key |
【Redis-String单元素操作】命令详细对比分析如下:
1.2.2、String批量操作
【核心命令】:MSET、MGET;
注意:
- MGET、MSET是Redis命令中的Boss,因为执行这两个命令是绝不会失败的。
- 【MSET】操作具有原子性,不存在部分key更新成功而部分key更新失败的情况;
- 【MGET】如果value不是String类型,将返回nil;
【Redis-String批量操作】命令简述:
命令 | 功能 | 参数 |
---|---|---|
MSET | 批量设置 | key value [key value ...] |
MGET | 批量查询 | key [key ...] |
【Redis-String批量操作】命令详细对比分析如下:
1.2.3、String指定范围处理
【核心命令】:SETRANGE、GETRANGE;
注意:
- 【SETRANGE、GETRANGE】 在操作对象较小时,时间复杂度近似看成O(1);
- 【SETRANGE】在特定情况下会造成服务器阻塞(value不存在或很小 偏移量offset很大),具体阻塞时长与服务器有关;
【Redis-String指定范围处理】命令简述:
命令 | 功能 | 参数 |
---|---|---|
SETRANGE | 设置指定偏移量位置的字符 | key offset value |
GETRANGE | 查询指定区间字符串 | key start end【@LBN;offset大于len将自动以len为准】 |
【Redis-String指定范围处理】命令详细对比分析如下:
1.2.4、String递增操作
【核心命令】:INCR/DECR、INCRBY/DECRBY、INCRBYFLOAT;
注意:
- String结构能存储数字?因为数字在Redis中是以字符串形式保存的;
- 【INCR/DECR】 支持加减1;
- 【INCRBY/DECRBY】 支持 加减指定整数,参数支持负数;
- 【INCRBYFLOAT】 支持 加减指定浮点数,参数支持负数;
- 递增命令时间负责度都是O(1);
【Redis-String递增操作】命令简述:
命令 | 功能 | 参数 |
---|---|---|
INCR/DECR | 递增/1递减1 | key |
INCRBY/DECRBY | 递增n/递减n | key increment(支持负数) |
INCRBYFLOAT | 递增浮点值 | key increment(支持负数) |
【Redis-String递增操作】命令详细对比分析如下:
1.2.5、String位操作
【核心命令】:SETBIT、BITOP、GETBIT、BITCOUNT、BITFIELD、BITPOS;
注意:
- 【BITOP】支持逻辑操作,且AND、或OR、异或XOR、非NOT;
- 由于按位存储非常节省空间,位操作特别适合于对连续的海量数据做标记。比如贴吧签到,标记每天是否签到,1天1标识位,则10年=10*365bit=456byte。
【Redis-String位操作】命令简述:
命令 | 功能 | 参数 |
---|---|---|
SETBIT | 指定偏移量bit位置设置值 | key offset value【0=< offset< 2^32】 |
BITOP | 对一个或多个key执行逻辑操作,并将结果保存到destkey | operation destkey key [key ...]【AND, OR, XOR, NOT】 |
GETBIT | 查询指定偏移位置的bit值 | key offset |
BITCOUNT | 统计指定区间bit为1的数量 | key [start end]【@LBN】 |
BITFIELD | 操作多字节位域 | key [GET type offset] [SET type offset value] [INCRBY type offset increment] [OVERFLOW WRAP/SAT/FAIL] |
BITPOS | 查询指定区间第一个被设置成1的bit位的位置 | key bit [start] [end]【@LBN】 |
【Redis-String位操作】命令详细对比分析如下:
2、List
2.1、List应用场景及注意事项
2.1.1、List应用场景
- List可用于构建队列(右进左出/先进先出)、栈(右进右出/先进后出);
- 存储相关数据,比如文章的相关文章ID,可用于文章推荐;
- 高级使用:quicklist快速链表;
2.1.2、List注意事项
- 元素是String,按插入顺序排序;
- 插入、弹出快,O(1);
- 索引慢(查询),O(n);
- List查询操作类似Java链表的get(int index),需要对链表遍历,性能随index的增大而降低;
- lindex的index可为负数,-1表示倒数第一个元素,-2倒数第二个;
- List的index参数存在越界问题;
-List的start、stop参数不存在越界问题;
- 列表弹出最后一个元素后,结构自动被删除,内存被回收;
- List左头右尾(记忆:我国自古就有左为尊的说法,左才是头);
2.2、List各命令对比分析
概述:
- List命令支持以下操作类型:新增元素、弹出元素、处理指定位置元素。
- List主命令L开头(左侧处理)、右侧处理目录R开头、阻塞命令B开头;
- List的超时timeout为0表示无限阻塞;
2.2.1、List新增元素
【核心命令】:LPUSH、RPUSH、LPUSHX、RPUSHX、RPOPLPUSH、BRPOPLPUSH;
注意:
- 【LPUSH / RPUSH】 支持批量添加元素;
- 【RPOPLPUSH】 拆分成2个命令理解:RPOP(src) LPUSH(dest);
- 【RPOPLPUSH】可作为安全队列:ListA取出消息放入“处理中的ListB”,处理完毕移除ListB;外挂监控ListB的超时情况;
【Redis-List新增元素操作】命令简述:
命令 | 功能 | 参数 |
---|---|---|
LPUSH / RPUSH | (批量)添加元素 | key value [value ...] |
LPUSHX / RPUSHX | 向已存在的list中添加单个元素 | key value |
RPOPLPUSH | 弹出source尾压入dest头部 | source destination |
BRPOPLPUSH | 阻塞式弹出source压入dest | source destination timeout |
【Redis-List新增元素操作】命令详细对比分析如下:
2.2.2、List弹出元素
【核心命令】:LPOP、RPOP、BLPOP、BRPOP;
注意:
- 【BLPOP】为LPOP的阻塞版本,0表示无限阻塞;
- 弹出元素操作时间复杂度都是O(1);
【Redis-List弹出元素操作】命令简述:
命令 | 功能 | 参数 |
---|---|---|
LPOP / RPOP | 弹出元素 | key |
BLPOP / BRPOP | 阻塞式弹出元素 | key [key ...] timeout |
【Redis-List弹出元素操作】命令详细对比分析如下:
2.2.3、List处理指定位置元素
【核心命令】:LSET、LINDEX、LRANGE、LTRIM、LREM;
注意:
- 【ltrim】支持保留区间内的值,可实现定长链表;
- 【LRANGE、LTRIM】不会越界;
- List处理指定位置相关命令时间复杂度可记为O(N);
【Redis-List处理指定位置元素】命令简述:
命令 | 功能 | 参数 |
---|---|---|
LSET | 指定位置设置元素 | key index value |
LINDEX | 查询指定位置元素 | key index |
LRANGE | 查询指定区间元素 | key start stop |
LTRIM | 保留指定区间元素 | key start stop |
LREM | 移除前/后count次的value元素 | key count value |
【Redis-List处理指定位置元素】命令详细对比分析如下:
3、Set
3.1、Set应用场景及注意事项
3.1.1、Set应用场景
- 类似Java的HashSet,键值无序唯一,可用于去重;
- Set支持交集运算,可用于查找QQ共同好友;
3.1.2、Set注意事项
- Set支持集合运算(差集、交集、并集);
- Set底层实现相当于特殊字典,value都是NULL;
- 集合最后一个元素移除后,结构自动删除,内存被回收;
3.2、Set各命令对比分析
概述:
- Set命令支持以下操作类型:集合运算、增删移动及统计;
- Set命令都是S开头;
3.2.1、Set增删移动及统计
【核心命令】:SADD(增)、SCADD(数量统计)、SISMEMBER(存在)、SMEMBERS(所有元素)、SREM(移除)、SMOVE(移动);
注意:
- Redis2.4 ,SADD、SREM支持批量添加元素;
- 【SMEMBERS】将返回Set中所有元素,慎用,请使用SSCAN代替;
- 【SRANDMEMBER】返回count个随机元素,支持count为负;SPOP返回并移除count个随机元素,不支持count为负(越界异常);
【Redis-Set增删移动及统计】命令简述:
命令 | 功能 | 参数 |
---|---|---|
SADD | (批量)添加元素到Set中 | key member [member ...] |
SCARD | 统计Set中元素数量 | key |
SISMEMBER | 判断指定元素是否存在于Set中 | key member |
SMEMBERS | 返回Set中的所有元素 | key |
SMOVE | 移动Set的指定元素到另一个集合 | source destination member |
SRANDMEMBER | 返回Set中count个随机元素 | key [count] |
SPOP | 移除并返回Set中count个随机元素 | key [count] |
SREM | 移除Set中指定的元素 | key member [member ...] |
SSCAN | 迭代Set | key cursor [MATCH pattern] [COUNT count] |
【Redis-Set增删移动及统计】命令详细对比分析如下:
3.2.2、Set集合运算(差集、交集、并集)
【核心命令】:差集SDIFF/SDIFFSTORE、交集SINTER/SINTERSTORE、并集SUNION/SUNIONSTORE;
注意:
- 主命令加STORE表示将对应的结果存入指定目标Set中;
- 对于“STORE”命令,如果destkey已存在,destkey的值将会被覆盖;
- 交集的时间复杂度是(N*M),差集/并集的时间复杂度是O(N);
【Redis-Set集合运算】命令简述:
命令 | 功能 | 参数 |
---|---|---|
SDIFF | 【差集】返回在第一个set中但不在其他set中的元素集合 | key [key ...] |
SDIFFSTORE | 【差集】将SDIFF结果存入destination | destination key [key ...] |
SINTER | 【交集】返回(多个)set集合的交集 | key [key ...] |
SINTERSTORE | 【交集】将多个set集合的交集存入dest | destination key [key ...] |
SUNION | 【并集】返回多个set的并集 | key [key ...] |
SUNIONSTORE | 【并集】将多个set集合的并集存入dest | destination key [key ...] |
【Redis-Set集合运算】命令详细对比分析如下:
4、Hash
4.1、Hash应用场景及注意事项
4.1.1、Hash应用场景
- 记录一个对象的多个属性,如员工的姓名/生日/职级,文章的点赞数/阅读数/收藏数;
4.1.2、Hash注意事项
- 类似Java的HashMap,数组 链表,结构是
>; - 字典key、value都只能是字符串(数字在redis里面是以 sds 字符串形式存在);
- 使用渐进式rehash策略:高性能,不堵塞服务;而HashMap的rehash是一次性hash,很耗时;
- 【优点】支持按需存取指定字段;
- 【缺点】hash结构存储消耗高于单个字符串;
4.2、Hash各命令对比分析
概述:
- Hash命令支持以下操作类型:新增、查询、统计、修改、删除(增删改查及统计);
4.2.1、Hash新增、查询元素
【核心命令】:HSET、HSETNX、HMSET;HGET、HMGET、HGETALL;
注意:
- 【HSET】field存在则覆盖;HSETNX:field不存在才赋值;
- 【HMSET、HMGET】支持批量操作;
【Redis-Hash新增、查询元素】命令简述:
命令 | 功能 | 参数 |
---|---|---|
HSET | 设置hash中指定字段的值 | key field value |
HSETNX | field不存在才设置hash中指定field的值 | key field value |
HMSET | 批量设置hash值 | key field value [field value ...] |
HGET | 查询hash中指定字段的值 | key field |
HMGET | 批量查询指定field的value | key field [field ...] |
HGETALL | 查询所有field-value列表 | key |
【Redis-Hash新增、查询元素】命令详细对比分析如下:
4.2.2、Hash统计、修改、删除
【核心命令】:HKEYS、HVALS、HLEN;HDEL、HEXISTS、HSTRLEN;HINCRBY、HINCRBYFLOAT;HSCAN;
注意:
- 支持查询Hash中所有field、所有value;
- 【HVALS】不是HVALUES;
- 【HINCRBY】支持增加Hash中指定field的值(点赞数/阅读数/收藏数);
【Redis-Hash统计、修改、删除】命令简述:
命令 | 功能 | 参数 |
---|---|---|
HKEYS | 查询所有field列表 | key |
HVALS | 查询所有value列表 | key |
HLEN | 查询hash的field数量 | key |
HDEL | 移除hash中指定field字段 | key field [field ...] |
HEXISTS | 判断hash中是否存在指定field | key field |
HSTRLEN | 查询hash中filed关联的value字符串的长度 | key field |
HINCRBY | 增加hash中指定field的值 | key field increment |
HINCRBYFLOAT | 增加hash中指定field的值 | key field increment |
HSCAN | 基于游标迭代hashes | key cursor [MATCH pattern] [COUNT count] |
【Redis-Hash统计、修改、删除】命令详细对比分析如下:
5、后记
《玩转Redis-Redis基础数据结构及核心命令》至此结束,后续将继续分享Redis其他数据结构及核心命令。
公众号搜索 【zxiaofan】【点我】查阅最新系列文章。
Life is all about choices!
将来的你一定会感激现在拼命的自己!