分布式之缓存击穿.docxVIP

  1. 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
  2. 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  3. 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
  4. 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
  5. 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们
  6. 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
  7. 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
分布式之缓存击穿 在谈论缓存击穿之前,我们先来回忆下从缓存中加载数据的规律,如下图所示 因而,假如黑客每次有意查询一个在缓存内必定不存在的数据,导致每次恳求都要去存储层去查询,这样缓存就得到了意义。假如在大流量下数据库可能挂掉。这就是缓存击穿。 场景如下图所示: 我们正常人在登录首页的时候,都是依据userID来命中数据,然而黑客的目的是破坏你的系统,黑客可以随机生成一堆userID,然后将这些恳求怼到你的服务器上,这些恳求在缓存中不存在,就会穿过缓存,直接怼到数据库上,从而形成数据库连接特别。 处理方案 在这里我们给出三套处理方案,大家依据项目中的实际情况,选择使用. 讲下述三种方案前,我们先回忆下redis的setnx方法 SETNX?key?value 将 key 的值设为 value ,当且仅当 key 不存在。 若给定的 key 已经存在,则?SETNX?不做任何动作。 SETNX 是『SET if Not eXists』(假如不存在,则 SET)的简写。 可用版本:= 1.0.0 时间简单度:?O(1) 前往值:?设置成功,前往 1。设置失败,前往 0 。 效果如下 redis EXISTS job ? ? ? ? ? ? ? ?# job 不存在 (integer) 0 redis SETNX job programmer ? ?# job 设置成功 (integer) 1 redis SETNX job code-farmer ? # 尝试掩盖 job ,失败 (integer) 0 redis GET job ? ? ? ? ? ? ? ? ? # 没有被掩盖 programmer 1、使用互斥锁 该方法是比较普遍的做法,即,在依据key获得的value值为空时,先锁上,再从数据库加载,加载完毕,释放锁。若其他线程发觉猎取锁失败,则睡眠50ms后重试。 至于锁的类型,单机环境用并发包的Lock类型就行,集群环境则使用分布式锁( redis的setnx) 集群环境的redis的代码如下所示: String get(String key) { ? ? String value = redis.get(key); ? ? if (value ?== null) { ? ? ?if (redis.setnx(key_mutex, 1)) { ? ? ? ? ?// 3 min timeout to avoid mutex holder crash ? ? ? ? ?redis.expire(key_mutex, 3 * 60) ? ? ? ? ?value = db.get(key); ? ? ? ? ?redis.set(key, value); ? ? ? ? ?redis.delete(key_mutex); ? ? ?} else { ? ? ? ? ?//其他线程休息50毫秒后重试 ? ? ? ? ?Thread.sleep(50); ? ? ? ? ?get(key); ? ? ?} ? ?} ? } ? 优点: 思路简约 保证全都性 缺点 代码简单度增大 存在死锁的风险 2、异步构建缓存 在这种方案下,构建缓存实行异步策略,会从线程池中取线程来异步构建缓存,从而不会让全部的恳求直接怼到数据库上。该方案redis本人维护一个timeout,当timeout小于System.currentTimeMillis()时,则进行缓存更新,否则直接前往value值。 集群环境的redis代码如下所示: String get(final String key) { ? ? ? ? ?V v = redis.get(key); ? ? ? ? ?String value = v.getValue(); ? ? ? ? ?long timeout = v.getTimeout(); ? ? ? ? ?if (v.timeout = System.currentTimeMillis()) { ? ? ? ? ? ? ?// 异步更新后台特别执行 ? ? ? ? ? ? ?threadPool.execute(new Runnable() { ? ? ? ? ? ? ? ? ?public void run() { ? ? ? ? ? ? ? ? ? ? ?String keyMutex = mutex: + key; ? ? ? ? ? ? ? ? ? ? ?if (redis.setnx(keyMutex, 1)) { ? ? ? ? ? ? ? ? ? ? ? ? ?// 3 min timeout to avoid mutex holder crash ?

文档评论(0)

bob157641554 + 关注
实名认证
文档贡献者

该用户很懒,什么也没介绍

1亿VIP精品文档

相关文档