### 正文
在实际的工作项目中, 缓存成为高并发、高
性能架构的关键组件 ,那么Re
dis为什么可以作为缓存使用呢?首先可以作为缓存的两个主要特征:
* 在分层系统中处于内存/
cpu具有访问
性能良好,
* 缓存数据饱和,有良好的数据淘汰机制
由于Re
dis 天然就具有这两个特征,Re
dis基于内存操作的,且其具有完善的数据淘汰机制,十分适合作为缓存组件。
其中,基于内存操作,容量可以为32-96GB,且操作时间平均为100ns,操作效率高。而且数据淘汰机制众多,在Re
dis 4.0 后就有8种了促使Re
dis作为缓存可以适用很多场景。
那Re
dis缓存为什么需要数据淘汰机制呢?有哪8种数据淘汰机制呢?
### 数据淘汰机制
Re
dis缓存基于内存实现的,则其缓存其容量是有限的,当出现缓存被写满的情况,那么这时Re
dis该如何处理呢?
Re
dis对于缓存被写满的情况,Re
dis就需要缓存数据淘汰机制,通过一定淘汰规则将一些数据刷选出来
删除,让缓存服务可再使用。那么Re
dis使用哪些淘汰策略进行刷选
删除数据?
在Re
dis 4.0 之后,Re
dis 缓存淘汰策略6+2种,
包括分成三大类:
* 不淘汰数据
* no
eviction ,不进行数据淘汰,当缓存被写满后,Re
dis不提供服务直接返回
错误。
* 在设置过期时
间的键值对中,
* volatile-random ,在设置过期时
间的键值对中
随机删除
* volatile-ttl ,在设置过期时
间的键值对,基于过期时
间的先后进行
删除,越早过期的越先被
删除。
* volatile-lru , 基于LRU(Least Recently Used) 算法筛选设置了过期时
间的键值对, 最近最少使用的原则来筛选数据
* volatile-lfu ,使用 LFU( Least Frequently Used ) 算法选择设置了过期时
间的键值对, 使用频率最少的键值对,来筛选数据。
* 在所有的键值对中,
* allkeys-random, 从所有键值对中
随机选择并
删除数据
* allkeys-lru, 使用 LRU 算法在所有数据中进行筛选
* allkeys-lfu, 使用 LFU 算法在所有数据中进行筛选
![](http://www.icode9.com/i/li/?n=2&i=images/20210704/1625401512800650.jpg)
> **Note**: LRU( 最近最少使用,Least Recently Used)算法, LRU维护
一个双向链表 ,链表的头和尾分别表示 MRU 端和 LRU 端,分别代表最近最常使用的数据和最近最不常用的数据。
>
> LRU 算法在实际实现时,需要用链表管理所有的缓存数据,这会带来额外的空间开销。而且,当有数据被访问时,需要在链表上把该数据移动到 MRU 端,如果有大量数据被访问,就会带来很多链表移动操作,会很耗时,进而会降低 Re
dis 缓存
性能。
其中,LRU和LFU 基于Re
dis的对象结构re
disObject的lru和refcount
属性实现的:
```
typedef struct re
disObject {
unsigned type:4;
unsigned encoding:4;
// 对象最后一次被访问的时间
unsigned lru:LRU_BITS; /* LRU time (relative to global lru_clock) or
* LFU data (least significant 8 bits frequency
// 引用计数 * and most significant 16 bits access time). */
int refcount;
void *ptr;
} robj;
```
Re
dis的LRU会使用re
disObject的lru记录最近一次被访问的时间,
随机选取参数maxmemory-samples 配置的
数量作为候选集合,在其中选择 lru
属性值最小的数据淘汰出去。
在实际项目中,那么该如何选择数据淘汰机制呢?
* 优先选择 allkeys-lru算法,将最近最常访问的数据留在缓存中,提升应用的访问
性能。
* 有顶置数据使用 volatile-lru算法 ,顶置数据不设置缓存过期时间,其他数据设置过期时间,基于LRU 规则进行筛选 。
在理解了Re
dis缓存淘汰机制后,来看看Re
dis作为缓存其有多少种模式呢?
### Re
dis缓存模式
Re
dis缓存模式基于是否接收写请求,可以分成只读缓存和读写缓存:
只读缓存:只处理读操作,所有的更新操作都在
数据库中,这样数据不会有丢失的风险。
* Cache Aside模式
![](http://www.icode9.com/i/li/?n=2&i=images/20210704/1625401512636883.jpg)
读写缓存,读写操作都在缓存中执行,出现宕机故障,会导致数据丢失。缓存回写数据到
数据库有分成两种同步和异步:
* 同步:访问
性能偏低,其更加侧重于保证数据可靠性
* Read-Throug模式
*
write-through模式
* 异步:有数据丢失风险,其侧重于提供低延迟访问
* Write-Behind模式
![](http://www.icode9.com/i/li/?n=2&i=images/20210704/1625401513635465.jpg)
#### Cache Aside模式
查询数据先从缓存读取数据,如果缓存中不存在,则再到
数据库中读取数据,
获取到数据之后更新到缓存Cache中,**但更新数据操作,会先去更新
数据库种的数据,然后将缓存种的数据失效。**
而且Cache Aside模式会存在并发风险:执行读操作未命中缓存,然后
查询数据库中取数据,数据已经
查询到还没放入缓存,同时
一个更新写操作让缓存失效,然后读操作再把
查询到数据加载缓存,导致缓存的脏数据。
#### Read/Write-Throug模式
查询数据和更新数据都直接访问缓存服务,**缓存服务同步方式地将数据更新到
数据库**。出现脏数据的概率较低,但是就强依赖缓存,对缓存服务的稳定性有较大要求,但同步更新会导致其
性能不好。
#### Write Behind模式
查询数据和更新数据都直接访问缓存服务,**但缓存服务使用异步方式地将数据更新到
数据库(通过异步任务)**?速度快,效率会非常高,但是数据的一致性比较差,还可能会有数据的丢失情况,实现逻辑也较为复杂。
在实际项目开发中根据实际的业务场景需求来进行选择缓存模式。那了解上述后,我们的应用中为什么需要使用到re
dis缓存呢?
在应用使用Re
dis缓存可以提高系统
性能和并发,主要体现在
* 高
性能:基于内存
查询,KV结构,简单逻辑运算
* 高并发:
MysqL 每秒只能
支持2000左右的请求,Re
dis轻松每秒1W以上。让80%以上
查询走缓存,20%以下
查询走
数据库,能让系统吞吐量有很大的提高
虽然使用Re
dis缓存可以大大提升系统的
性能,但是使用了缓存,会出现一些问题,比如,缓存与
数据库双向不一致、缓存雪崩等,对于出现的这些问题该怎么
解决呢?
### 使用缓存常见的问题
使用了缓存,会出现一些问题,主要体现在:
* 缓存与
数据库双写不一致
* 缓存雪崩: Re
dis 缓存无法处理大量的应用请求,转移到
数据库层导致
数据库层的压力激增;
* 缓存穿透:访问数据不存在在Re
dis缓存中和
数据库中,导致大量访问穿透缓存直接转移到
数据库导致
数据库层的压力激增;
* 缓存击穿:缓存无法处理高频热点数据,导致直接高频访问
数据库导致
数据库层的压力激增;
#### 缓存与
数据库数据不一致
**只读缓存(Cache Aside模式)**
对于**只读缓存(Cache Aside模式)**, 读操作都发生在缓存中,数据不一致只会发生在**删改操作**上(新增操作不会,因为新增只会在
数据库处理),当发生删改操作时,缓存将数据中标志为无效和更新
数据库 。因此在更新
数据库和
删除缓存值的过程中,无论这两个操作的执行顺序谁先谁后,只要有
一个操作失败了就会出现数据不一致的情况。
### 最后
即使是面试跳槽,那也是
一个学习的过程。只有全面的复习,才能让我们更好的充实自己,武装自己,为自己的面试之路不再坎坷!**今天就给大家
分享一个Github上全面的Java面试题大全,就是这份面试大全助我拿下大厂Offer,月薪提至30K!**
[**资料领取方式:蓝色传送门**](https://docs.qq.com/doc/DSmxTbFJ1cmN1R2dB)
**我也是第一时间
分享出来给大家,希望可以帮助大家都能去往自己心仪的大厂!为金三银四做准备!**
一共有20个知识点专题,分别是:
####
dubbo面试专题
![](http://www.icode9.com/i/li/?n=2&i=images/20210704/1625401513412552.jpg)
**JVM面试专题**
![这个GItHub上的Java项目开源了,2020最全的Java架构面试复习指南](http://www.icode9.com/i/li/?n=2&i=images/20210704/1625401513944839.jpg)
**Java并发面试专题**
![这个GItHub上的Java项目开源了,2020最全的Java架构面试复习指南](http://www.icode9.com/i/li/?n=2&i=images/20210704/1625401513513043.jpg)
**Kafka面试专题**
![这个GItHub上的Java项目开源了,2020最全的Java架构面试复习指南](http://www.icode9.com/i/li/?n=2&i=images/20210704/1625401513605058.jpg)
**MongDB面试专题**
![这个GItHub上的Java项目开源了,2020最全的Java架构面试复习指南](http://www.icode9.com/i/li/?n=2&i=images/20210704/1625401514508177.jpg)
**MyBatis面试专题**
![这个GItHub上的Java项目开源了,2020最全的Java架构面试复习指南](http://www.icode9.com/i/li/?n=2&i=images/20210704/1625401514761626.jpg)
**
MysqL面试专题**
![这个GItHub上的Java项目开源了,2020最全的Java架构面试复习指南](http://www.icode9.com/i/li/?n=2&i=images/20210704/1625401514356818.jpg)
**Netty面试专题**
![这个GItHub上的Java项目开源了,2020最全的Java架构面试复习指南](http://www.icode9.com/i/li/?n=2&i=images/20210704/1625401514232525.jpg)
**RabbitMQ面试专题**
![这个GItHub上的Java项目开源了,2020最全的Java架构面试复习指南](http://www.icode9.com/i/li/?n=2&i=images/20210704/1625401515680423.jpg)
**Re
dis面试专题**
![这个GItHub上的Java项目开源了,2020最全的Java架构面试复习指南](http://www.icode9.com/i/li/?n=2&i=images/20210704/1625401515482800.jpg)
**Spring Cloud面试专题**
![这个GItHub上的Java项目开源了,2020最全的Java架构面试复习指南](http://www.icode9.com/i/li/?n=2&i=images/20210704/1625401515518314.jpg)
**SpringBoot面试专题**
![这个GItHub上的Java项目开源了,2020最全的Java架构面试复习指南](http://www.icode9.com/i/li/?n=2&i=images/20210704/1625401515575518.jpg)
**zookeeper面试专题**
![这个GItHub上的Java项目开源了,2020最全的Java架构面试复习指南](http://www.icode9.com/i/li/?n=2&i=images/20210704/1625401515976228.jpg)
**常见面试算法题汇总专题**
![这个GItHub上的Java项目开源了,2020最全的Java架构面试复习指南](http://www.icode9.com/i/li/?n=2&i=images/20210704/1625401515956590.jpg)
**计算机网络基础专题**
![这个GItHub上的Java项目开源了,2020最全的Java架构面试复习指南](http://www.icode9.com/i/li/?n=2&i=images/20210704/1625401517945103.jpg)
**设计模式专题**
![这个GItHub上的Java项目开源了,2020最全的Java架构面试复习指南](http://www.icode9.com/i/li/?n=2&i=images/20210704/1625401517676450.jpg)