Redis
2025-05-04 01:28:52 0 举报
AI智能生成
redis啊
作者其他创作
大纲/内容
基础部分
mysql数据库限制
在高并发场景下,可能面临性能瓶颈、数据库连接压力、锁竞争、缓存不足和扩展受限
解决方案
读的多
缓存系统
redis
redis(Remote dictionary server)
一个开源的内存数据存储系统,用作数据库、缓存和消息中间件
解决问题
高性能缓存
数据全部存储在内存中,具有极快的读写速度,适用于频繁读写的场景,显著提高程序的响应速度和吞吐量
数据持久化
可以将数据保存到磁盘上,防止数据丢失,在重启后将数据重新加载到内存中
分布式缓存
多个应用程序共享同一个redis集群,提高缓存的命中率和整体性能,还有数据分片、数据复制、故障转移
发布订阅消息系统
通过发布订阅模式实现消息的发布和订阅机制,进行消息的异步传递和广播、实现解耦和消息通信
数据结构
字符串:string
最基本的key-value结构
key是唯一标识,value是具体的值
value可以是字符串,也可以是数字(整型或浮点类型)
value最多可以容纳的数据长度是512m
内部实现
主要是int和SDS(简单动态字符串)
SDS相比于C原生字符串的优势
不仅可以保存文本数据,也可以保存二进制数据
SDS使用len属性的值判断字符串是否结束,而不是空字符来判断的
所有操作api都会以处理二进制的方式处理SDS存放在buf[]数组里的数据
获取字符串长度的时间复杂度为O(1)
SDS结构使用len属性记录了字符串的长度,而C字符串不记录自身长度,获取时需要遍历
SDS api是安全的,拼接字符串不会造成缓冲区溢出
SDS在扩容字符串前会判断内存空间是否满足要求,不满足就不扩容
value的类型
整型
整数值可以用long类型表示,则会将值存储在字符串对象结构的ptr属性里,字符串编码为int
字符串:长度界限每个版本不一样
长度小于等于44字节
使用SDS保存,字符串编码为embstr
embstr编码是专门用于保存短字符串的一种优化编码方式
通过一次内存分配一块连续内存空间来保存redisObject和SDS,减少了指针寻址操作,而且分配和创建都只需要一次调用
但若字符串长度增加是需要重新分配内存的,主那成raw编码方式
即embstr编码的字符串对象实际上是只读的
长度大于44字节
使用SDS保存,字符串编码为raw
通过两次内存分配分别存储redisObject和SDS
常用命令
基本操作
设置值
set name axemc
获取值
get name
删除值
del name
判断值
exists name
获取值长度
strlen name
批量操作
批量设置值
mset name1 axemc1 name2 axemc2
批量获取值
mget name1 name2
整型操作
设置值
set numer 0
递增值
incr number
增加值
incrby number 10
递减值
decr number
减少值
decrby number 10
过期操作(默认永不过期)
设置值过期
expire name 60
查看值过期
ttl name
设置值并设置过期
set name axemc ex 60
setex name 60 axemc
判断操作
不存在再设置值
setnx name axemc
应用场景
缓存对象
缓存对象的json
SET user:1 '{"name":"xiaolin", "age":18}'
key属性分离
MSET user:1:name xiaolin user:1:age 18 user:2:name xiaomei user:2:age 20
常规计数
计算文章的阅读量:redis处理命令是单线程的,即符合原子性
SET aritcle:readcount:1001 0
INCR aritcle:readcount:1001
GET aritcle:readcount:1001
分布式锁
set命令的nx参数:key不存在才插入
加锁
SET lock_key unique_value NX PX 10000
是否设置
NX:不存在才设置
XX:存在才设置
设置过期
PX:设置毫秒值
EX:设置秒值
解锁:多操作,使用lua脚本保证原子性
需要先判断当前操作的客户端是加锁的客户端,是的话才能删除
// 释放锁时,先比较 unique_value 是否相等,避免锁的误释放
if redis.call("get",KEYS[1]) == ARGV[1] then
return redis.call("del",KEYS[1])
else
return 0
end
if redis.call("get",KEYS[1]) == ARGV[1] then
return redis.call("del",KEYS[1])
else
return 0
end
共享seesion信息
单系统重启不影响用户登陆信息或分布式系统需要共享登陆信息
各个系统间session信息不共享
通过redis同一管理这些session信息的存储和管理
列表:list
按照传入顺序排序的简单字符串列表,可以头部和尾部插入元素
列表的最大长度为2^32-1,即列表超多40亿元素
内部实现
低版本
元素的个数小于512个(list-max-ziplist-entries参数控制)
&每个元素的值都小于64(list-max-ziplist-value控制)字节
&每个元素的值都小于64(list-max-ziplist-value控制)字节
使用压缩列表
反之使用双向链表
高版本:3.2
quicklist
常用命令
基本操作
将一个或多个插入头部
LPUSH key value [value ...]
后插入的在最前面
将一个或多个插入尾部
RPUSH key value [value ...]
后插入的在最后面
移除头部元素并返回
LPOP key
移除尾部元素并返回
RPOP key
返回指定范围区间值(闭区间),支持正序和逆序
LRANGE key start stop
大规模数据
LTRIM
LTRIM mylist 1 3
用于修剪列表,仅保留指定索引范围内的元素,超出部分将被删除
用于精准控制列表范围,适合队列管理和数据窗口
保留最新 N 条数据
SCAN
SCAN 0 MATCH user:* COUNT 10 # 分批扫描以 "user:" 开头的键,每次最多返回10个
渐进式遍历键,避免一次性加载所有键导致的性能问题
替代KEYS实现高性能键遍历,适用于大数据量场景
获取元素,没有就等待timeout秒,timeout=0就一直阻塞
从头部获取元素
BLPOP key [key ...] timeout
要操作的列表键名(可指定多个)
从尾部获取元素
BRPOP key [key ...] timeout
要操作的列表键名(可指定多个)
应用场景
消息队列
必要条件:消息保序、处理重复的消息、保证消息可靠性
list
消息保序
按先进先出顺序存取的
RPUSH+LPOP(合理点)
LPUSH + RPOP
存在问题:消费者不能感知,需要不停的循环获取值,造成性能问题
阻塞式获取:BRPOP
处理重复的消息
每个元素都需要有个全局的id,消费者记录处理过的id
list不会自动生成这个id,需要业务层自己生成
LPUSH mq "111000102:stock:99"
保证消息可靠性
元素被获取后就不存在list中了,若消费者处理过程中出现问题,则无法再次处理
BRPOPLPUSH:留存
让消费者从一个 List 中读取元素,同时会把这个元素再插入到另一个 List(可以叫作备份 List)留存
等出问题后可以从备份list中获取这个元素
方案缺陷
不支持多消费者消费同一条消息,
需要消费组,list类型不支持消费组
stream
哈希:hash
一个键值对key-value的集合,特别适合存储对象
内部实现
低版本
元素个数少于512个(hash-max-ziplist-entries参数控制)
&所有值小于64字节(hash-max-ziplist-value参数控制)
&所有值小于64字节(hash-max-ziplist-value参数控制)
使用压缩列表
反之使用哈希表
高版本:7.0
listpack
常用命令
基本操作
设置值
HSET key field value
获取值
HGET key field
删除值
HDEL key field
批量操作
批量设置值
HMSET key field value [field value...]
批量获取值
HMGET key field [field ...]
批量删除值
HDEL key field [field ...]
返回元素的数量
HLEN key
返回所有元素
HGETALL key
为指定元素加n
HINCRBY key field n
应用场景
缓存对象
整体结构和对象的结构类似
设置值
HMSET uid:1 name Tom age 15
获取值
HGETALL uid:1
一般对象使用string+json存储,频繁变化的属性可以使用hash类型存储
购物车
用户id为key,商品id、商品数量为元素
回显的时候在从数据获取完整的信息
具体操作
添加商品
HSET cart:{用户id} {商品id} 1
添加数量
HINCRBY cart:{用户id} {商品id} 1
商品总数
HLEN cart:{用户id}
删除商品
HDEL cart:{用户id} {商品id}
获取所有商品
HGETALL cart:{用户id}
集合:set
一个无序且唯一的键值集合
最多可以存储2^32-1个元素
和list的区别
set不可以存储重复的元素
set存储的数据是无序的
支持交并差集运算
计算复杂较高,建议从库做聚合统计或在客户端完成聚合统计
内部实现
全是整数&元素的个数小于512(set-maxintset-entries参数控制)
使用整数集合
反之使用哈希表
常用命令
基本操作
设置值
SADD key member [member ...]
获取值
SREM key member [member ...]
删除值
SMEMBERS key
获取元素个数
SCARD key
判断元素是否存在
SISMEMBER key member
随机获取指定个数元素
删除元素
SPOP key [count]
不删除元素
SRANDMEMBER key [count]
运算操作
交集运算
SINTER key [key ...]
存到新的集合
SINTERSTORE destination key [key ...]
并集运算
SUNION key [key ...]
存到新的集合
SUNIONSTORE destination key [key ...]
差集运算
SDIFF key [key ...]
存到新的集合
SDIFFSTORE destination key [key ...]
应用场景
点赞
文章id是key,value是用户id
可以保证一个用户只能点一个赞
共同关注
通过交集计算出共同关注的好友
抽奖活动
抽奖活动名是key,value是员工名
允许重复中奖使用SRANDMEMBER,反之使用SPOP
有序集合:sorted set
内部实现
常用命令
应用场景
bitmap
内部实现
常用命令
应用场景
hyperloglog
内部实现
常用命令
应用场景
geo
内部实现
常用命令
应用场景
stream
内部实现
常用命令
应用场景
进阶部分
缓存淘汰策略
持久化
高阶部分
缓存问题
高可用
分布式锁
事务
热key
大key
0 条评论
下一页