前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >缓存世界中的三大问题及解决方案

缓存世界中的三大问题及解决方案

作者头像
数据和云
发布2019-08-27 16:35:41
5590
发布2019-08-27 16:35:41
举报
文章被收录于专栏:数据和云数据和云

Redis 经常用于系统中的缓存,可以极大地提高了系统性能和效率,但同时也带来一些问题。一个是数据一致性问题。从严格意义上讲,只要使用缓存,就会出现一致性问题,这是无法解决的。另一个问题是本文将讨论的缓存穿透,缓存击穿和缓存雪崩,这三个问题不仅限于 Redis,其他缓存工具同样需要面对这三个问题。接下来我详细讲解这三个问题以及对应的解决方案。

一、缓存穿透


缓存穿透意味着当用户查询数据库不存在数据时,返回的结果为空,并且结果不会在缓存中存储。假设用户不断发起这样的请求,它将永远不会访问缓存,导致所有查询都落在数据库上,从而导致数据库被打死。

代码语言:javascript
复制
public Object getGoods(Long goodsId) {

    //从 Redis 获取 goods 信息
    Object goodsInfo = redisTemplate.opsForValue()
                .get(String.valueOf(goodsId));
        if (goodsInfo != null) { 
            return goodsInfo;
        }

    //从数据库查询 goods 信息,并存入 Redis
    goodsInfo = goodsDao.selectByGoodsId(goodsId);
        if (goodsInfo != null) { 
        redisTemplate.opsForValue()
                .set(String.valueOf(goodsId), goodsInfo);
        }
    return goodsInfo;
}

假设 goodsId 没有负数情况,如果发起一个参数 goodsId = -1 的请求,这个数据在缓存中肯定不会存在,每次它都会进入查询数据库,并且数据查询结果也是 null,并且不会缓存结果到 Redis。

解:

1) 通过用户认证、参数验证等,在上层拦截这些不合理的请求;

2) 当数据库查询结果为空时,数据也被缓存,但缓存有效期设置较短,以免影响正常数据的缓存。

代码语言:javascript
复制
public Object getGoods(Long goodsId) {

    //从 Redis 获取 goods 信息
    Object goodsInfo = redisTemplate.opsForValue()
            .get(String.valueOf(goodsId));
    if (goodsInfo != null) { 
        return goodsInfo;
    }

    //从数据库查询 goods 信息,并存入 Redis
    goodsInfo = goodsDao.selectByGoodsId(goodsId);
         if (goodsInfo != null) { 
            redisTemplate.opsForValue()
                .set(String.valueOf(goodsId), goodsInfo
                    , , TimeUnit.MINUTES);
         } else { //查询为 null 同样存储
            redisTemplate.opsForValue()
                .set(String.valueOf(goodsId), null, , 
                    TimeUnit.SECONDS);
    }
    return goodsInfo;
}

二、缓存击穿


缓存击穿意味着当热点数据存储到期时,多个线程同时请求热点数据。因为缓存刚过期,所有并发请求都会到数据库查询数据。

解:

实际上,在大多数实际业务场景中,缓存击穿是实时发生的,但不会对数据库造成太大压力,因为一般的公司业务,并发量不会那么高。当然如果你不幸有这种情况,你可以通过设置这些热点键,使其永远不会过期。另一种方法是通过互斥锁来控制查询数据库的线程访问,但这种会导致系统的吞吐率下降,需要实际情况使用。

三、缓存雪崩


数据未加载到缓存中,或者缓存同时在大范围中失效,导致所有请求查找数据库,导致数据库、CPU 和内存过载,甚至停机。

一个简单的雪崩过程:

1) Redis 集群的大面积故障;

2) 缓存失败,但仍有大量请求访问缓存服务 Redis;

3) 在大量 Redis 请求失败后,请求转向数据库;

4) 数据库请求急剧增加,导致数据库被打死;

5) 由于你应用程序服务大部分都依赖于数据库和 Redis 服务,它很快就会导致服务器集群的雪崩,最后整个系统将彻底崩溃。

解:

事前:高可用的缓存

高可用的缓存是防止出现整个缓存故障。即使个别节点,机器甚甚至机房都关闭,系统仍然可以提供服务,Redis 哨兵(Sentinel) 和 Redis 集群(Cluster) 都可以做到高可用。

事中:缓存降级(临时支持)

当访问次数急剧增加导致服务出现问题时,我们如何确保服务仍然可用。在国内使用比较多的是 Hystrix,它通过熔断、降级、限流三个手段来降低雪崩发生后的损失。只要确保数据库不死,系统总可以响应请求,每年的春节 12306 我们不都是这么过来的吗?只要还可以响应起码还有抢到票的机会。

事后:Redis 备份和快速预热

1) Redis 数据备份和恢复

2) 快速缓存预热

四、小结


目前的大部分的系统都增加了缓存机制,避免对数据库造成过大压力导致系统出问题,极大的提升系统稳定性。虽然使用缓存能够给系统带来了一定的质的提升,但同时也带来缓存穿透、缓存击穿、缓存雪崩问题等问题。特别是当并发量增大、恶意攻击的时候,是很难避免。这些问题应该在设计系统时候就应该考虑,这样设计出来的系统才经得起考验。

扩展阅读


  1. 甲骨文因超过90亿美元的NetSuite交易起诉Larry Ellison和CEO Safra Catz
  2. MySQL入门全套
  3. Oracle 12c因bug导致ORA-04031问题处理过程 | 云和恩墨技术通讯精选
  4. 一名33岁运维工程师的自述,如何度过中年危机
  5. 不会SQL注入,连漫画都看不懂了
  6. 史上最全近百条Oracle DBA日常维护SQL脚本指令

数据和云

ID:OraNews

如有收获,请划至底部,点击“在看”,谢谢!

资源下载

关注公众号:数据和云(OraNews)回复关键字获取

help,30万+下载的完整菜单栏

2019DTCC,数据库大会PPT

2018DTCC , 数据库大会PPT

2018DTC,2018 DTC 大会 PPT

ENMOBK,《Oracle性能优化与诊断案例》

DBALIFE,“DBA 的一天”海报

DBA04,DBA 手记4 电子书

122ARCH,Oracle 12.2体系结构图

2018OOW,Oracle OpenWorld 资料

产品推荐

云和恩墨Bethune Pro2 企业版,集监控、巡检、安全于一身,你的专属数据库实时监控和智能巡检平台,漂亮的不像实力派,你值得拥有!

云和恩墨zData一体机现已发布超融合版本和精简版,支持各种简化场景部署,零数据丢失备份一体机ZDBM也已发布,欢迎关注。

云和恩墨大讲堂 | 一个分享交流的地方

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-08-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 数据和云 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 Redis
腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档