04-三高项目-缓存设计
三高项目-缓存设计
分流、并发
导流:将原本复杂操作的请求,引导到简单的操作上。以后再来查,不需要经过复杂的计算。
成本:空间,收益:节省了时间。
不要以为仅仅是 redis,map等。
对应。kv值。
1计算k,2 查询k,3 得到值,做转换。
如果能做好对应,最好,做不好对应呢? 命中率。没有命中的缓存,查原数据。
数据的查询时间:时间(123)+(1-命中率p)*查原数据的时间。
命中率=缓存中能查到的数据/数据库总数据
如何 提升缓存的收益:
减少 123时间。
提高命中率(*)。
应用场景:
读多写少用缓存。
查询原数据时间特别长的场景。
Key
键K有关
生成时间
不同功能业务的,key值要不一样,否则会被覆盖。
要唯一,避免碰撞。
单向函数:hash。给定输入的情况下,很容易计算出结果,而给定结果的情况下,几乎不可能计算出输入值。
一般不存在。正向快速,逆向困难,输入敏感,冲突避免。
md4 , md5,sha-0,sha-1,sha-2(用)
查询时间
缓存的位置。内存,硬盘,本地。
数据结构。
1234567890
234567890-
equals,hashcode。
键总结
无碰撞(唯一),高效生成(不需要,约定好),高效比较。
系统标识+功能标识+业务标识+前后缀。
13910712345+vcode: 123456
公司统一标准。
值
序列化值(二进制),对象值。
数据污染:
0-0.5-1 1-2 存的不是最终值
缓存只是 在 调用方和 数据提供方之间的一个 暂存方。
统一:缓存中数据怎么来的,查询的时候,如果没有,就从数据提供方获取,然后放到缓存中。
缓存的更新机制
时效性更新机制
固定时间过期,被动更新
:缓存中的数据设置一个过期时间。如果缓存数据过期,那么,我会去提供方查询,这样就相当于将 提供方 的数据 更新到缓存中了。
放弃了:实时一致性。(商品关注人数,评论数,浏览量,评论点赞收藏)
读,
写:只写数据提供方。不理会缓存。
主动更新机制
清风:cap。
cache aside
写:先更新,更新数据提供方,删除缓存。
概率很低:
1。 读的时候,缓存里 没有数据。
2。 读的时候,有写在同时进行。
3。读的时长大于 写操作。(不那么容易发生 1%)。
4。 读写操作 同时发生时,读到的是旧值。50%。
可以用。鸵鸟算法。
在计算机科学中,鸵鸟算法 是一个忽略潜在问题的一种算法策略,这种策略对计算机程序可能出现的问题采取无视态度(类似于鸵鸟在遇到危险时将头埋在地里,装作看不见)。鸵鸟算法的使用前提是,问题出现的概率很低。
三高项目-缓存
双写一致性
先删除缓存,再更新数据提供方。 延迟双删。
1。更新缓存,更新数据库。更容易造成数据的不一致,缓存成功,数据提供方失败。更糟糕。
2。更新数据库,更新缓存。有缺点,一点点稍微可取。
缺点:A 更新了数据库。B更新了数据库,B更新了缓存,A更新了缓存。
空干活,经过复杂的计算,给缓存设置值,但是用的少,浪费了资源。
3。删除缓存,更新数据库。延迟双删
4。更新数据库,删掉缓存。上节课所说的额cache aside。
延迟双删:删除缓存,更新数据提供方,睡眠一段时间(根据实际业务),再删除缓存。
如果第二次 删除失败了,怎么办? 重试一下。
自己写重试代码,没问题。自己挂了呢?
转移风险。重试的组件? 消息队列。
上面所说的,不管方案多么复杂,完善,总不能保证一致性。
Read/Write Through
直接 将 结果写入缓存。再从缓存 同步到数据提供方。调用方只需要和缓存交互。
写成功标识:缓存成功,数据提供方成功。TCC。
初始化:1。 启动缓存,从数据提供方,初始化。2。读取缓存 ,初始化。
缓存预热。命中率低,慢慢的命中率才高。
保障:缓存 非常 可靠。
Write Behind
在上面 做了升级,异步写入到数据提供方。加入消息队列,保证最终一致性。
缓存空间足够大,能缓存所有的数据,命中率 100%。
清理机制
以提高缓存命中率为目标。
过去访问多的,未来访问也多。
最近被更新的,未来访问的多。
时效性清理
过期全部清理。要求缓存中的数据都有一个生存期,有效期。
1条数据:data,ttl。2min。
轮询时效清理:额外开启一个程序,定期扫描所有数据的有效期,到期了,干掉。
自动时效清理:cookie。本质:上面的 轮询。
数目阈值清理
1 条数,2 每条的大小。
FIFO: 队列大小是10,
LRU:左神算法。数据访问次数,头部,删尾部。
LinkedHashMap 都可以实现 fifo,lru。
如果空间充足,则缓存多多的,提高命中率。如果空间不够,再回收空间,把空间给其他人让出来。
垃圾回收。
强引用:只要被强引用,就不会被回收。内存不足时,哪怕自己挂掉,也不回收。
软引用:空间不足时,才会被回收。
弱引用,虚引用。
SoftReference。 java实现它。
用java实现一个 根据内存空间大小的使用情况,做一个缓存组件。
Map <k,SoftReference<>>。
实战:
时效性清理+数据阈值式= 1。过期就干掉。2,密集查询,导致空间急剧增大。
LRU+软引用:保证最近用的数据在,然后最近不用的,放到软引用里,用软引用包装一下。
不建议:只用软引用。缓存的存活与否,从业务逃脱。业务控制不了。
三高项目
缓存风险点
每增加一个环节,就多一个风险。
缓存穿透
缓存没有数据,数据提供方也没有数据,穿透了。
无效的调用,增加数据提供方的压力,缓存基本无效。
解决方案:在缓存中,缓存一份 空数据。key有值,value为空。
缓存雪崩
大量缓存突然失效,引发的数据提供方压力 骤增。
数据阈值式清理:(缓存是逐个失效的)阈值比较低的时候会。10个缓存。阈值高,可以缓解。
时效式清理:会造成雪崩。避免缓存在同一时刻失效。过期时间=固定值+随机值。错峰失效。
软引用清理:当空间紧张的时候,缓存占据的空间会被回收。单纯的软引用无法解决。lru:对经常访问的数据建立强引用。
缓存击穿
有数据提供方 兜底,不叫穿透。
lru:高频访问的数据,大概率在前面 fifo。
read/write through, write behind。更新机制。缓存里有没有?因为数据的写、更新,先操作的是缓存。
cache aside: 有一个节点,缓存被删除。可能有击穿。
实际工作:
清理机制+更新机制,针对缓存,共同考虑。
缓存预热
启动系统的时候,提前加载一些数据。预加载。
缓存服务启动后,脚步直接灌入。init
时效式清理机制:缓存重复预热。
缓存的位置
需要缓存的数据,一定要靠前。。要想系统性能好,缓存一定要趁早。
前置模块:减少和后端通信的成本。
后置模块:公共模块,尽量用这个方式。
客户端缓存
客户端:浏览器,c软件,安卓,ios,h5,小程序。
浏览器:cookie,过期时间。轻量级的缓存。
F12 application。h5支持 & 浏览器的支持。
sqlite :安卓端的一个数据库。规则类。开机图片,引导页。
cdn 静态缓存
静态资源:页面,图片。
数据:重点:地名,字典,行业分类,统计局 那些标准化的数据。三级联动。算。广义:与用户个体无关的具有通用性的数据,都可以作为静态数据。
数据:用户不同,参数不同,时间不同,----结果不同。 对系统性能造成负面影响。
服务端缓存
redis。localcache,guava。
数据库缓存
冗余字段,中间表
操作完业务,需要做统计,非实时的数据,让它后置。
新增订单:
insert order (xxxxxx), 统计表 (订单数据 + 1) 10s。
5s, 定时任务扫描(48h-24h) +10。
冗余字段:
订单表(商品的数据)快照。
三高项目
写缓存
读缓存。调用方 数据提供方。
写缓存:调用方和 数据 处理方之间。目的:减少巨量调用操作对数据处理方的冲击。库存。削峰。
消息队列。
写缓存收益:原始时间 <(写缓存时间+缓存中数据向后传递的时间+原始时间)
收益在于用户的角度:目标用户的响应时间 降低了。
读缓存:是以缓存命中的数据 替代 数据提供方的操作。
写缓存:通过增加额外花费的时间,来延迟数据处理方的工作。
写缓存实践:redis(发布订阅),消息队列(发布订阅),数据库(先生成数据,后期再进行统计,耗时的&对实时性要求不高的,后置)
适合场景:请求峰谷值变化明显&对实时性要求不高的系统中。
抢购系统,竞品系统,秒杀系统,抢红包系统。
消息推送系统:极光,百度。
实时性不高。
大厂:
需求:平峰(请求量在某个阈值之下):正常处理。峰值超过阈值的时候,触发写缓存。
降级:微服务降级组件处理可以。
灰度发布。配置灰度规则(规则中 请求的阈值,根据阈值的不同,调用不同的系统)。
限流。要对流量进行 评估。
面试:写的访问量增大,怎么处理。
下单:订阅消息,不重要的系统订阅关键 业务的数据。