目录
五种基本数据类型
String字符串
特点
- 二进制安全,可以包含任何数据,如数字,字符串,jpg图片或者序列化的对象
应用场景
-
缓存: redis作为缓存层,mysql做持久化层,降低mysql的读写压力
-
计数器:redis是单线程模型,一个命令执行完才会执行下一个,同时数据可以一步落地到其他的数据源
-
session:常见方案spring session + redis实现session共享
相关命令
命令 | 简述 | 使用 |
---|---|---|
GET | 获取存储在给定键中的值 | GET key |
SET | 设置存储在给定键中的值 | SET key value |
DEL | 删除存储在给定键中的值 | DEL key |
INCR | 将键存储的值加1 | INCR key |
DECR | 将键存储的值减1 | DECR key |
INCRBY | 将键存储的值加上整数 | INCRBY key num |
DECRBY | 将键存储的值减去整数 | DECRBY key num |
List列表
特点
- 底层实现为双端链表
应用场景
-
时间轴
-
消息队列
相关命令
命令 | 简述 | 使用 |
---|---|---|
RPUSH | 将给定值推入到列表右端 | RPUSH key value |
LPUSH | 将给定值推入到列表左端 | LPUSH key value |
RPOP | 从列表的右端弹出一个值,并返回被弹出的值 | RPOP key |
LPOP | 从列表的左端弹出一个值,并返回被弹出的值 | LPOP key |
LRANGE | 获取列表在给定范围上的所有值 | LRANGE key 0 -1 |
LINDEX | 通过索引获取列表中的元素。可以使用负数下标,以 -x表示列表的倒数第x个元素 | LINDEX key index |
Hash哈希
特点
- 存储k-v,适合存储对
应用场景
- 缓存: 更直观,相比string更节省空间的维护缓存信息,如用户信息,视频信息等
相关命令
命令 | 简述 | 使用 |
---|---|---|
HSET | 添加键值对 | HSET hash-key sub-key1 value1 |
HGET | 获取指定散列键的值 | HGET hash-key key1 |
HGETALL | 获取散列中包含的所有键值对 | HGETALL hash-key |
HDEL | 如果给定键存在于散列中,那么就移除这个键 | HDEL hash-key sub-key1 |
Set集合
特点
-
不能出现重复的数据
-
添加,删除,查找的复杂度都是 O(1)
应用场景
- 标签:给用户添加标签,或者用户给消息添加标签,有同一标签或者类似标签的可以给推荐关注的事或者关注的人
- 点赞,或点踩,收藏等,可以放到set中实现
相关命令
命令 | 简述 | 使用 |
---|---|---|
SADD | 向集合添加一个或多个成员 | SADD key value |
SCARD | 获取集合的成员数 | SCARD key |
SMEMBERS | 返回集合中的所有成员 | SMEMBERS key member |
SISMEMBER | 判断 member 元素是否是集合 key 的成员 | SISMEMBER key member |
ZSet有序集合
特点
- 每个元素都会关联一个 double 类型的分数。redis 通过分数来为集合中的成员进行从小到大的排序
应用场景
- 排行榜:有序集合经典使用场景。例如小说视频等网站需要对用户上传的小说视频做排行榜,榜单可以按照用户关注数,更新时间,字数等打分,做排行。
- 其他排名
相关命令
命令 | 简述 | 使用 |
---|---|---|
ZADD | 将一个带有给定分值的成员添加到有序集合里面 | ZADD zset-key score1 member1 [score2 member2] |
ZRANGE | 根据元素在有序集合中所处的位置,从有序集合中获取多个元素,可以使用负数下标 | ZRANGE zset-key start end [WITHSCORES] |
ZREM | 如果给定元素成员存在于有序集合中,那么就移除这个元素 | ZREM zset-key member1 |
三种特殊数据类型
HyperLogLogs基数统计
特点
- 节省空间
- 有一定误差(0.81% 标准错误的近似值)
应用场景
- 统计各种计数,比如注册 IP 数、每日访问 IP 数、页面实时UV、在线用户数,共同好友数等
BitMaps位图
特点
- 操作二进制位来进行记录,只有 0 和 1 两个状态
- 节省空间
应用场景
- 统计用户信息,活跃,不活跃! 登录,未登录! 打卡,不打卡! 两个状态的,都可以使用 Bitmaps
geospatial地理位置
特点
- 两极无法直接添加
- 有效的经度从-180度到180度
- 有效的纬度从-85.05112878度到85.05112878度
应用场景
- 附近的人
- 两地之间的距离
Stream
特点
- 可持久化、分组消费
- 客户端可以平滑扩展,提高处理能力
应用场景
- 消息队列
独立消费
在不定义消费者组的情况下,进行独立消费,当Stream没有新的消息时,可以阻塞等待,独立消费指定xread
# 头部读取一条消息
xread block 0 count 1 streams codehole $
使用xread进行顺序消费,一定要记住当前消费到哪里了,也就是返回的消息ID。下次继续调用xread时,将上次返回的最后一个消息ID作为参数传递进去,就可以继续消费后续的消息。
block 0表示永远阻塞,直到消息到来,block 1000表示阻塞1s,如果1s内没有任何消息到来,就返回nil
相关命令
XGROUP CREATE - 创建消费者组
XREADGROUP GROUP - 读取消费者组中的消息
XACK - 将消息标记为"已处理"
XGROUP SETID - 为消费者组设置新的最后递送消息ID
XGROUP DELCONSUMER - 删除消费者
XGROUP DESTROY - 删除消费者组
XPENDING - 显示待处理消息的相关信息
XCLAIM - 转移消息的归属权
XINFO - 查看流和消费者组的相关信息;
XINFO GROUPS - 打印消费者组的信息;
XINFO STREAM - 打印流信息
更多了解
消息ID的时间回拨问题
Redis生成的消息ID,由两部分组成:时间戳-序号。时间戳是毫秒级单位,是生成消息的Redis服务器时间,它是个64位整型(int64)。序号是在这个毫秒时间点内的消息序号,它也是个64位整型。由于一个redis命令的执行很快,所以可以看到在同一时间戳内,是通过序号递增来表示消息的。
为了保证消息是有序的,Redis生成的ID是单调递增有序的。由于ID中包含时间戳部分,为了避免服务器时间错误而带来的问题(例如服务器时间延后了),Redis的每个Stream类型数据都维护一个latest_generated_id属性,用于记录最后一个消息的ID。若发现当前时间戳退后(小于latest_generated_id所记录的),则采用时间戳不变而序号递增的方案来作为新消息ID(序号使用int64保证有足够多的的序号),从而保证ID的单调递增性质。
PS:ID是支持自定义的
消息丢失问题
结论:消费者崩溃不会带来消费丢失。
STREAM 设计了 Pending 列表,用于记录读取但并未处理完毕的消息。命令XPENDIING
用来获消费组或消费内消费者的未处理完毕的消息.
每个Pending的消息有4个属性:
- 消息ID
- 所属消费者
- IDLE,已读取时长
- delivery counter,消息被读取次数
消费者处理完毕了,使用命令 XACK 完成告知消息处理完成,
消费者宕机问题
需要将pending中的消息转移给其他消费者处理。
转移除了要指定消息ID,还需要指定IDLE(未被处理的时间),保证是长时间未处理的才被转移。消息被转移后IDLE会被重置,因为可能出现消息同时转移给多个消费者的并发操作,重置IDLE后,后面的转移就不会成功。
死信问题
某个消息,不能被消费者处理,即不能被XACK,长时间处于Pending列表中,即使被反复的转移给各个消费者也是如此。此时该消息的delivery counter就会累加,当累加到预设的临界值时,就认为是坏消息(也叫死信,DeadLetter,无法投递的消息),由于有了判定条件,将坏消息处理掉即可,删除一个消息使用XDEL语法。此时并没有删除Pending中的消息,可以执行XACK标识其处理完毕。
XDEL mq 1553585533795-1