一、缓存设计1、缓存的作用在业务系统中,查询时最容易出现性能问题的模块,查询面对的数据量大,筛选条件复杂,所以在系统架构中引入缓存层,则是非常必要的,用来缓存热点数据,达到快速响应的目的 。
缓存使用的基本原则:
- 所有缓存数据,必须设置过期时间;
- 核心业务流程不通过缓存层;
- 缓存层移除,不影响现有流程;
- 系统各个端首页数据不实时查询;
- 报表数据不实时查询加载;
- 归档数据(定时统计的结果数据)不实时查询;
2、缓存设计模式Cache-Aside模式
业务中最常用的缓存层设计模式,基本实现逻辑和相关概念如下:
文章插图
- 缓存命中:直接查询缓存且命中,返回数据;
- 缓存加载:查询缓存未命中,从数据库中查询数据,获取数据后并加载到缓存;
- 缓存失效:数据更新写到数据库,操作成功后,让缓存失效,查询时候再重新加载;
- 缓存穿透:查询数据库不存在的对象,也就不存在缓存层的命中;
- 缓存击穿:热点key在失效的瞬间,高并发查询这个key,击穿缓存,直接请求数据库;
- 缓存雪崩:缓存Key大批量到过期时间,导致数据库压力过大;
- 命中率:缓存设计的是否合理要看命中率,命中率高说明缓存有效抗住了大部分请求,命中率可以通过redis监控信息计算,一般来说命中率在(70-80)%都算合理 。并发问题
在遵守缓存使用原则下出现该情况概率非常低,可以通过复杂的Paxos协议保证一致性,一般情况是不考量该场景的处理,如果缓存管理过于复杂,会和缓存层核心理念相悖 。
基本描述代码:
@Servicepublic class KeyValueServiceImpl extends ServiceImpl<KeyValueMApper, KeyValueEntity> implements KeyValueService {@Resourceprivate RedisService redisService ;@Overridepublic KeyValueEntity select(Integer id) {// 查询缓存String redisKey = RedisKeyUtil.getObectKey(id) ;String value = https://www.isolves.com/it/cxkf/jiagou/2020-10-21/redisService.get(redisKey) ;if (!StringUtils.isEmpty(value) && !value.equals("null")){return JSON.parseobject(value,KeyValueEntity.class);}// 查询库KeyValueEntity keyValueEntity = this.getById(id) ;if (keyValueEntity != null){// 缓存写入redisService.set(redisKey,JSON.toJSONString(keyValueEntity)) ;}// 返回值return keyValueEntity ;}@Overridepublic boolean update(KeyValueEntity keyValueEntity) {// 更新数据boolean updateFlag = this.updateById(keyValueEntity) ;// 清除缓存if (updateFlag){redisService.delete(RedisKeyUtil.getObectKey(keyValueEntity.getId()));}return updateFlag ;}}
Read-Throug模式当应用系统向缓存系统请求数据时,如果缓存中并没有对应的数据存在,缓存系统将向底层数据源的读取数据 。如果数据在缓存中存在,则直接返回缓存中存在的数据 。把更新数据库的操作由缓存层代劳了 。
Write-Through模式
更新写数据时,如果没有命中缓存,则直接更新数据库,如果命中了缓存,则先更新缓存,然后由缓存系统自行更新数据库 。
Write-Behind模式
应用系统对缓存中的数据进行更新时,只更新缓存,不更新数据库,缓存系统会异步批量向底层数据源更新数据 。
二、数据一致问题业务开发模式中,会涉及到一个问题:如何最大限度保证数据库和Redis缓存的数据一致性?
首先说明一下:数据库和缓存强一致性同步成本太高,如果追求强一致,缓存层存在的价值就会很低,如上缓存模式一中几乎可以解决大部分业务场景问题 。
解决这个问题的方式很多:
文章插图
方案一说明:
- 数据库更新写入数据成功;
- 准备一个先进先出模式的消息队列;
- 把更新的数据包装为一个消息放入队列;
- 基于消息消费服务更新Redis缓存;
推荐阅读
- 「go-zero」 防止缓存击穿之进程内共享调用
- 250个点位的监控工程,后端合适选什么设备?
- 网上搜索会被监控吗?
- 监控工具之Cacti,搭建和使用
- 缓存只会用!缓存架构没听过?分布式多级缓存大瓶装,你拎包带走
- 运维小工具:Mysql库TPS,QPS实时监控脚本
- Windows 10默认已禁用USB驱动器缓存 1903版本起无需点击安全弹出
- 交换机性能、网络带宽对监控画面有哪些影响?
- Java性能调优:JVM性能监控常用方法
- Windows 10默认已禁用USB驱动器缓存:不用手动“弹出”