Redis持久化机制及缓存失效解决方案
Redis集群故障监测及哨兵机制原理解析
Redis海量数据存储方案Redis Cluster
前言
在之前的文章写过redis的实用功能,包括数据结构,主从复制结构,以及应对高并发海量数据场景下的分片redis cluster 集群;本篇文章继续学习redis框架应对缓存失效,以及持久化机制及内存管理出现的问题,以及提供的解决方案及思想。
概述
在redis中缓存失效的原因主要是重启导致数据失效, 解决方案 RDB、AOF持久化机制。以及aof中为什么能保证数据在断电或重启不失效的原因,提供不同的fsync策略:完全没有fsync,每秒fsync,每个查询fsync。使用默认策略fsync时,每秒的写入性能仍然很好(fsync是使用后台线程执行的,并且在没有进行fsync的情况下,主线程将尽力执行写入操作。)保证数据不失效;缓存中常见的内存淘汰与过期管理机制,保证数据更新;以及缓存雪崩分析及解决方案,在redis中利用ehcache 缓存降级,或者Redis备份和快速预热 等都可以避免 缓存出现缓存雪崩问题。
Redis的持久化机制
![](/assets/blank.gif)
持久化的方式
redis中既有RDB持久化,也有AOF持久化,两者是可以并存的。对于数据要求非常高的情况下,官方是推荐使用AOF,在配置文件中使用 redis.conf中对应的开启方式
在磁盘中对应的文件名为appendonly.aof
对应rdb与aof的持久化配置策略
RDB 持久化
RDB 持久化方式能够在指定的时间间隔对你的数据进行快照存储
Redis客户端直接通过命令BGSAVE或者SAVE来创建一个内存快照
- BGSAVE 调用fork来创建一个子进程,子进程负责将快照写入磁盘,而父进程仍然继续处理命令。
- SAVE 执行SAVE命令过程中,不再响应其他命令。
# 900秒之内至少一次写操作
save 900 1
# 300秒之内至少发生10次写操作
save 300 10
# 60秒之内发生至少10000次
save 60 10000
优点
AOF(append only file)持久化
![](/assets/blank.gif)
appendonly yes
#每次有数据修改发生时都会写入AOF文件,非常安全非常慢
appendfsync always
#每秒钟同步一次,该策略为AOF的缺省策略,够快可能会丢失1秒的数据
appendfsync everysec
#不主动fsync,由操作系统决定,更快,更不安全的方法
appendfsync no
优点
Redis丢失数据的可能性
Redis中淘汰策略
Redis在内存空间不足的时候,为了保证命中率,就会选择一定的数据淘汰策略,这个和我们操作系统中的页面置换算法类似。
内存分配
- Strings类型:一个String类型的value最大可以存储512M。
- Lists类型:list的元素个数最多为2^32-1个,也就是4294967295个。
- Sets类型:元素个数最多为2^32-1个,也就是4294967295个。
- Hashes类型:键值对个数最多为2^32-1个,也就是4294967295个
# 最大内存控制
maxmemory 最大内存阈值
maxmemory-policy 到达阈值的执行策略
单位是字节 ,利于精确控制
内存压缩
当内存达到配置量时,会做一个内存压缩 ,这些配置都是压缩优化内存手段。
#配置字段最多512个
hash-max-zipmap-entries 512
#配置value最大为64字节
hash-max-zipmap-value 64
#配置元素个数最多512个
list-max-ziplist-entries 512
#配置value最大为64字节
list-max-ziplist-value 64#配置元素个数最多512个
set-max-intset-entries 512
#配置元素个数最多128个
zset-max-ziplist-entries 128
#配置value最大为64字节
zset-max-ziplist-value 64
大小超出压缩范围,溢出后Redis将自动将其转换为正常大小,减少cpu的消耗
过期数据的处理策略
Reids的种淘汰策略:
主动处理( redis 主动触发检测key是否过期)每秒执行10次。过程如下:
过期数据的计算和计算机本身的时间是有直接联系的。
LRU算法
- 核心思想:如果数据最近被访问过,那么将来被访问的几率也更高。
- 注意:Redis的LRU算法并非完整的实现,完整的LRU实现是因为这需要太多的内存。
- 方法:通过对少量keys进行取样(50%),然后回收其中一个最好的key。
配置方式: maxmemory-samples 5
结构是通过链表+map来进行实现的,当淘汰也是淘汰链表尾的数据
产生的代价就是 访问、删除都需要遍历链表
LFU算法
- Redis实现的是近似的实现,每次对key进行访问时,用基于概率的对数计数器来记录 访问次数,同时这个计数器会随着时间推移而减小。
- Morris counter算法依据: https://en.wikipedia.org/wiki/Approximate_counting_algorithm
- 启用LFU算法后,可以使用热点数据分析功能。( redis-cli --hotkeys )
Redis内存回收策略
noeviction 客户端尝试执行会让更多内存被使用的命令直接报错
allkeys-lru 在所有key里执行LRU算法
volatile-lru 在所有已经过期的key里执行LRU算法
volatile-lfu 使用过期集在密钥中使用近似LFU进行驱逐
allkeys-lfu 使用近似LFU逐出任何键
allkeys-random 在所有key里随机回收
volatile-random 在已经过期的key里随机回收
volatile-ttl 回收已经过期的key,并且优先回收存活时间(TTL)较短的键
适合缓存的数据
三个维度评判数据是否合适缓存
缓存穿透、缓存雪崩的解决方案
缓存穿透
- 高峰期大面积缓存Key失效。(所有请求全部访问后端数据库)
类似12306网站,因为用户频繁的查询车次信息,假设所有车次信息都建立对应的缓存,那么如果所有车次建立缓存的时间一样,失效时间也一样,那么在缓存失效的这一刻,也就意味着所有车次的缓存都失效。通常当缓存失效的时候我们需要重构缓存,这时所有的车次都将面临重构缓存,即出现问题1的场景,此时数据库就将面临大规模的访问。
- 局部高峰期,热点缓存Key失效。(导致海量的请求直击数据库) 缓存数据有效期到来的那一瞬间
春节马上快到了,抢票回家的时刻也快来临了。通常我们会事先选择好一个车次然后疯狂更新车次信息,假设此时这般车的缓存刚好失效,可以想象会有多大的请求会直怼数据库。
这会造成数据库的压力是非常大的,有可能导致数据库连接占满,有可能会影响其他功能,大量占用数据库连接,导致其他应用访问该DB数据库时,都会等待着,查询慢的情况。这就是缓存雪崩,缓存失效。
缓存雪崩风险
![](/assets/blank.gif)
解决方案
- 在redis中设置过期时间,设置不一样的过期时间
- 不需要大量的请求来恢复缓存,采用互斥锁;把数据库不存在的数据,也缓存起来,短期过滤,过滤一些不存在的key.
- 拿到锁的线程负责更新缓存,其他请求读取备份缓存数据或者执行降级策略;
备份缓存通常是不设置过期时间的,异步更新的缓存。
- 限流限次限频。
- 服务降级 对应用前端请求降级
使用锁的机制对商品进行 处理的形式
public class GoodsService2 {private final Logger logger = LoggerFactory.getLogger(GoodsService2.class);@Resource(name = "mainRedisTemplate")StringRedisTemplate mainRedisTemplate;@AutowiredDatabaseService databaseService;Lock lock = new ReentrantLock();/*** 查询商品库存数** @param goodsId 商品ID* @return 商品库存数*/// @Cacheable 不管用什么样的方式,核心步骤 1,2,3public Object queryStock(final String goodsId) throws InterruptedException {// 1. 先从redis缓存中获取余票信息String cacheKey = "goodsStock-"+goodsId;String value = mainRedisTemplate.opsForValue().get(cacheKey);if (value != null) {logger.warn(Thread.currentThread().getName() + "缓存中取得数据==============>" + value);return value;}// 2000 请求// 同步 一个个来lock.lock(); // 2000 线程 1个线程拿到,1999 等待排队try {// 再次获取缓存value = mainRedisTemplate.opsForValue().get(cacheKey);if (value != null) {logger.warn(Thread.currentThread().getName() + "缓存中取得数据==============>" + value);return value;}// 拿到锁 重建缓存// 2. 缓存中没有,则取数据库value = databaseService.queryFromDatabase(goodsId);System.out.println(Thread.currentThread().getName() + "从数据库中取得数据==============>" + value);// 3. 塞到缓存,120秒过期时间final String v = value;mainRedisTemplate.execute((RedisCallback<Boolean>) connection -> {return connection.setEx(cacheKey.getBytes(), 120, v.getBytes());});} finally {lock.unlock();}return value;}
}
Redis持久化机制及缓存失效解决方案相关推荐
- Redis持久化机制(RDB VS AOF)
Redis持久化机制 Redis持久化机制由来 一.RDB机制 1.1 工作原理 1.2 RDB的配置 1.3 修改RDB配置的快照策略 1.3.1 自定义RDB持久化策略 1.3.2 服务宕机RDB ...
- Redis系列:Redis持久化机制与Redis事务
Redis 是个基于内存的数据库.那服务一旦宕机,内存中数据必将全部丢失.所以丢失数据的恢复对于 Redis 是十分重要的,我们首先想到是可以从数据库中恢复,但是在由 Redis 宕机时(说明相关工作 ...
- Redis系列之Redis持久化机制
Redis持久化机制 为什么要持久化 如果Redis再次访问时,发现Redis的数据是空的,就会形成缓存穿透.更重要的是,因为Redis的数据是空的,所以客户端想要访问的key都没有,就会造成大量的请 ...
- Redis持久化机制
1.简单介绍一下Redis Redis是使用C语言开发的数据库,不过与传统数据库不同的是Redis的数据是存在内存中的,也就是内存数据库,读写速度非常的快,因此Redis被广泛应用于缓存方向. 2.R ...
- redis的通用命令 || redis持久化机制:(RDB || AOF)
通用命令 1. keys * : 查询所有的键 2. type key : 获取键对应的value的类型 3. del key:删除指定的key value 持久化 ...
- 缓存使用-4、Redis 持久化机制
一.redis启动时载入持久化文件的流程. 二.redis两种持久化机制 两种持久化机制是RDB和AOF机制,下面介绍下是什么和优缺点. RDB持久化是指用数据集快照的方式记录redis数据库的所有键 ...
- redis持久化机制,深入分析redisAOF和RDB模式的利弊
文章目录 写在前面 日志文件-AOF AOF的格式 AOF的写入方式 三种写回策略 AOF 中开启 always 刷盘策略也会存在数据丢失吗? AOF配置为每秒刷盘,有可能阻塞Redis,影响性能吗? ...
- Redis系列(五)Redis持久化机制
文章目录 Redis持久化 为什么需要持久化 RDB 概念 触发条件(什么时候触发?) 自动触发 手动触发 通过RDB文件恢复数据 优势 不足 AOF 概念 同步机制 重写机制 重写过程 重写触发条件 ...
- Redis持久化机制——随记2
引言 Redis官方提供了两种不同的持久化方法来将数据存储到硬盘里面分别是: (1)快照(Snapshot) (2)AOF (Append Only File)只追加日志文件 1.快照机制 1.1.特 ...
最新文章
- 【124】排球基本技术
- CentOS6.8 x86_64bit MySQL简单语句应用
- Facebook如何向十亿人推荐东西
- django 连接mysql 数据库
- PyTorch模块类
- [云炬创业管理笔记]第二章测试6
- QT的QUrl类的使用
- 物联网(车联网)平台架构方案
- [css] 如何解决html设置height:100%无效的问题?
- 深入理解ArrayList
- 《BI那点儿事》数据流转换——透视
- ubuntu 安装chrome浏览器
- PAT(Basic Level)--个位数统计
- 计算机网络误区——源目IP和源目MAC变化问题
- 关于static的使用
- poj Gone Fishing 枚举加贪心 当初做的很纠结啊!!终于A了,与大家分享一下经验
- IIS 添加支持json格式文件
- Springboot 系列(九)使用 Spring JDBC 和 Druid 数据源监控
- 前端开发常用网站整理
- oppo9s刷机教程_oppor9s怎么自己刷机很简单的技巧
热门文章
- Oracle报错ORA-01653: 表xx无法通过 8192 (在表空间 xx_data 中) 扩展
- Silverlight 动画实现--太阳升起、落下
- Caused by: java.lang.ClassNotFoundException: org.apache.log4j.Priority 的解决办法
- 小程序如何使用vant
- 用GVIM替代Val(a)IDE!
- 基于scrapy+mongodb的智联招聘网站信息爬取
- 第二十三章 案例分析
- sql查询去除某列重复
- 稳定性领导者 阿里云获得信通院多项系统稳定性认证
- 《百万巨鳄》特效揭密