缓存在不同的场景下,作用是不一样的具体举例说明: ✔ 操作系统磁盘缓存 ——> 减少磁盘机械操作。 ✔ 数据库缓存——>减少文件系统IO。 ✔ 应用程序缓存——>减少对数据库的查询。 ✔ Web服务器缓存——>减少应用服务器请求。 ✔ CDN缓存——>减少静态资源请求。 ✔ 客户端浏览器缓存——>减少对网站的访问。
用缓存,主要有两个用途:高性能,高并发
通俗一点来讲就是,同时更新缓存和数据库(Cache Aside 更新模式);先更新缓存,缓存负责同步更新数据库(Read/Write Through 更新模式);先更新缓存,缓存定时异步更新数据库(Write Behind Caching 更新模式)。这三种模式各有优劣,可以根据业务场景选择使用。
三种缓存模式的优缺点:
Cache Aside 更新模式实现起来比较简单,但是需要维护两个数据存储,一个是缓存(Cache),一个是数据库(Repository)。Read/Write Through 更新模式只需要维护一个数据存储(缓存),但是实现起来要复杂一些。Write Behind Caching 更新模式和Read/Write Through 更新模式类似,区别是Write Behind Caching 更新模式的数据持久化操作是异步的,但是Read/Write Through 更新模式的数据持久化操作是同步的。优点是直接操作内存速度快,多次操作可以合并持久化到数据库。缺点是数据可能会丢失,例如系统断电等。缓存是通过牺牲强一致性来提高性能的。所以使用缓存提升性能,就是会有数据更新的延迟。这需要我们在设计时结合业务仔细思考是否适合用缓存。然后缓存一定要设置过期时间,这个时间太短太长都不好,太短的话请求可能会比较多的落到数据库上,这也意味着失去了缓存的优势。太长的话缓存中的脏数据会使系统长时间处于一个延迟的状态,而且系统中长时间没有人访问的数据一直存在内存中不过期,浪费内存。
常见的缓存算法有以下几种类型: 基于访问的时间:此类算法按各缓存项被访问时间来组织缓存队列,决定替换对象。如 LRU;基于访问频率:此类算法用缓存项的被访问频率来组织缓存。如 LFU、LRU2、2Q、LIRS;访问时间与频率兼顾:通过兼顾访问时间和频率。使得数据模式在变化时缓存策略仍有较好性能。如 FBR、LRUF、ALRFU。多数此类算法具有一个可调或自适应参数,通过该参数的调节使缓存策略在基于访问时间与频率间取得一个平衡;基于访问模式:某些应用有较明确的数据访问特点,进而产生与其相适应的缓存策略。如专用的 VoD 系统设计的A&L缓存策略,同时适应随机、顺序两种访问模式的 SARC策略。可能会出现缓存穿透、缓存击穿、缓存雪崩和缓存刷新问题。
缓存穿透:缓存穿透是说收到一个请求,但是该请求缓存中不存在,只能去数据库中查询,然后放进缓存。但当有好多请求同时访问同一个数据时,业务系统把这些请求全发到了数据库;或者恶意构造一个逻辑上不存在的数据,然后大量发送这个请求,这样每次都会被发送到数据库,最终导致数据库挂掉。 【解决的办法】:对于恶意访问,一种思路是先做校验,对恶意数据直接过滤掉,不要发送至数据库层;第二种思路是缓存空结果,就是对查询不存在的数据也记录在缓存中,这样就可以有效的减少查询数据库的次数。非恶意访问,结合缓存击穿说明。缓存击穿:上面提到的某个数据没有,然后好多请求查询数据库,可以归为缓存击穿的范畴:对于热点数据,当缓存失效的一瞬间,所有的请求都被下放到数据库去请求更新缓存,数据库被压垮。 【解决的办法】:防范此类问题,一种思路是加全局锁,就是所有访问某个数据的请求都共享一个锁,获得锁的那个才有资格去访问数据库,其他线程必须等待。但现在大部分系统都是分布式的,本地锁无法控制其他服务器也等待,所以要用到全局锁,比如 Redis的 setnx实现全局锁。另一种思想是对即将过期的数据进行主动刷新,比如新起一个线程轮询数据,或者比如把所有的数据划分为不同的缓存区间,定期分区间刷新数据。第二个思路与缓存雪崩有点关系。缓存雪崩:缓存雪崩是指当我们给所有的缓存设置了同样的过期时间,当某一时刻,整个缓存的数据全部过期了,然后瞬间所有的请求都被抛向了数据库,数据库就崩掉了。 【解决的办法】:解决思路要么是分治,划分更小的缓存区间,按区间过期;要么给每个 key的过期时间加一个随机值,避免同时过期,达到错峰刷新缓存的目的。 对于 Redis 挂掉了,请求全部走数据库,也属于缓存雪崩,我们可以有以下思路进行解决: 事发前:实现 Redis 的高可用(主从架构+Sentinel 或者 Redis Cluster),尽可能避免 Redis 挂掉这种情况。 事发中:万一 Redis 真的挂了,我们可以设置本地缓存(ehcache)+ 限流(hystrix),尽量避免我们的数据库被干掉。 事发后:Redis 持久化,重启后自动从磁盘上加载数据,快速恢复缓存数据。缓存刷新:既清空缓存 ,一般在 Insert、Update、Delete 操作后就需要刷新缓存,如果不执行就会出现脏数据。但当缓存请求的系统蹦掉后,返回给缓存的值为null。参考:
https://blog.csdn.net/zhengzhaoyang122/article/details/82184029https://www.cnblogs.com/xingxia/p/cache.htmlhttps://www.jianshu.com/p/207130233e60