1.本地缓存的选型(Caffeine/Guava/自己写......)
Caffeine是一种高性能的缓存库,SpringBoot内置的本地缓存实现。(Caffeine性能是Guava Cache的6倍)
Caffeine的特性:
自动加载条目到缓存中,可选异步方式;
可以基于大小剔除;
可以设置过期时间,时间可以从上次访问或上次写入开始计算;
异步刷新;
keys自动包装在弱引用中;
values自动包装在弱引用或软引用中;
条目剔除通知;
缓存访问统计;
Caffeine提供四种类型的加载策略:
Manual手动、Loading自动、Asynchronous Manual异步手动、 Asynchronously Loading异步自动
Caffeine提供的几种剔除方式:
基于大小、基于权重、基于时间、基于引用
Guava缓存是谷歌开源的一种本地缓存,使用本机的内存来存储的,实现原理类似于ConcurrentHashMap,但前者增加了更多的元素失效策略,后者只能显示的移除元素。
Guava提供了三种基本的缓存回收方式:
基于容量回收、定时回收和基于引用回收。
定时回收有两种:按照写入时间,最早写入的最先回收;
按照访问时间,最早访问的最早回收
2.分布式缓存?(Redis/Memcached/......)
Redis:是一个开源的、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。Redis的外围由一个键、值映射的字典构成。与其他非关系型数据库主要不同在于:Redis中值的类型不仅限于字符串,还支持抽象数据类型。
Redis提供五种数据类型:string,hash,list,set及zset(sorted set)。
Redis使用了两种文件格式:全量数据和增量请求。
全量数据格式是把内存中的数据写入磁盘,便于下次读取文件进行加载;
增量请求文件是把内存中的数据序列化为操作请求,用于读取文件进行replay得到数据,序列化的操作包括SET、RPUSH、SADD、ZADD。
Redis的存储分为:内存存储、磁盘存储(所以断电也可以存储数据)和log文件三部分
Redis适用的场景:
热点数据的缓存
限时业务的运用(优惠活动,手机验证码......)
计数器相关问题(高并发秒杀活动,限制请求......)
排行榜相关问题
分布式锁
延时操作(例如用户下单未支付,设置时间看是否付款)
分页、模糊搜索
点赞、好友等相互关系的存储(set是可以自动排重的,并且set提供了判断某个成员是否在一个set集合内的重要接口,例如,每个用户关注的人存在一个集合中,就很容易实现求两个人的共同好友功能)
队列(redis有list push和list pop的命令,能够很方便的执行队列操作)
Redis不适用的场景:
数据量太大、数据访问频率非常低的业务都不适合使用Redis。
保存用户的基本信息,虽然它能够支持持久化,但是它的持久化方案并不能保证数据绝对的落地,并且还可能带来Redis性能下降,因为持久化太过频繁会增大Redis服务的压力。
Memcached:是一个免费开源的、高性能的、具有分布式内存对象的缓存系统,它通过减轻数据库负载加速动态Web应用;
Memcached的特性:
内存是一个key-value缓存;
协议简单,使用基于文本行的协议;
数据不能持久化,服务器关闭之后数据全部丢失;
互不通信的Memcached之间具有分布特征 ;
没有安全机制。
Memcached适用的场景:
memcached适合变化频繁,查询频繁
变化不频繁,但查询频繁的数据,或读多写少的场景,在电商场景中,页面数据的缓存
Memcached不适用的场景:
页面都没什么访问量
变化频繁且需要入库
数据量过大
Redis | memcached | |
线程模型 | 单进程单线程 | 单进程多线程 |
QPS/TPS | 10W+/<10w | 10W+/10w+ |
数据支持类型 | Key-value,set,map,list,String等 | Key-value |
持久化 | 支持 | 不支持 |
集群 | 能 | 能 |
数据备份 | 能 | 不能,但可以使用第三方工具 |
数据一致性 | 支持事务 | 轻量级锁CAS机制 |
list排序 | 可以 | 不可以 |
缓存策略 | LRU,FIFO,LRU | LRU |
Jcache | 支持 | 支持 |
单条数据约束 | 不同数据结构可使用不同约束规则 | 默认值:key最大长度250个,Value容量<=1M |
3.使用缓存可以解决什么问题?
(提高查询的效率/减少对于关系型数据库的访问-mysql)
4.使用缓存会带来什么问题?
(数据一致性问题,缓存穿透/缓存雪崩/缓存击穿)
5.为什么应用了缓存会有数据一致性问题?
(数据库数据更新了,缓存中数据还没更新)
6.什么是缓存穿透/缓存雪崩/缓存击穿?
缓存穿透:指客户端请求的数据在缓存中和数据库中都不存在,查询缓存不存在,然后查询数据库库也不存在,这个过程叫做缓存穿透。如果黑客攻击时,启用很多个线程,一直对这个不存在的数据发送请求 ,很容易将数据库打崩。
解决方案:缓存空对象(内存消耗多),布隆过滤器(实现复杂,存在误判)
缓存击穿:因为数据存在时效,可能前一次缓存中可以查到数据,但是过一会无法查到数据,需要从数据库中查询数据,这个过程叫做缓存穿透。
解决方案:预先设置热门数据,提前存入缓存;实时监控热门数据,调整key过期时长;二级缓存:对于热点数据进行二级缓存,并对于不同级别的缓存设定不同的失效时间;设置分布式锁。
缓存雪崩:大量的请求导致Redis无法进行处理,紧接着应用将大量请求发送到数据库层,导致数据库层的压力激增,击穿与雪崩的区别即在于击穿是对于特定的热点数据来说,而雪崩是全部数据,雪崩相当于多个击穿。
缓存穿透不是导致缓存雪崩,是导致数据库宕机
7.假如让你设计一个缓存要考虑哪些问题?
(数据的存储结构/数据的淘汰算法(当缓存快满的时候)/日志记录(命中率)/定时刷新/线程安全/序列化)
8.什么是深拷贝、浅拷贝
(深拷贝就是拷贝内容,可以理解为序列化和反序列化,浅拷贝一般拷贝地址)