redis十大数据类型
文章目录
- 一、redis字符串(String)
- set key value
- 同时获取或设置多个键值
- 获取指定区间范围内的值
- 数字增减
- 获取字符串长度和内容追加
- 分布式锁
- getset(先get再set)
- 二、redis列表(List)
- 通过索引获取列表中的元素 lindex key index
- lrem key 数字N 给定值v1 解释(删除n个值等于v1的元素)
- ltrim key 开始index 结束index,截取指定范围的值后再赋值给key
- rpoplpush 源列表 目的列表
- lset key index value
- linsert key before/after 已有值 插入的新值
- 三、redis哈希表(Hash)
- 四、redis集合(Set)
- SRANDMEMBER key [数字]
- SPOP key [数字]
- smove key1 key2 在key1里已存在的某个值
- 集合运算
- 五、redis有序集合(Zset)
- 向有序集合中加入一个元素和该元素的分数
- 按照元素分数从小到大的顺序,返回索引从start到stop中的所有元素
- zrevrange
- 获取指定分数范围的元素
- 获取元素分数
- key 某score下对应的value值,作用是删除元素
- 增加某个元素的分数
- 获取指定分数范围内的元素个数
- 从键名列表中的第一个非空排序集中弹出一个或多个元素,它们是成员分数对
- 场景应用
- 六、redis地理空间(GEO)
- GEOADD
- GEOPOS
- GEODIST
- GEORADIUS
- GEOHASH
- 七、redis基数统计(HyperLogLog)
- 基本命令
- 八、redis位图(bitmap)
- setbit
- getbit
- strlen
- bitcount
- bitop
- 应用场景
- 九、redis位域(bitfield)
- 指令
- BITFLELD key [GET type offset]
- BITFLELD key [SET type offset value]
- BITFLELD key [INCRBY type offset increment]
- 溢出控制OVERFLOW[WRAP|SAT|FAIL]
- 十、redis流(Stream)
- 底层结构和原理说明
- 指令
- 队列相关指令
- XADD
- XRANGE
- XREVRANGE
- XREVRANGE
- XDEL
- XLEN
- Xtrim
- XREAD
- 消费组相关指令
- XGROUP CREATE
- XREADGROUP GROUP
- XPENDING
- XACK向消息队列确认消息处理已完成
- XINFO用于打印Stream、Consumer、Group的详细信息
- 四个特殊符号
常用命令:
key * #查看当前库所有的key
exists key #判断某个key是否存在
type key #查看key是什么类型
del key #删除key
unlink key # 非阻塞删除,仅仅将keys从keyspace元数据中删除,真正的删除会在后续异步中操作。
ttl key # 查看还有多少秒过期,-1表示永不过期,-2表示已过期
expire key # 为给定的key设置过期时间,单位秒
move key dbindex # 将当前数据库的 key移动到给定的数据库 db 当中
select dbindex # 切换数据库【0-15】,默认为0
dbsize # 查看当前数据库key的数量
flushdb # 清空当前库
flushall # 通杀全部库
一、redis字符串(String)
- String(字符串)
- String是redis最基本的类型,一个key对应一个value
- string类型是二进制安全的,意思是redis的string可以包含任何数据,比如jpg图片或者序列化的对象
- string类型是redis最基本的数据类型,一个redis中字符串value最多可以是512M
set key value
set key value [NX|XX] [GET] [EX seconds|PX milliseconds|EXAT unix-time-seconds|PXAT unix-time-milliseconds|KEEPTTL]
同时获取或设置多个键值
MSET key value [key value ....]
MGET key [key ....]
mset/mget/msetnx
mset:同时设置一个或多个 key-value 对。
mget:获取所有(一个或多个)给定 key 的值。
msetnx:同时设置一个或多个 key-value 对,当且仅当所有给定 key 都不存在。
获取指定区间范围内的值
getrange/setrange
getrange:获取指定区间范围内的值,类似between…and的关系
从零到负一表示全部
setrange设置指定区间范围内的值,格式是setrange key值 具体值
数字增减
一定是要数据才能进行增加减少
递增数字INCR key
增加指定的整数,指定增加的步长INCRBY key increment
递减数值decr key
减少指定的整数DECRBY key decrement
获取字符串长度和内容追加
STRLEN key
APPEND key value
分布式锁
getset(先get再set)
getset:将给定 key 的值设为 value ,并返回 key 的旧值(old value)。
简单一句话,先get然后立即set
二、redis列表(List)
-
List(列表)
-
Redis列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)
-
它的底层实际是个双端链表,最多可以包含 2^32 - 1 个元素 (4294967295, 每个列表超过40亿个元素)
常用命令
一个双端链表的结构,容量是2的32次方减1个元素,大概40多亿,主要功能有push/pop等,一般用在栈、队列、消息队列等场景。
left、right都可以插入添加;
如果键不存在,创建新的链表;
如果键已存在,新增内容;
如果值全移除,对应的键也就消失了。
它的底层实际是个双向链表,对两端的操作性能很高,通过索引下标的操作中间的节点性能会较差。
127.0.0.1:6379> LPUSH list1 1 2 3 4 5
(integer) 5
127.0.0.1:6379> LRANGE list1
(error) ERR wrong number of arguments for 'lrange' command
127.0.0.1:6379> LRANGE list1 0 -1
1) "5"
2) "4"
3) "3"
4) "2"
5) "1"
127.0.0.1:6379> RPUSH list1 0
(integer) 6
127.0.0.1:6379> LRANGE list1 0 -1
1) "5"
2) "4"
3) "3"
4) "2"
5) "1"
6) "0"
127.0.0.1:6379> LPOP list1 1
1) "5"
127.0.0.1:6379> LRANGE list1 0 -1
1) "4"
2) "3"
3) "2"
4) "1"
5) "0"
127.0.0.1:6379>
通过索引获取列表中的元素 lindex key index
lrem key 数字N 给定值v1 解释(删除n个值等于v1的元素)
-
从left往right删除2个值等于v1的元素,返回的值为实际删除的数量
-
LREM list3 0 值,表示删除全部给定的值。零个就是全部值
ltrim key 开始index 结束index,截取指定范围的值后再赋值给key
ltrim:截取指定索引区间的元素,格式是ltrim list的key 起始索引 结束索引.
rpoplpush 源列表 目的列表
移除列表的最后一个元素,并将该元素添加到另一个列表并返回
lset key index value
linsert key before/after 已有值 插入的新值
在list某个已有值的前后再添加具体值
三、redis哈希表(Hash)
-
Redis hash 是一个 string 类型的 field(字段) 和 value(值) 的映射表,hash 特别适合用于存储对象。
-
Redis 中每个 hash 可以存储 2^32 - 1 键值对(40多亿)
四、redis集合(Set)
-
Redis 的 Set 是 String 类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据,集合对象的编码可以是 intset 或者 hashtable。
-
Redis 中Set集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。
-
集合中最大的成员数为 2^32 - 1 (4294967295, 每个集合可存储40多亿个成员)
127.0.0.1:6379> SADD set1 1 1 1 2 2 2 3 4 5
(integer) 5
127.0.0.1:6379> SMEMBERS set1
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
127.0.0.1:6379> SISMEMBER st1 x
(integer) 0
127.0.0.1:6379> SISMEMBER st1 1
(integer) 0
127.0.0.1:6379> SISMEMBER set1 x
(integer) 0
127.0.0.1:6379> SISMEMBER set1 1
(integer) 1
127.0.0.1:6379> SREM set1 y
(integer) 0
127.0.0.1:6379> SREM set1 1
(integer) 1
127.0.0.1:6379> SMEMBERS set1
1) "2"
2) "3"
3) "4"
4) "5"
127.0.0.1:6379> SCARD set1
(integer) 4
127.0.0.1:6379>
SRANDMEMBER key [数字]
从集合中随机展现设置的数字个数,元素不删除
SPOP key [数字]
从集合中随机弹出一个元素,出一个删一个
smove key1 key2 在key1里已存在的某个值
将key1里已存在的某个值赋给key2
集合运算
运用场景
微信抽奖小程序
微信朋友圈点赞查看同赞朋友
五、redis有序集合(Zset)
-
zset(sorted set:有序集合)
-
Redis zset 和 set 一样也是string类型元素的集合,且不允许重复的成员。
-
不同的是每个元素都会关联一个double类型的分数,redis正是通过分数来为集合中的成员进行从小到大的排序。
-
zset的成员是唯一的,但分数(score)却可以重复。
-
zset集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。 集合中最大的成员数为 2^32 - 1
向有序集合中加入一个元素和该元素的分数
按照元素分数从小到大的顺序,返回索引从start到stop中的所有元素
ZRANGE key start stop [WITHSCORES]
zrevrange
获取指定分数范围的元素
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]
获取元素分数
-
zcard :获取集合中元素个数
-
zcount :获取分数区间内元素个数,zcount key 开始分数区间 结束分数区间
-
zrank: 获取value在zset中的下标位置
-
zscore:按照值获得对应的分数
key 某score下对应的value值,作用是删除元素
删除元素,格式是zrem zset的key 项的值,项的值可以是多个
zrem key score某个对应值,可以是多个值
增加某个元素的分数
ZINCRBY key increment member
获取指定分数范围内的元素个数
ZCOUNT key min max
从键名列表中的第一个非空排序集中弹出一个或多个元素,它们是成员分数对
ZMPOP
场景应用
六、redis地理空间(GEO)
-
Redis GEO 主要用于存储地理位置信息,并对存储的信息进行操作,包括
-
添加地理位置的坐标。
-
获取地理位置的坐标。
-
计算两个位置之间的距离。
-
根据用户给定的经纬度坐标来获取指定范围内的地理位置集合
GEOADD
如何处理中文乱码
GEOPOS
GEODIST
GEORADIUS
georadius 以给定的经纬度为中心, 返回键包含的位置元素当中, 与中心的距离不超过给定最大距离的所有位置元素。
GEORADIUS city 116.418017 39.914402 10 km withdist withcoord count 10 withhash desc
GEORADIUS city 116.418017 39.914402 10 km withdist withcoord withhash count 10 desc
#WITHDIST: 在返回位置元素的同时, 将位置元素与中心之间的距离也一并返回。 距离的单位和用户给定的范围单位保持一致。
#WITHCOORD: 将位置元素的经度和维度也一并返回。
#WITHHASH: 以 52 位有符号整数的形式, 返回位置元素经过原始 geohash 编码的有序集合分值。 这个选项主要用于底层应用或者调试, 实际中的作用并不大
#COUNT 限定返回的记录数。
GEOHASH
七、redis基数统计(HyperLogLog)
-
HyperLogLog 是用来做基数统计的算法,HyperLogLog 的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定且是很小的。
-
在 Redis 里面,每个 HyperLogLog 键只需要花费 12 KB 内存,就可以计算接近 2^64 个不同元素的基 数。这和计算基数时,元素越多耗费内存就越多的集合形成鲜明对比。
-
但是,因为 HyperLogLog 只会根据输入元素来计算基数,而不会储存输入元素本身,所以 HyperLogLog 不能像集合那样,返回输入的各个元素。
基本命令
八、redis位图(bitmap)
由0和1状态表现的二进制位的bit数组
setbit
getbit
getbit key offset(偏移量)
strlen
统计字节数占用多少
bitcount
全部键里面含有1的有多少个
bitop
连续2天都签到的用户
加入某个网站或者系统,它的用户有1000W,做个用户id和位置的映射
比如0号位对应用户id:uid-092iok-lkj
比如1号位对应用户id:uid-7388c-xxx
。。。。。。
红色代表第一天
蓝色代表第二天
连续两天的只有两个人,用户id分别为0和2
这里统计签到在202106这一月某人是否签到了
蓝色代表:查询第三天这个帅哥有没有签到,返回1说明在3号这天签到了
绿色代表:查询第30天这个u1这个人有没有签到,返回0说明没签到
应用场景
按年去存储一个用户的签到情况,365 天只需要 365 / 8 ≈ 46 Byte,1000W 用户量一年也只需要 44 MB 就足够了。
假如是亿级的系统,
每天使用1个1亿位的Bitmap约占12MB的内存(10^8/8/1024/1024),10天的Bitmap的内存开销约为120MB,内存压力不算太高。
此外,在实际使用时,最好对Bitmap设置过期时间,让Redis自动删除不再需要的签到记录以节省内存开销。
九、redis位域(bitfield)
-
通过bitfield命令可以一次性操作多个比特位域(指的是连续的多个比特位),它会执行一系列操作并返回一个响应数组,这个数组中的元素对应参数列表中的相应操作的执行结果。
-
说白了就是通过bitfield命令我们可以一次性对多个比特位域进行操作。
指令
BITFLELD key [GET type offset]
BITFLELD key [SET type offset value]
BITFLELD key [INCRBY type offset increment]
溢出控制OVERFLOW[WRAP|SAT|FAIL]
- WRAP: 使用回绕(wrap around)方法处理有符号整数和无符号整数的溢出情况
-
SAT: 使用饱和计算(saturation arithmetic)方法处理溢出,下溢计算的结果为最小的整数值,而上溢计算的结果为最大的整数值
-
FAIL: 命令将拒绝执行那些会导致上溢或者下溢情况出现的计算,并向用户返回空值表示计算未被执行
十、redis流(Stream)
-
Redis Stream 是 Redis 5.0 版本新增加的数据结构。
-
Redis Stream 主要用于消息队列(MQ,Message Queue),Redis 本身是有一个 Redis 发布订阅 (pub/sub) 来实现消息队列的功能,但它有个缺点就是消息无法持久化,如果出现网络断开、Redis 宕机等,消息就会被丢弃。
-
简单来说发布订阅 (pub/sub) 可以分发消息,但无法记录历史消息。
-
而 Redis Stream 提供了消息的持久化和主备复制功能,可以让任何客户端访问任何时刻的数据,并且能记住每一个客户端的访问位置,还能保证消息不丢失
底层结构和原理说明
一个消息链表,将所有加入的消息都串起来,每个消息都有一个唯一的 ID 和对应的内容
名称 | 描述 |
---|---|
Message Content | 消息内容 |
Consumer group | 消费组,通过XGROUP CREATE 命令创建,同一个消费组可以有多个消费者 |
Last_delivered_id | 游标,每个消费组会有个游标 last_delivered_id,任意一个消费者读取了消息都会使游标 last_delivered_id 往前移动。 |
Consumer | 消费者,消费组中的消费者 |
Pending_ids | 消费者会有一个状态变量,用于记录被当前消费已读取但未ack的消息Id,如果客户端没有ack,这个变量里面的消息ID会越来越多,一旦某个消息被ack它就开始减少。这个pending_ids变量在Redis官方被称之为 PEL(Pending Entries List),记录了当前已经被客户端读取的消息,但是还没有 ack (Acknowledge character:确认字符),它用来确保客户端至少消费了消息一次,而不会在网络传输的中途丢失了没处理 |
指令
队列相关指令
XADD
添加消息到队列末尾
XADD 用于向Stream 队列中添加消息,如果指定的Stream 队列不存在,则该命令执行时会新建一个Stream 队列
* 号表示服务器自动生成 MessageID(类似mysql里面主键auto_increment),后面顺序跟着一堆 业务key/value
- 信息条目指的是序列号,在相同的毫秒下序列号从0开始递增,序列号是64位长度,理论上在同一毫秒内生成的数据量无法到达这个级别,因此不用担心序列号会不够用。millisecondsTime指的是Redis节点服务器的本地时间,如果存在当前的毫秒时间戳比以前已经存在的数据的时间戳小的话(本地时间钟后跳),那么系统将会采用以前相同的毫秒创建新的ID,也即redis 在增加信息条目时会检查当前 id 与上一条目的 id, 自动纠正错误的情况,一定要保证后面的 id 比前面大,一个流中信息条目的ID必须是单调增的,这是流的基础。
- Redis对于ID有强制要求,格式必须是时间戳-自增Id这样的方式,且后续ID不能小于前一个ID
- Stream的消息内容,也就是图中的Message Content它的结构类似Hash结构,以key-value的形式存在。
XRANGE
XREVRANGE
XREVRANGE
XDEL
XLEN
Xtrim
XREAD
用于获取消息(阻塞/非阻塞),只会返回大于指定ID的消息
非阻塞
- $代表特殊ID,表示以当前Stream已经存储的最大的ID作为最后一个ID,当前Stream中不存在大于当前最大ID的消息,因此此时返回nil
- 0-0代表从最小的ID开始获取Stream中的消息,当不指定count,将会返回Stream中的所有消息,注意也可以使用0(00/000也都是可以的……)
阻塞
redis-cli启动第2个客户端连接上来
消费组相关指令
XGROUP CREATE
用于创建消费组
$表示从Stream尾部开始消费
0表示从Stream头部开始消费
创建消费者组的时候必须指定 ID, ID 为 0 表示从头开始消费,为 $ 表示只消费新的消息,队尾新来
XREADGROUP GROUP
-
“>”,表示从第一条尚未被消费的消息开始读取
-
消费组groupA内的消费组consumer1从mystream消息队列中读取所有消息
-
但是,不同消费组的消费者可以消费同一条消息,同组的不行
-
实现负载均衡的读取(通过count来进行控制)
-
让组内的多个消费者共同分担读取消息,所以,我们通常会让每个消费者读取部分消息,从而实现消息读取负载在多个消费者间是均衡分布的
问题:基于stream实现的消息队列,如何保证消费者在发生故障或者宕机再次重启后,任然可以读取未处理完的消息? -
stream会自动使用内部队列(也称为pending list)留存消费组里每个消费者读取的消息保底措施,直到消费者,使用xack命令通知stream消息已经处理完成
-
消息确认增加了消息的可靠性,一般在业务处理完成之后,需要执行xack命令确认消息已经被消费完成
XPENDING
查询每个消费组内所有消费者【已读取,但尚未确认】的消息
查看某个消费者具体读取了哪些数据
下面抓图所示:consumer2已读取的消息的 ID是1659430293537-0
一旦消息1659430293537-0被consumer2处理了consumer2就可以使用 XACK 命令通知 Streams,然后这条消息就会被删除
XACK向消息队列确认消息处理已完成