厉害了,如何通过双 key 来解决缓存并发问题?
云栖号资讯:【点击查看更多行业资讯】
在这里您可以找到不同行业的第一手的上云资讯,还在等什么,快来!
我们在使用缓存的时候,不管Redis或者是Memcached,基本上都会遇到以下3个问题:缓存穿透、缓存并发、缓存集中失效。这篇文章主要针对【缓存并发】问题展开讨论,并给出具体的解决方案。
1.什么是缓存并发?
在高并发的访问下,当某个缓存处于过期失效的时间点时,极有可能出现多个进程同时查询该缓存(该缓存是业务场景中非常 "热点" 的数据,比如首页的缓存数据)。因为查询DB并重新缓存需要一定的时间,而瞬时并发非常高,如果此时缓存失效了,这些并发请求都会直接访问DB,从而导致DB服务器的CPU或者内存负载过高,服务能力下降甚至宕机,此问题即缓存并发问题。
缓存并发问题在微服务架构下凸显更加严重,比如某个基础服务A因为上述问题出现不可用,进而导致依赖A服务的B、C服务也不可用,而B服务的不可用又导致服务E、F不可用,不可用的服务就像滚雪球一样越滚越大,最终导致系统出现严重故障,此现象我们称之为雪崩效应。
注意缓存并发和缓存集中失效的区别在于:缓存并发指的是某一个热点key的失效,而缓存集中失效则是一批key同时失效,两者都可能导致雪崩问题。
2.如何解决?
针对该问题,存在以下三种解决方案:
1.加锁:在缓存失效后,通过加锁的方式只允许一个线程查询数据和写缓存,其他线程如果发现有锁就等待,等解锁后再返回数据。该方案会造成部分请求等待。
2.二级缓存:A1为原始缓存,A2为拷贝缓存。A1失效时,可以访问A2,其中A1的缓存失效时间设置为短期(比如5min),A2的缓存失效时间设置为长期(比如1天)。如果缓存value很大,此方案的缓存空间利用率低。关注公众号互联网架构师,回复关键字2T,获取最新架构视频
3.双key:思路和方案2类似,不同的是双key分别缓存过期时间(key-time)和缓存数据(key-data),其中(key-time)的缓存失效时间设置为短期(比如5min),(key-data)的缓存失效时间设置为长期(比如1天)。当第一个线程发现 key-time 过期不存在时,则先更新key-time,然后去查询数据库并更新key-data 的值;当其他线程来获取数据时,虽然第一个线程还没有从数据库查询完毕并更新缓存,但发现key-time存在,会直接读取缓存的旧数据返回。和二级缓存的方案对比,该方案的缓存空间利用率高。
3.双key方案的示例代码
- 写缓存的示例代码
1public static boolean set(String key, String value, int seconds) { 2 Jedis jedis = null; 3 try { 4 jedis = jedisPool.getResource(); 5 if (seconds > 0){ 6 // 添加数据缓存,缓存有效时间 = 真实时间 + 1 天 7 jedis.set(key, seconds + 60 * 60 * 24, value); 8 9 // 添加过期时间缓存,缓存有效时间 = 真实时间 10 jedis.set("lock_" + key, seconds, System.currentTimeMillis() + ""); 11 } else { 12 jedis.set(key, value); 13 jedis.set("lock_" + key, System.currentTimeMillis() + ""); 14 } 15 16 return true; 17 } catch (JedisException e) { 18 if (jedis != null) { 19 returnBrokenResource(jedis); 20 jedis = null; 21 } 22 throw e; 23 } finally { 24 if (jedis != null) { 25 returnResource(jedis); 26 } 27 } 28}
2. 读缓存的示例代码
1public static String get(String key) { 2 Jedis jedis = null; 3 try { 4 jedis = jedisPool.getResource(); 5 6 // 缓存过期 && 获取锁成功,setnx:原子操作 7 if (jedis.setnx("lock_" + key, System.currentTimeMillis() + "") == 1) { 8 /** 9 * 将锁的失效时间设为60s,在60s内若查询数据库成功,则更新锁的失效时间=缓存时间 10 * 如果60s内出现异常,则60s后第一个请求又会去访问数据库 11 * 返回null表示没有查询到数据库,外层代码会通过数据库获取数据并设置缓存 12 */ 13 jedis.expire("lock_" + key, 60); 14 return null; 15 } else{ 16 // 缓存未过期或者缓存过期但获取锁失败, 则返回旧数据 17 return jedis.get(key); 18 } 19 } catch (JedisException e) { 20 if (jedis != null) { 21 returnBrokenResource(jedis); 22 jedis = null; 23 } 24 throw e; 25 } finally { 26 if (jedis != null) { 27 returnResource(jedis); 28 } 29 } 30}
【云栖号在线课堂】每天都有产品技术专家分享!
课程地址:https://yqh.aliyun.com/zhibo立即加入社群,与专家面对面,及时了解课程最新动态!
【云栖号在线课堂 社群】https://c.tb.cn/F3.Z8gvnK
原文发布时间:2020-07-17
本文作者:互联网架构师
本文来自:“互联网架构师”,了解相关信息可以关注“互联网架构师”
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
阿里人脸识别安全技术获专利 可防范3D人脸面具攻击
云栖号资讯:【点击查看更多行业资讯】在这里您可以找到不同行业的第一手的上云资讯,还在等什么,快来! 当人脸识别遇上3D技术,谁将是最后的胜利者?长期困扰人脸识别行业的安全问题有了最新的解法。日前,阿里安全推出的人脸识别安全技术方案获得美国专利局授权。根据这个新的专利方案,只需要通过光影和手机位置变化,就可以有效防范此前技术上难以解决的3D人脸面具等攻击。 图片说明:阿里安全获得美国专利局人脸识别新技术专利授权通知 随着智能手机的广泛应用,远程开户、开卡等网上身份认证、验证服务也越来越普及。通过人脸识别技术,人们足不出户就可核验身份,大大降低了现场核验的时间成本,但也面临被不法分子攻击的威胁。 为了防止系统被不法分子用照片、视频和3D软件等方式欺骗,目前安全行业普遍采用的活体检测方案主要有两类。一种是基于特殊的硬件装置,比如用双目镜头和深度相机等设备对物体进行3D检测。这种方法通常可以防范照片、视频等攻击方法,但受限于设备,智能手机无法使用这种检测方法。 另一种是对指定动作的识别,比如通过点头、摇头、眨眼、张嘴等动作进行验证。这种方法可以在智能手机中使用,但如果攻击者在视频中录好所有的验...
- 下一篇
走出PPT,智能制造如何真正落地?
自18世纪第一次工业革命以来,工业已经走过机械化、 电气自动化、数字化三个阶段。如今,几乎所有日常生活方式背后都离不开工业的力量。 不过,在“效率就是生命”的现代语境里,留给工业的提升空间还很多,世界各国也都发布过工业转型计划,且思路大同小异:依托物联网、大数据等新兴技术,提升制造业的智能化、效率和互联互通。 具体到中国的情况,随着人口老龄化、劳动力成本提升,仅靠人口红利实现高速增长的日子一去不复返,国内制造业需要找到新的引擎,产业升级迫切。 挑战与机遇并存,产业升级意味着存在可观的市场空间,嗅到机遇的资本和创业公司早已有所布局,联想创投及其被投企业便是典型代表。 传统制造业升级迫切 用一句话概括传统制造业的痛点便是:成本高但效率较低。 而成本和效率之间的问题一般表现为:产能过剩、生产灵活性不足、运维成本过高等。 产能过剩是国内老生常谈的话题,根据国际通用的标准,工业产能利用率低于79%即为“产能过剩”,但从国家统计局公布的数据来看,我国工业产业利用率一直处于79%以下。在以制造业著称的德国,该项数值在高峰期曾接近90%。 图源:国家统计局 生产灵活性和运维成本则不难理解——得益于第二...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Docker安装Oracle12C,快速搭建Oracle学习环境
- CentOS8编译安装MySQL8.0.19
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS6,CentOS7官方镜像安装Oracle11G
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- CentOS8安装Docker,最新的服务器搭配容器使用
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- 设置Eclipse缩进为4个空格,增强代码规范