一、Redis是什么?
key-value形式的非关系型数据库,基于内存(64位系统默认是物理内存的四分之三),单线程多路io复用,通常当缓存使用,提高查询效率。
二、为什么使用Redis?
2.1 快(内单异高算)
内存存储,单线程模型,异步操作,高效的网络通信,优化的算法和数据结构
2.2 作用
2.2.1 五大数据类型
Redis存储,key-value形式,value的五种数据类型
String,List,Set,Hash,Zset
- String:Redis最基本的类型,二进制安全,可包含任何数据,字符串value最多512M。
- List:单键多值,value是List,底层双向链表,两端插入。快速链表(ziplist(连续空间)+链表)
- Set:自动排重,提供可判断一个元素是否在一个Set集合内,String类型的无序集合,底层value为null的hash表,添加,删除,查找O(1)
- hash:键值对集合String类型field和value的映射表。适合存储对象。
- Zset:有序不重复集合
2.2.2 用处
- String:分布式锁
- List:消息队列
- Set:自动排重
- hash:存储对象。
- Zset:排行榜,计数器
- 做缓存:key-value时间复杂度O(1),基于内存块
地理位置 - GEO
三、项目中的使用
3.1.1 使用场景操作命令
- String:存储单只数据{Json字符串}。存储订单流水号,校验防止重复提交订单。
动态字符串存储上限512M,超过512M要分片存储或使用Hash存储类型。
set key value
set key value nx timeout ex
get key
incr/decr key - List:存储队列,消息队列,实现简单的秒杀功能或发送消息,双向列表或压缩列表
lpush/rpush key value
lpop/rpop key - Set:自动排重,存储两个集合交集,并集。
sadd key member
smembers key
sinter key1 key2 --交集
sdiff key1 key2 --差集 hash:适合存储对象(便于修改维护)。 根据一级分类ID,播放量,点赞量... 排行榜:根据一级分类Id,播放量,点赞量... hset key field value key=1Id field =playNum value=List<AlbumInfoIndex> 购物车:hset key field value key=userId field=skuId value=CartInfo 哈希表,包含键值对的散列表 hset key field value hget key field hvals key == 获取购物车列表 hdel key field
Zset:有序不重复集合 热度排名{电商 销量-价格} 跳跃表和哈希表的组合, 跳跃表用来存储元素和分数, 哈希表用来存储成员和分数的映射关系 Zadd key score member Zrange key start stop Zincrby key increment
3.1.2 专辑详情
3.1.3 redis 两种完善的持久化备份机制
- AOF:
- 手动开启:以日志的形式记录服务器所处理的每一个写、删除操作,查询操作不会记录,以文本的方式记录,可以打开文件看到详细的操作记录
- 三种开启策略:
appendfsync always
(每次写操作都同步)
appendfsync everysec
(每秒同步一次)
appendfsync no
(由操作系统决定同步时机) 优点。
1. 数据安全,Redis中提供了3种同步策略,即每秒同步、每修改同步、不同步
2. 通过 append 模式写文件,即使中途服务器宕机也不会破坏已经存在的内容,可以通过 redis- check-aof 工具解决数据一致性问题
3. AOF 机制的 rewrite 模式。定期对AOF文件进行重写,以达到压缩的目的缺点
1. AOF 文件比 RDB 文件大,且恢复速度慢
2. 数据集大的时候,比 rdb 启动效率低
3. 运行效率没有RDB高
- RDB:
- 默认 在指定的时间间隔内将内存中的数据集快照写入磁盘,实际操作过程是fork一个子进程,先将数据集写入临时文件,写入成功后,再替换之前的文件,用二进制压缩存储。
- 开启策略:配置快照触发条件 save 90 10 90秒内10次
- 优点:
1. 整个Redis数据库将只包含一个文件 dump.rdb,方便持久化
2.容灾性好,方便备份
3.性能最大化,fork 子进程来完成写操作,让主进程继续处理命令
4.相对于数据集大时,比 AOF 的启动效率更高 缺点:
1.数据安全性低。RDB 是间隔一段时间进行持久化,如果持久化之前 redis 发生故障,会发生数据丢失。
2.由于RDB是通过fork子进程来协助完成数据持久化工作的,因此,如果当数据集较大时,可能会导致整个服务器停止服务几百毫秒,甚至是1秒钟
具体区别:
3.1.4 订阅与发布--类似于公众号
四、大key问题
定义:大Key问题是指在Redis数据库中存储了过大的数据结构,如大型列表、哈希、集合等
问题:
大Key占用了大量的内存空间,导致其他数据无法被缓存,从而影响Redis的性能和响应速度。
大Key的加载和传输需要较长时间,会导致读取和写入操作的延迟
在进行数据持久化(如RDB快照、AOF日志)时,大Key会增加持久化的时间和磁盘空间占用。
解决方案:
数据分片: 将大数据拆分成多个小数据,分别存储在不同的Key中。例如,将一个大型哈希表分成多个小型哈希表。
使用分布式存储: 将大数据存储在分布式数据库中,如Redis Cluster或其他分布式存储系统
合理选择数据结构: 根据实际需求,选择合适的数据结构,避免在单个Key中存储过大的数据
数据压缩: 对于可以压缩的数据,使用Redis提供的数据压缩功能,减小存储占用
使用大Key分析工具:Redis提供了一些工具可以用于识别和处理大Key问题,例如Redis内存分析工具和命令。
定期清理: 周期性地检查数据库,发现并处理大Key,例如将大Key转移至其他存储系统
合理设置过期时间:对于不再需要的数据,设置适当的过期时间,让Redis可以自动淘汰这些数据
五、热点key
定义:热Key问题是指在Redis或数据库中,某个或某些特定的键被频繁访问,导致对这些键的操作成为系统的性能瓶颈
问题:热Key问题可能会导致Redis负载过高,响应时间延长,甚至造成系统崩溃
解决方案:
1. 增加缓存容量:扩大Redis内存容量可以提高缓存命中率,减少对热Key的访问次数,从而缓解热Key问题。可以考虑升级Redis服务器或增加Redis集群节点来增加内存容量。
2. 分片:将热Key均匀地分散到多个Redis实例中,每个实例处理一部分热Key的请求。这样可以降低单个Redis实例的负载压力,提系统整体的吞吐量
3. 缓存预热:在系统启动或流量低峰期,提前加载热Key的数据到缓存中,使得这些热Key的数据在实际访问时已经存在于缓存中,减少对后端存储的访问
4. 数据分片:对于热Key所对的数据量较大的情况,可以考虑将数据进行分片存储,将不同片段的数据存放在不同的键上,从而减轻单个键的访问压力
5. 使用Redis集群:通过搭建Redis集群,将热Key分散到多个节点上,实现负载均衡和高可用性,提高系统的整体性能和稳定性
6. 缓存降级:对于某些热Key,可以考虑将其缓存时间设置较短,或者不缓存,直接访问后端存储。这样可以避免热Key对缓存系统的过度压力,同时确保其他非热Key正常缓存
集群--预热--数据分片--缓存降级
六、淘汰策略
6.1 noeviction:不淘汰
不淘汰任何数据,如果内存已经满了,不支持客户端写入新的数据,会直接发出拒绝,返回错误
6.2 过期时间的数据中进行淘汰 (redis 4.0之前)
volatile-random:在设置了过期时间的键值对中,进行随机删除
volatile-ttl:根据过期时间的先后进行删除,越早过期的越先被删除。
volatile-lru:会使用 LRU 算法筛选设置了过期时间的键值对。场景:置顶新闻、置顶视频。
volatile-lfu:会使用 LFU 算法选择设置了过期时间的键值对。
allkeys-random:从所有键值对中随机选择并删除数据。场景:如果业务应用中的数据访问频率相差不大,没有明显的冷热数据区分
allkeys-lru:使用 LRU 算法在所有数据中进行筛选,推荐:最近最常访问的数据留在缓存中,提升应用的访问性能,场景:业务数据中有明显的冷热数据区分
allkeys-lfu:使用 LFU 算法在所有数据中进行筛选
LRU/LFU 算法:
- LRU (Least recently used) 最近最少使用,如果数据最近被访问过,那么将来被访问的几率也更高。
- LFU (Least frequently used) 最不经常使用,如果一个数据在最近一段时间内使用次数很少,那么在将来一段时间内被使用的可能性也很小。
七、集群
7.1 哨兵 AP
- 动态监控主动上位
1. sentinel 以每秒一次发送 ping 命令信息
2. 如果在一定时间范围内,没有回复,则标记为主观下线
3. sentinel 监听master 确认是否主观下线
4. 多个sentinel 确认master 主观下线,则标记为客观下线
5. 是否有足够的sentinel同意master 下线
ping--->主--->客
哨兵 ID
sentinel myid 1
# 监听地址
bind 127.0.0.1
# 监听端口
port 26379
# 日志文件路径
logfile "/var/log/redis/sentinel.log"
7.2 主从复制 AP
slaveof ip port
原理: 开启异步线程;第一次执行全量IO; 后续增量IO
7.3 过半机制 CP
去中心化:redis-cluster
原理:根据计算出slot的位置存储数据 slot:16384 set name admin ---> 数据存储过程 使用crc16 算法 根据key(name)与16384 进行取模运算,得到一个数值,这个数值就是slot的位置。
使用slot位置来存储数据的好处:
数据分片:实现水平分片,便于集群的扩展和提高吞吐量
高可用:有多个副本,当节点宕机副本依然可以使用
动态扩缩容:会随着节点数变化而变化
简化数据迁移:只需要迁移slot
分-->高-->扩-->移