1.定义
关系型数据库的数据都存储在磁盘中,在高并发情况下,业务应用的查询会对关系型数据库产生的巨大 I/O 开销,为了最大程度的降低对数据库服务器的访问压力,提出了数据库缓存的概念。
2.优点
2.1.性能优越
数据库缓存的数据基本上都是存储在内存中,相比磁盘 I/O ,读写的速度快,极大缓解了数据库服务器的压力。
2.2.响应速度
数据库缓存技术应用场景绝大部分针对的是查的场景。因为在常见的应用中,数据库层的压力有80%的是查询,20%的才是数据的变更操作。所以绝大部分的应用场景的还是查缓存。数据库缓存的使用,提高应用的响应速度,提升了用户体验。
3.缓存策略
当一个数据发生变更的时候,应考虑怎么样确保缓存数据和数据库中数据保存一致性,以确保从缓存读取的数据是最新的。
3.1.写回策略
Write Back 策略,特别适合写多的场景。
在更新数据的时候,只更新缓存,同时将缓存数据设置为脏的,然后立马返回,并不会更新数据库。对于数据库的更新,会通过批量异步更新的方式进行。
3.2.读穿策略
Read Through 策略,先查询缓存中数据是否存在,如果存在则直接返回,如果不存在,则由缓存服务负责从数据库查询数据,并将结果写入到服务,最后缓存组件将数据返回给应用。
3.3.写穿策略
Write Through 策略,先查询缓存中数据是否存在,如果缓存中数据已经存在,则更新缓存中的数据,并且由缓存服务同步更新到数据库中,然后缓存服务告知应用程序更新完成;如果缓存中数据不存在,直接更新数据库,然后返回。
3.4.旁路缓存策略
Cache Aside策略,是最常用的策略。适合读多写少的场景,不适合写多的场景。
写策略的步骤:先更新数据库中的数据,再删除缓存中的数据。
读策略的步骤:如果读取的数据命中了缓存,则直接返回数据;如果读取的数据没有命中缓存,则从数据库中读取数据,然后将数据写入到缓存,并且返回给用户。
4.常见问题
4.1.缓存穿透
指访问一个缓存和数据库中都不存在的 key,由于这个 key 在缓存中不存在,则会到数据库中查询,数据库中也不存在该 key,无法将数据添加到缓存中。
解决办法有:
- 将空 key 添加到缓存中;
- 过滤空 key;
- 对请求进行身份鉴权、数据合法性校验等。
4.2.缓存击穿
指大量请求访问缓存中的一个 key 时,该 key 过期导致这些请求都去直接访问数据库,短时间大量的请求可能会将数据库击垮。
解决办法有:
- 添加互斥锁或分布式锁,总之让一个线程去访问数据库,将数据添加到缓存中后,其他线程直接从缓存中获取;
- 热点数据 key 不过期,定时更新缓存,但如果更新出问题会导致缓存中的数据一直为旧数据。
4.3.缓存雪崩
指在系统运行过程中,缓存服务宕机或大量的 key 值同时过期,导致所有请求都直接访问数据库导致数据库压力增大。
解决方法有:
- 将 key 的过期时间打散,避免大量 key 同时过期;
- 对缓存服务做高可用处理;
- 加互斥锁,同一 key 值只允许一个线程去访问数据库,其余线程等待写入后直接从缓存中获取。
5.缓存预热
缓存预热是指系统上线后,提前将相关的缓存数据加载到数据库缓存中。避免在用户请求的时候先查询数据库,然后再将数据缓存的问题,用户直接查询事先被预热的缓存数据。如果不进行预热,那么缓存初始状态数据为空,对于高并发的流量都会访问到数据库中,对数据库造成流量的压力。
解决方法为:
工程启动的时候进行加载缓存动作,数据量大的时候,设置一个定时任务脚本,进行缓存的刷新;数据量太大的时候,优先保证热点数据进行提前加载到缓存。