同步:操作分布式锁住
异步:mq 消息保证、binlog 保证
持久化缓存处理——持久化内存Redis 持久化内存
数据库、本地(还可以通过 hash优化一下)、redis

## 缓存模式
### 基本思路
- **Cache Aside(旁路缓存)**
- 写操作:业务代码写数据库,再写缓存
- 读操作:业务代码读缓存,缓存未命中读数据库
- 一致性问题:先写数据库或先写缓存都有一致性问题
- **Read Through(读穿)**
- 写操作:和Cache Aside一样
- 读操作:业务代码读缓存,缓存会去加载数据
- 缓存可以直接返回错误或者默认值
- 缓存可以加载了数据库之后返回
- 缓存可以加载了数据库数据,并回写缓存之后返回
- 存在一致性问题
- **Write Through(写穿)**
- 写操作:写入到缓存,缓存去更新数据库;读操作:和Cache Aside一样
- 存在一致性问题
- **Write Back(回写/写回)**
- 特点——读写缓存:缓存过期的时候才回写到数据库;存在数据丢失的可能
- 使用场景——不介意少量数据丢失;缓存本身高可用
- 一致性问题
- 回写之前,数据库和缓存数据不一致,但是对于用户来说是一致的
- 用 **SETNX(设置不存在的键)** 回写规避一致性问题
- **Refresh Ahead(提前刷新)**
- 特点——利用 **CDC(变更数据捕获)** 接口监听数据变更;数据变更之后刷新缓存
- 一致性问题
- 在数据库中数据变更之后,到数据被刷新到缓存之前,数据是不一致的
- 缓存未命中时,使用 **SETNX(设置不存在的键)** 来回写缓存
- **Singleflight(单次请求合并)**
- 特点——多个线程或者协程在缓存未命中时去加载数据;同一个key,只有一个允许过去加载数据,其他都在等待
- 适合高并发场景
- 删除缓存
- 特点:更新数据库之后直接删除缓存——可以立刻删除,也可以异步删除
- 降低缓存命中率
- 存在数据一致性问题
- 延迟双删
- 特点:更新数据库之后直接删除缓存;过一段时间后,再次删除缓存
- 降低缓存命中率
- 加重数据库查询负担
### 用装饰器模式实现缓存模式
- 无侵入式;可适配不同缓存实现
### 选用什么模式
- 因地制宜;面试——考虑延迟双删