缓存能够有效加速应用的访问速度,同时可以降低后端负载,在应用架构中起着至关重要的作用,本文主要介绍缓存使用的一些技巧。

缓存更新策略

  • LRU/LFU/FIFO算法剔除

    场景:数据一致性要求较低
    原理:缓存使用量超过了预设值,使用maxmemory-policy来选择何种剔除策略对现有数据进行删除
    问题:数据清理由算法决定,开发人员只能选择使用哪种算法,数据一致性最差
  • 超时剔除

    场景:数据一致性要求低
    原理:给缓存设置过期时间(expire),自动删除
    问题:一段时间窗口内存在一致性问题
  • 主动更新

    场景:数据一致性要求较高
    原理:真实数据更新后,立即更新缓存
    问题:主动更新发生问题,这条数据很长时间不会发生更新

总结:

低一致性业务使用最大内存+淘汰策略
高一致性业务使用超时剔除+主动更新

缓存粒度控制

缓存的粒度在缓存应用时也有着很重要的影响,究竟缓存全部属性还是部分属性?可以从三个维度来进行权衡。

  • 通用性

    缓存全部数据比部分更加通用,但是较多情况下,应用只需要其中几个重要的属性
  • 空间占用

    缓存全部数据占用更多的空间,可能会造成内存的浪费,而且每次传输产生的网络流量较大,极端情况会阻塞网络
  • 代码维护

    部分数据一旦表结构变动,增加新字段则需要修改业务代码,并且需要重新刷新缓存

总结:

缓存粒度问题容易被忽视,但是使用不当,可能造成更多无用空间的浪费、网络带宽的浪费、代码通用型较差等情况,需要综合以上三点进行取舍

缓存穿透优化

缓存穿透指查询一个不存在的数据,导致不存在的数据每次请求都要到存储层查询,使后端存储层负载过大,极端情况可能导致宕掉。

  • 缓存空对象

    原理:缓存不命中,查询存储层,仍然不命中,则将空对象保存至缓存层中,然后再返回
    场景:数据命中率不高,频繁变化实时性高
    问题:1.空值占用更多的键,占用更多的内存空间,如果被攻击,可能导致内存快速增长,利用较短的过期时间来自动剔除;
    2.缓存层和存储层一定时间窗口数据不一致,利用消息系统或者其它方式清楚缓存中空对象。
  • 布隆过滤拦截器

    原理:在缓存层和存储层之间,将存在的key用布隆过滤器提前保存,如果key存在,则不访问存储层,可以通过Bitmaps来实现。
    场景:数据命中率不高、数据相对固定、实时性低(数据集较大)
    问题:代码维护复杂

无底洞优化

业务增长导致需要增加缓存节点来提高性能,但是增加节点后性能不但没有反转反而下降。分布式场景下,一次批量操作需要访问多个Redis节点,需要多次网络访问时间。

  • 串行命令

    原理:n个key均匀分布在Redis Cluster各个节点上,逐次执行n个get命令
    耗时:n次网络时间+n次命令时间
    缺点:大量keys请求延迟
  • 串行IO

    原理: 使用JedisClusterCRC16计算出key的slot,然后找到对应的节点,将属于同一个节点的key进行归档,对每个节点执行mget操作
    耗时:node次网络时间+n次命令时间
    缺点:大量node延迟
  • 并行IO

    原理:对于串行IO中,得出每个节点的key列表,通过多线程来对每个节点进行mget操作
    耗时:max_slow(node网络时间)+n次命令时间
    缺点:变成复杂、多线程问题定位较难
  • hash_tag

    原理:利用Redis Cluster功能,将多个key强制分配到一个节点
    耗时:1次网络时间+n次命令时间
    缺点:业务维护成本高、数据倾斜

雪崩优化

缓存层由于某些原因不可用,所有请求到达存储层,压力暴增,可能导致存储层也会级联宕机。

  • 保证缓存层服务高可用:Redis Sentinel、Redis Cluster
  • 依赖隔离组件为后端限流降级:Hystrix
  • 提前演练:模拟缓存层宕掉,应用以及后端的负载情况和可能出现的问题

热点key重建优化

“缓存+过期时间”的策略绝大部分情况满足加速数据读写、保证数据定期更新的需求,但是也可能出现其它问题,假如某一个key是一个热点key,并发量很大,并且重建缓存遇到复杂SQL、多次IO等不可能短时间完成情况,当缓存失效的瞬间,大量线程重建,造成后端负载过大。

  • 互斥锁(分布式锁)

    原理:只允许一个线程重建缓存,其它线程等待,直接从缓存中获取数据
    实现:使用Redis setnx或者其它方式来实现
    问题:构建缓存过程出现问题或者时间过长,可能存在死锁和线程池阻塞的风险
  • 永远不过期

    原理:为每个value设置逻辑过期时间,当发现超过逻辑过期时间后,使用单独线程重新构建缓存
    问题:不保证一致性问题,代码维护成本和内存成本(每次重建)增加

    参考资料:《Redis开发与运维》

Redis缓存使用技巧的更多相关文章

  1. Redis缓存设计及常见问题

    Redis缓存设计及常见问题 缓存能够有效地加速应用的读写速度,同时也可以降低后端负载,对日常应用的开发至关重要.下面会介绍缓存使 用技巧和设计方案,包含如下内容:缓存的收益和成本分析.缓存更新策略的 ...

  2. redis缓存分页思路

    传统分页一般分页做缓存都是直接查找出来,按页放到缓存里,但是这种缓存方式有很多缺点.如缓存不能及时更新,一旦数据有变化,所有的之前的分页缓存都失效了.比如像微博这样的场景,微博下面现在有一个顶次数的排 ...

  3. Redis缓存策略设计及常见问题

    Redis缓存设计及常见问题 缓存能够有效地加速应用的读写速度,同时也可以降低后端负载,对日常应用的开发至关重要.下面会介绍缓存使用技巧和设计方案,包含如下内容:缓存的收益和成本分析.缓存更新策略的选 ...

  4. 缓存工厂之Redis缓存

    这几天没有按照计划分享技术博文,主要是去医院了,这里一想到在医院经历的种种,我真的有话要说:医院里的医务人员曾经被吹捧为美丽+和蔼+可亲的天使,在经受5天左右相互接触后不得不让感慨:遇见的有些人员在挂 ...

  5. Windows下Redis缓存服务器的使用 .NET StackExchange.Redis Redis Desktop Manager

    Redis缓存服务器是一款key/value数据库,读110000次/s,写81000次/s,因为是内存操作所以速度飞快,常见用法是存用户token.短信验证码等 官网显示Redis本身并没有Wind ...

  6. 总结:如何使用redis缓存加索引处理数据库百万级并发

    前言:事先说明:在实际应用中这种做法设计需要各位读者自己设计,本文只提供一种思想.准备工作:安装后本地数redis服务器,使用mysql数据库,事先插入1000万条数据,可以参考我之前的文章插入数据, ...

  7. .NET基于Redis缓存实现单点登录SSO的解决方案[转]

    一.基本概念 最近公司的多个业务系统要统一整合使用同一个登录,这就是我们耳熟能详的单点登录,现在就NET基于Redis缓存实现单点登录做一个简单的分享. 单点登录(Single Sign On),简称 ...

  8. Redis缓存连接池管理

    import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.util.Assert;import ...

  9. ssm+redis 如何更简洁的利用自定义注解+AOP实现redis缓存

    基于 ssm + maven + redis 使用自定义注解 利用aop基于AspectJ方式 实现redis缓存 如何能更简洁的利用aop实现redis缓存,话不多说,上demo 需求: 数据查询时 ...

随机推荐

  1. Spring Boot学习笔记:整合H2数据库

    H2数据库:java语言编写的嵌入式sql数据库.可以和应用一起打包发布. H2有三种连接模式(Connection Modes): Embedded mode (local connections ...

  2. Hibernate 映射及查询

    实体类和实体之间的关系:一对多,多对多 数据库设计:e_r 一个实体对象就是一个表格,  如果是1对多的关系,将多方的主键拿到1方做外键.  多对多:重新建立一张新的表格,将双方的主键拿到这里做外键 ...

  3. Android开发之Activity

    活动(Activity) 活动是最容易吸引用户的地方,它是一种可以包含用户界面的组件,主要用于和用户交互. FirstActivity 手动创建活动 新建一个project,不再选择empty act ...

  4. InternalResourceViewResolver视图解析器(转)

    转载地址:https://www.cnblogs.com/liruiloveparents/p/5054605.html springmvc在处理器方法中通常返回的是逻辑视图,如何定位到真正的页面,就 ...

  5. 长方体类Java编程题

    1. 编程创建一个Box类(长方体),在Box类中定义三个变量,分别表示长方体的长(length).宽(width)和高(heigth),再定义一个方法void setBox(int l, int w ...

  6. We FALL ASleep At Night, We Do REST Right

    We Do Sleep At Night, We Do REST Right 前言 REST 起源 REST 约束 客户端 - 服务端 无状态 缓存 统一接口 分层系统 按需代码 统一接口约束 资源识 ...

  7. win7安装vs2017时闪退

    最近用公司的笔记本电脑,装win10发现太卡,无奈最终选择安装win7系统,本以为系统安装成功了,接下来只要安装下开发环境:vs2017 sqlserver等就好,结果在安装vs2017的时候,一直出 ...

  8. c++ 日志输出库 spdlog 简介(1)

    参考文章: log库spdlog简介及使用 - 网络资源是无限的 - CSDN博客 http://blog.csdn.net/fengbingchun/article/details/78347105 ...

  9. PHP 生成验证码(+图片没有显示的解决办法)

    今天有需要用到验证码,就敲了个,毕竟用途比较广,所以打算把代码留下来,以后肯定用得上的.当然,今天在做的时候也是有一些问题的,分享出来吧,记录自己所犯的错误,避免以后再掉坑里. 先给个效果图(下面的真 ...

  10. Android开发工程师文集-1 小时学会SQLite

    前言 大家好,给大家带来Android开发工程师文集-1 小时学会SQLite的概述,希望你们喜欢 内容 什么是Sqlite: 效率高,开源,小型,程序驱动,支持事务操作,无数据类型,可嵌入的关系型数 ...