邯郸做网站哪家好,wordpress文件上传管理,网站建设需要什么硬件和软件,北京搜索引擎推广服务《服务器开发技术、方法与实用解决方案》
一、缓存预热
在系统刚启动或活动刚开始时#xff0c;如果缓存中没有数据#xff0c;那么大量请求将直接访问数据库。如果瞬时访问流量巨大#xff0c;则可能导致数据库因过载而宕机#xff0c;甚至引发系统雪崩。因此需要将缓存…《服务器开发技术、方法与实用解决方案》
一、缓存预热
在系统刚启动或活动刚开始时如果缓存中没有数据那么大量请求将直接访问数据库。如果瞬时访问流量巨大则可能导致数据库因过载而宕机甚至引发系统雪崩。因此需要将缓存的数据加载到缓存系统中以减轻数据库的压力
1. 应用启动预热策略
本地缓存在应用启动时进行缓存预热。如在Spring中实现InitializingBean接口中的afterProperitesSet方法实现
但是该策略仅适合预热本地缓存且与应用深度耦合
2.任务调度预热策略
如果预热场景涉及的数据规模非常大可以采用任务调度预热
使用分布式任务调度中间件定时、周期触发缓存预热数据。常用的中间件有阿里的SchedulerX、蚂蚁的AntScheduler、XXL-JOB、ElasticJob
分布式任务调度中间件的基本架构
Scheduler Console控制台。可视化集中管理平台Scheduler Server服务端负责客户端任务的调度触发、任务执行状态的监测、集群间任务分配等Scheduler Client客户端多个负责具体任务执行
预热步骤
数据分片将需要处理的数据按照一定规则划分为若干份数据加载根据客户端业务服务器的数量、机房属性等将分片单元拆分为若干份指派到多台客户端业务服务器中数据处理客户端根据任务调度中间件下发的业务参数id访问数据库并将读取的商品数据写入分布式缓存
周期调度数据规模巨大时无法通过一次调度完成缓存预热可以采用周期调度指定每个调度周期预热的数据量。为了避免在数据加载环节重复服务数据需要对已预热过的数据打标如更新预热时间、预热版本号等。在加载数据时通过标记来识别、加载数据
3. 模拟请求预热策略
任务调度预热和应用启动预热都需要定制开发对业务应用有入侵。
可以采用模拟请求预热通过模拟用户请求来实现数据预热如模拟调用数据查询接口。该方式对业务应用的侵入非常小
4. 缓存预热思路
分析业务场景和用户行为来圈定需要预热的数据范围根据待预热数据的特定设计合适的预热策略根据业务需要为不同的预热策略编排执行时间
二、缓存淘汰
缓存大多是基于内存实现的空间相对有限。为了高效利用存储空间当缓存触及设定的空间上限时通常需要借助淘汰算法将部分数据移除
1. LRU
LRU最近最少使用算法根据数据的历史访问记录优先淘汰最近未被使用的数据核心思想为如果数据最近被访问过那么将来被访问的频率会更高。
实现一般采用Hash表双向链表将被访问的数据放到链表头部淘汰链表尾部的数据
LRU算法简单、高效但是一些偶发性、周期性的批量操作会导致LRU算法的缓存命中率急剧下降。如一次性读取大量数据块这些数据块会占用大量空间并淘汰最近最少使用的数据。但是这些数据并非是经常被访问的数据从而导致缓存命中率低下
2. LFU
LFU最近最不常用算法根据数据的历史访问频次来淘汰数据核心思想为如果数据最近被使用的频率高则将来大概率会被再次使用
LRU倾向于保留最近使用的数据LFU倾向于保留使用频率较高的数据。LFU能避免偶发性情况对命中率的影响但是一旦访问内容发生较大变化LFU需要更长的时间来适应因为历史的频次记录会使已无用的数据保留较长一段时间
3. ARC
ARC自适应缓存替换算法兼具LRU和LFU的优点既可以根据时间进行优化缓存最近使用的数据又可以根据频率进行优化同时还能根据负载来灵活调整缓存策略。ARC的命中率要显著优于LRU和LFU。
实现原理见P218
三、缓存更新
1. Cache Aside
读场景先读缓存、若缓存命中则从缓存取数据直接返回若缓存未命中则从数据库读取数据成功后将数据放到缓存中写场景先更新数据库再失效缓存 是否可以先更新缓存再更新数据库 一旦出现缓存成功而更新数据库失败的情况会导致缓存错误值导致业务上无法接受的一致性问题是否可以先失效缓存再更新数据库 通常数据库的写操作耗时大于读操作一旦更新数据库期间有读请求并未命中缓存会导致写回的数据为脏数据为什么是失效缓存而不是更新缓存 如A、B两个线程都执行写操作A线程早于B执行B数据是最新的但A线程晚于B线程更新缓存这样就会导致缓存中的数据是A线程更新的旧值而不是B线程更新的最新值先更新数据库再失效缓存是否存在问题 可能存在更新数据成功失效缓存失败导致缓存脏数据的问题。这种场景最常用的解决方案是为缓存设置失效时间到期自动失效 事实上保证缓存和数据库的强一致性是非常困难的一般须通过Paxos或2PC来保证一致性但这些协议耗时或实现复杂实用性不高。在大多数使用缓存场景中通常有一个重要前提可接受弱一致性
2. Read/Write Through 模式
Read/Write Through 模式将更新数据库的操作交由缓存代理从应用的角度看缓存是主存储应用层的读写操作均面向缓存缓存服务代理对数据库的读写
Read Through若缓存未命中则由缓存服务负责加载数据写入缓存Write Through数据更新时若没有命中缓存则直接更新数据库如命中缓存则更新缓存由缓存服务更新数据库同步更新
3. Write Behind Caching
Read/Write Through 模式同步更新数据库和缓存而Write Behind Caching只更新缓存缓存会异步批量更新数据库类似Linux的Writeback机制
但是该机制无法保证数据强一致性且可能会丢失数据没有完美的机制
四、缓存雪崩
缓存雪崩是指缓存因为某些原因如大量key集中过期、服务器宕机等导致大量查询请求到达服务端数据库造成数据库压力骤增、甚至宕机、进而引起整个系统崩溃的现象
1. 缓存常驻策略
为缓存设置较长的有效期保证缓存在业务高峰期一定不会过期
2. 多级缓存策略
本地缓存作为一级缓存分布式缓存作为二级缓存。多级缓存相结合可以有效分担查询请求压力防止雪崩
3. 过期时间优化策略
为缓存有效期增加随机值防止集中失效将热点Key有效期设置为永久有效内存到达限定值时依旧会淘汰逻辑过期与异步更新为每个Key维护一个逻辑过期时间当逻辑过期时间小于当前时间时说明当前缓存逻辑已经失效需要进行更新。如Redis中设置Key的过期时间为60minValue中设置逻辑过期时间为30min。若命中缓存时发现已到达30min逻辑过期时间则在返回数据的同时异步更新这个Key的缓存
4. 加锁重建策略
如果以上策略均失效在高并发场景下大量Key依旧集中过期或热点Key过期则需要控制通过查询数据库重建缓存的请求量常用策略是加锁和限流
若缓存为命中则对Key加锁只有获得锁的线程才能访问数据库并加载数据重建缓存最后释放锁。未获得锁的线程直接返回空结果或休眠一段时间后重试
缺点是不能保证系统的吞吐量有损用户体验
五、缓存穿透
缓存穿透是指查询一条缓存和数据库都不存在的数据会导致查询这条数据的请求会穿透缓存直接查询数据库最后返回空。如果用户发起大量请求去查询这条根本不存在的数据则会对数据库造成极大压力
1. 缓存空值策略
未不存在的Key缓存一个空值对于之后的请求会命中缓存中的空值直接返回空数据减少对数据库的访问。
缺点
浪费空间需要缓存空值防御能力若若攻击者构建不重复的请求该策略就会被攻破失去防御能力
2. 布隆过滤器
布隆过滤器可以在不查询数据库的情况下准确地判断数据是否一定不存在从而过滤请求
布隆过滤器由一个固定大小的二进制向量或位图和一系列映射函数组成。元素被加入到布隆过滤器中时该元素经k个哈希函数生成k个哈希值然后将位图对应的k个点置为1。 如果需要判断某个元素是否在布隆过滤器中只需对给定元素进行相同的哈希计算得到k个哈希值如果有任何一个点为0则说明这个元素一定不在布隆过滤器中
提前将真实存在的数据的Key如商品Id添加到布隆过滤器中用户查询时若不存在则直接返回若存在继续查询缓存缓存未命中则进一步查询数据库
实现方案
Guava适用于单机环境RedisRedis中的Bitmaps数据结构可以实现布隆过滤器RedisBloom开源的Redis插件可提供布隆过滤器、布谷鸟过滤器、TopK等功能
缺陷
由于哈希碰撞存在误判无法判断是否一定存在不支持删除元素因为布隆过滤器每一个Bit位不是独占的若直接删除可能会影响其他元素
3. 布谷鸟过滤器
布谷鸟过滤器支持删除元素但是存在误删的概率且插入操作的复杂度高且会随着插入元素的增加而增加
六、缓存热点
当大量用户集中访问热点数据时压力将汇聚于单一缓存服务器实例可能导致热点数据所在的服务器过载缓存服务不可用
1. 前置缓存策略
将热点数据提前缓存在应用服务器的本地内存中对于数据查询请求首先查询本地缓存命中则直接返回
缺陷
无法防御未知热点对于难以预见的突发热点无效数据更新存在延迟。本地缓存可能会存在短时数据不一致
2. 热点散列策略
多副本策略将热点数据复制多份分别缓存在多台缓存服务器上减轻缓存热点导致的单台缓存服务器压力
实践中散列数量一般与分布式缓存集群的服务器数量相等。
实现方案如Redis Cluster