您的位置: 翼速应用 > 业内知识 > 数据库 > 正文

Redis关键点分析

    Redis(Remote Dictionary Server )是一种远程字典服务,它是以ANSI C语言编写的基于日志的开源键值数据库,支持基于内存的或持久性的网络,并提供多种语言的API。  

 

    由于它的快速入门,高执行效率,多种数据结构,对持久性,集群和其他功能的支持,因此许多Internet公司都在使用它。但是,如果使用和操作不当,将导致内存浪费,甚至导致系统宕机。


    要点分析


    2.1 使用正确的数据类型


    在 Redis 5 种数据类型中,string 类型最为常用,也最为简单。但是,能解决问题不代表使用了正确的数据类型。


    例如,将一个用户(name,age,city)信息保存到 Redis 中,下边有三种方案:


    方案1:使用 string 类型,每个属性当作一个 key

Redis关键点分析1.png

    优点:简单直观,每个属性支持更新操作

    缺点:使用过多的 key,占用的内存较大,同时用户信息的聚合性较差,管理和维护麻烦


    方案2:使用 string 类型,将用户信息序列化成字符串保存

Redis关键点分析2.png

    优点:简化存储步骤

    缺点:序列化和反序列化存在一定开销


    方案3:使用 hash 类型,每个属性使用一对 field-value,但只用一个 key

Redis关键点分析3.png

    优点:简单直观,合理使用可以减少内存空间


    总结:尽量减少 Redis 中的 key。


    2.2 警惕 Big Key


    big key 一般指的是字符串类型 value 值非常大(大于10KB),或哈希、列表、集合、有序集合元素个数多(大于5000个)的 key。


    big key 会对 Redis 造成很多负面影响:


    内存不均:在集群环境下,big key 被分配到某个节点机器中,由于不知道被分配到哪个节点上且该节点内存占用大,不利于集群环境下内存的统一管理


    超时阻塞:由于 Redis 是单线程操作,操作 big key 比较耗时,容易造成阻塞


    过期删除:big key 不单读写慢,删除也慢,删除过期 big key 也比较耗时


    迁移困难:由于数据庞大,备份和还原也容易造成阻塞,操作失败


    知道了 big key 的危害,我们如何判断和查询 big key 呢?其实,redis-cli 提供了 --bigkeys 参数,键入 redis-cli --bigkeys 即可查询出 big key 。


    找到 big key 后,我们一般会将 big key 拆分成多个小 key 进行存储。这种做法似乎与 2.1 的总结相矛盾,但任何方案都有优缺点,衡量利弊取决于实际情况。


    总结:尽量减少 Redis 中的 big key。


    补充:如果想查看某个 key 所占用的内存空间,可以使用 memory usage 命令。注意:该命令是 Redis 4.0+ 才开始提供的,如想使用必须将 Redis 升级至 4.0+。


    2.3 内存消耗


    即便我们合适使用正确的数据类型保存数据,将 Big Key 拆分小 key,还是会出现内存消耗问题,那么 Redis 内存消耗是如何产生的呢?一般由以下 3 种情况产生:


    业务不断发展,存储的数据不断增多(不可避免)


    无效/过期的数据没有及时处理(可优化)


    没有对冷数据进行降级(可优化)


    在优化情况 2 之前,我们得先知道为什么会出现没有及时处理过期数据的问题,这得说到 Redis 提供的 3 种过期删除策略:


    定时删除:对于每个设置了过期时间的 key 都会创建一个定时器,一旦达到过期时间就立即删除


    惰性删除:当访问一个 key 时,才判断该 key 是否已过期,如过期就删除


    定期删除:每隔一段时间扫描 Redis 中过期 key 的字典,并清除部分过期的 key


    由于定时删除需要创建定时器,会占用的大量内存,同时精准删除大量 key 也会消耗大量 CPU 资源,因此 Redis 同时采用的是惰性删除和定时删除两种策略。如果客户端没有请求过期的 key 或定期删除线程没有扫描到并清除这个 key,该 key 就会一直占用着内存,导致内存浪费。


    知道了内存消耗的原因后,我们可以很快地想出优化方案:手动删除。


    当使用完缓存后,缓存即使设置了过期时间,我们也要手动调用 del 方法/命令删除。如果不能当场删除,我们也可在代码中开启定时器定期删除这些过期的 key,相比较 Redis 的两种删除策略,手动清除数据要及时很多。


    情况 3 的问题不算大,针对其优化的手段,我们可以调整 Redis 的淘汰策略。


    2.4 多命令的执行


    Redis 是基于一个 request, 一个 response 的同步请求服务。即当多个客户端向 Redis 服务端发送命令时,Redis 服务端只能接收和处理其中的一个客户端的命令,其他客户端只能等待 Redis 服务端处理好当前的命令并作出响应后才会继续接收和处理其他命令请求。


    Redis 处理命令分 3 个过程:接收命令,处理命令,返回结果。由于处理的数据都是在内存中的,因此处理时长通常都是纳秒级别,非常快(big key 除外)。因此,大部分耗时的情况都发生在接受命令和返回结果上。当客户端发送多个命令给 Redis 服务器时,如果有一条命令处理时长很久,其他命令只能等待着,从而影响整体性能。


    为了解决这类问题,Redis 提供了 pipeline(管道),客户端可以将多条命令放入 pipeline 中,然后一次性将 pipeline 的命令发给 Redis 服务端处理,当 Redis 服务端处理完毕后再一次性将结果返回给客户端。这样处理减少了客户端与 Redis 服务端的交互次数,从而减少了往返时间,提升了性能。


    补充:


    Redis pipeline 与原生批量命令对比:


    原生批量命令是原子性,pipeline 是非原子性


    原生批量命令一次只能执行一种命令,pipeline 支持执行多种命令


    原生批量命令是服务端实现,pipeline 需要服务端和客户端实现


    使用 Redis pipeline 的注意事项:


    使用 pipeline 装载的命令数量不能太多


    pipeline 中的命令会按照缓冲的顺序执行,但是可能会穿插其他客户端发来的命令,即不保证时序性


    pipeline 执行中间某一指令出现异常,会继续执行后续的指令,即不保证原子性


    2.5 缓存穿透


    在项目中运用缓存,我们通常的设计思路如下图:

Redis关键点分析4.png

    发送请求查询数据,查询规则是先查缓存,如果缓存没有数据再查询数据库,将查到的数据放入缓存最后返回数据给客户端。如果请求的数据是不存在的,最终每次请求都会请求到数据库中,这就是缓存穿透。


    缓存穿透存到很大的安全隐患,如果有人使用工具发送大量请求,请求一个不存在的数据,大量请求会流入到数据库上,导致数据库压力增大,可能会导致数据库宕机,进而影响整个应用的正常运行,导致系统瘫痪。


    解决这类问题,重点在于减少对数据库的访问,通常有以下几种方案:


    缓存预热:系统发布上线后,提前把相关的数据直接加载到缓存系统中


    设置默认值:如果请求最终落在数据库中,数据库也查不出数据,给缓存 key 设置一个默认值,放入缓存中,注意:由于这个默认值是无意义的,因此我们需要设置过期时间,减少内存占用


    布隆过滤器:将所有可能存在的数据哈希到一个足够大的 bitmap 中,一个不存在的数据肯定会被 bitmap 拦截掉


    2.6 缓存雪崩


    缓存雪崩: 简单来说是指大量请求访问缓存数据但无法查询到,进而去请求数据库,导致数据库压力增大,性能下降,不堪重负宕机,从而影响整个系统正常运行,甚至系统瘫痪的现象。


    比如,一个完整的系统由系统A,系统B,系统C 三个子系统组成,它们的数据请求链是系统A -> 系统B -> 系统C -> 数据库。如果缓存中没有数据,数据库宕机,系统C不能查询数据作出响应,只能处在重试等待的阶段,从而影响了系统B 和系统A。一处节点发生异常导致一连串的问题就像雪山的一阵风吹过引起雪崩的现象。


    看到这里,可能有读者会疑惑,缓存穿透和缓存雪崩有什么区别呢?


    缓存穿透侧重于请求的数据不在缓存中,从而去请求数据库,就好像直接透过缓存直接请求数据库。


    缓存雪崩侧重于大请求由于在缓存中查询不出数据,从而访问数据库导致数据库压力增大引起一系列异常。


    要解决缓存雪崩问题,还是得先知道导致问题的原因:


    Redis 自身出现问题


    热点数据集中失效


    针对原因1,我们可以作为主从集群,尝试使所有请求都在缓存中找到数据,减少对数据库的访问

 

    针对原因2,在设置缓存的过期时间时,请错开过期时间( 例如,在基本时间内增加或减少随机值)可避免集中式缓存失败。同时,我们还可以设置本地缓存(例如ehcache),限制接口流或服务降级,还可以减轻数据库的访问压力。

我来说两句

0 条评论

推荐阅读

  • 响应式布局CSS媒体查询设备像素比介绍

    构建响应式网站布局最常见的是流体网格,灵活调整大小的站点布局技术,确保用户在使用的幕上获得完整的体验。响应式设计如何展示富媒体图像,可以通过以下几种方法。

    admin
  • 提升网站的性能快速加载的实用技巧

    网站速度很重要,快速加载的网站会带来更好的用户体验、更高的转化率、更多的参与度,而且在搜索引擎排名中也扮演重要角色,做SEO,网站硬件是起跑线,如果输在了起跑线,又怎么跟同行竞争。有许多方法可提升网站的性能,有一些技巧可以避免踩坑。

    admin
  • 织梦CMS TAG页找不到标签和实现彩色标签解决方法

    织梦cms是我们常见的网站程序系统的一款,在TAG标签中常常遇到的问题也很多。当我们点击 tags.php 页的某个标签的时候,有时会提示:“系统无此标签,可 能已经移除!” 但是我们检查程序后台,以及前台显示页面。这个标签确实存在,如果解决这个问题那?

    admin
  • HTML关于fieldset标签主要的作用

    在前端开发html页面中常用的标签很多,今天为大家带来的是关于HTML中fieldset标签主要的作用说明,根据技术分析HTML

    admin