文章目录

  • 一、Linux 配置优化
    • 内存分配控制
    • OOM killer
    • 使用 NTP
  • 二、flushall / flushdb 误操作
    • 缓存与存储
    • 借助 AOF 机制恢复
    • RDB 有什么变化
  • 三、安全的 Redis
    • Redis 密码机制
    • 伪装危险命令
    • 防火墙
    • 定期备份数据
    • 不使用默认端口
    • 使用非 root 用户启动
  • 四、处理 bigkey
    • bigkey 的危害
    • 如何发现
    • 如何删除
  • 五、寻找热点 key
    • 统计热点 key
    • 解决热点 key 问题

一、Linux 配置优化

内存分配控制

  • Redis 设置合理的 maxmemory,保证机器有 20% ~ 30% 的闲置内存。
  • 集中化管理 AOF 重写和 RDB 的 bgsave。
  • 设置 vm.overcommit_memory=1,防止极端情况下会造成 fork 失败。

OOM killer

  • OOM killer 会在可用内存不足时选择性地杀掉用户进程。
  • 对于 Redis 所在的服务器来说,可以将所有 Redis 的 oom_adj 设置为最低值或者稍小的值,降低被 OOM killer 杀掉的概率。

使用 NTP

  • NTP(Network Time Protocol,网络时间协议)是一种保证不同机器时钟一致性的服务。一般公司里都会有 NTP 服务用来提供标准时间服务,从而达到纠正时钟的效果。

二、flushall / flushdb 误操作

  • Redis 的 flushall / flushdb 命令可以做数据清除,对于 Redis 的开发和运维人员有一定帮助,然而一旦误操作,它的破坏性也是很明显的。

缓存与存储

  • 被误操作 flush 后,根据当前 Redis 是缓存还是存储使用策略有所不同:

    • 缓存:对于业务数据的正确性可能造成损失还小一点,因为缓存中的数据可以从数据源重新进行构建。
    • 存储:对业务方可能会造成巨大的影响,如果没有提前做业务降级,那么最终反馈到用户的应用可能就是报错或者空白页面等。

借助 AOF 机制恢复

  • Redis 执行了 flush 操作后,AOF 持久化文件会受到什么影响呢,如下:

    • appendonly no:对 AOF 持久化没有任何影响,因为根本不存在 AOF 文件。
    • appendonly yes:只不过在 AOF 文件中追加了一条 flushall 记录。
  • 也就是说,虽然 Redis 中的数据被清掉了,但是 AOF 文件还保存着 flush 操作之前完整的数据,这对恢复数据是很有帮助的。

RDB 有什么变化

Redis 执行了 flushall 操作后,RDB持久化文件会受到什么影响呢?

  • 1)如果没有开启 RDB 的自动策略,也就是配置文件中没有类似如下配置
save 900 1
save 300 10
save 60 10000
  • 那么除非手动执行过 save、bgsave 或者发生了主从的全量复制,否则 RDB 文件也会保存 flush 操作之前的数据,可以作为恢复数据的数据源。注意问题如下:

    • 防止手动执行 save、bgsave,如果此时执行 save、bgsave,新的 RDB 文件就不会包含 flush 操作之前的数据,被老的RDB文件进行覆盖。
    • RDB 文件中的数据可能没有 AOF 实时性高,也就是说,RDB 文件很可能很久以前主从全量复制生成的,或者之前用 save、bgsave 备份的。
  • 2)如果开启了 RDB 的自动策略,由于 flush 涉及键值数量较多,RDB 文件会被清除意味着使用 RDB 恢复基本无望。


三、安全的 Redis

  • 数据丢失对于很多 Redis 的开发者来说是致命的,经过相关机构的调查发现,被攻击的 Redis 有如下特点:

    • Redis 所在的机器有外网 IP
    • Redis 以默认端口 6379 为启动端口,并且是对外网开放的
    • Redis 以 root 用户启动的 Redis 没有设置密码
    • Redis 的 bind 设置为 0.0.0.0 或者 “”
  • 将从下面几个方面介绍如何保证 Redis 的安全。

Redis 密码机制

  • Redis 提供了 requirepass 配置为 Redis 提供密码功能,如果添加这个配置,客户端就不能通过 redis-cli -h {ip} -p {port} 来执行命令。

伪装危险命令

  • Redis 中包含了很多“危险”命令,一旦生产上错误使用或者误操作,后果不堪设想,例如:

    • keys:如果键值较多,存在阻塞 Redis 的可能性
    • flushall/flushdb:数据全部被清除
    • save:如果键值较多,存在阻塞 Redis 的可能性
    • debug:个例如 debug reload 会重启 Redis
    • config:config 应该交给管理员使用
    • shutdown:停止 Redis
  • Redis 提供了 rename-command 配置解决了这个问题,例如添加如下配置:
rename-command flushall abcabcabc
  • 那么再执行 flushall 的话,会收到 Redis 不认识 flushall 的错误提示,说明成功的对 flushall 进行了伪装。
  • 而如果执行 abcabcabc ,那么就可以实现 flushall 功能了。

防火墙

  • 可以使用防火墙限制输入和输出的 IP 或者 IP 范围、端口或者端口范围。

定期备份数据

  • 定期备份数据能够在一定程度挽回一些损失,定期备份持久化数据是一个比较好的习惯。

不使用默认端口

  • Redis 的默认端口是 6379,不使用默认端口从一定程度上可降低被入侵者发现的可能性,因为入侵者通常本身也是一些攻击程序。

使用非 root 用户启动

  • root 用户作为管理员,权限非常大。如果被入侵者获取 root 权限后,就可以在这台机器以及相关机器所以操作。所以建议在启动 Redis 服务的时候使用非 root 用户启动。

四、处理 bigkey

  • bigkey 是指 key 对应的 value 所占的内存空间比较大,例如一个字符串类型的 value 可以最大存到 512MB,一个列表类型的 value 最多可以存储 2^32 - 1 个元素。如果按照数据结构来细分的话,一般分为两种:

    • 字符串类型:体现在单个 value 值很大,一般认为超过 10 KB 就是 bigkey,但这个值和具体的 OPS 相关。
    • 非字符串类型:哈希、列表、集合、有序集合,体现在元素个数过多

bigkey 的危害

  • 内存空间不均匀:例如在 Redis 集群中,bigkey 会造成节点的内存空间使用不均匀。
  • 超时阻塞:由于 Redis 单线程的特性,操作 bigkey 比较耗时,也就意味着阻塞 Redis 可能性增大。
  • 网络阻塞:每次获取 bigkey 产生的网络流量较大。

如何发现

  • redis-cli --bigkeys 可以命令统计 bigkey 的分布。但是生产环境中,开发和运维人员更希望自己可以定义 bigkey 的大小而且更希望找到真正的 bigkey 都有哪些 ,这样才可以去定位、解决、优化问题。
  • 判断一个 key 是否为 bigkey,只需要执行 debug object key 查看 serializedlength 属性即可,它表示 key 对应的 value 序列化之后的字节数。
  • 在实际的生产环境中发现 bigkey 的两种方式如下:
    • 被动收集:许多开发人员确实可能对 bigkey 不了解或重视程度不够,但是这种 bigkey 一旦大量访问,很可能就会带来命令慢查询和网卡跑满问题,开发人员通过对异常的分析通常能找到异常原因可能是 bigkey,这种方式并不推荐,但是在实际生产环境中却大量存在,建议修改 Redis 客户端,当抛出异常时打印出所操作的 key,方便排查 bigkey 问题。
    • 主动检测scan + debug object,如果怀疑存在bigkey,可以使用scan命令渐进的扫描出所有的key,分别计算每个 key 的 serializedlength,找到对应 bigkey 进行相应的处理和报警,这种方式是比较推荐的方式。

如何删除

  • 首先,无论是什么数据结构,del 命令都能将其删除。但是经过上面的分析你一定不会这么做,删除 bigkey 通常来说会阻塞 Redis 服务
  • 这个时候就需要 scan 命令的若干类似命令拿出来:sscan、hscan、zscan
  • string
    • 对于 string 类型使用 del 命令一般不会产生阻塞
  • hash、list、set、sorted set
    • 下面以 hash 为例子,使用 hscan 命令,每次获取部分(例如 100 个)field-value,再利用 hdel 删除每个 field(为了快速可以使用 Pipeline):
        public void delBigHash(String bigKey) {// 游标Jedis jedis = new Jedis("127.0.0.1", 6379);String cursor = "0";while (true) {ScanResult<Map.Entry<String, String>> scanResult = jedis.hscan(bigKey, cursor, new ScanParams().count(100));// 每次扫描后获取新的游标cursor = scanResult.getStringCursor();// 获取扫描结果List<Map.Entry<String, String>> list = scanResult.getResult();if (list == null || list.size() == 0) {continue;}String[] fields = getFieldsFrom(list);// 删除多个fieldjedis.hdel(bigkey, fields);// 游标为0时停止if (cursor.equals("0")) {break;}}//最终删除keyjedis.del(bigKey);}/*** 获取 field 数组* @param list* @return*/private String[] getFieldsFrom(List<Map.Entry<String, String>> list) {List<String> fields = new ArrayList<>();for (Map.Entry<String, String> entry : list) {fields.add(entry.getKey());}return fields.toArray(new String[fields.size()]);}
    
  • Redis 4.0 新增了非常实用的惰性删除 lazy free 特性,从根本上解决了 bigkey(主要指定元素较多集合类型key)删除的风险

五、寻找热点 key

热门新闻事件或商品通常会给系统带来巨大的流量,对存储这类信息的 Redis 来说却是一个巨大的挑战。以 Redis Cluster 为例,它会造成整体流量的不均衡,个别节点出现 OPS 过大的情况,极端情况下热点 key 甚至会超过 Redis 本身能够承受的 OPS,因此寻找热点 key 对于开发和运维人员非常重要。下面从以下几个方面分析热点 key。

统计热点 key

  • 客户端

    • 客户端其实是距离 key “最近” 的地方,因为 Redis 命令就是从客户端发出的,例如在客户端设置全局字典(key 和调用次数),每次调用 Redis 命令时,使用这个字典进行记录。
    • 使用客户端进行热点 key 的统计非常容易实现,但同时问题也非常多:
      • 无法预知 key 的个数,存在内存泄露的危险。
      • 对于客户端代码有侵入,各个语言的客户端都需要维护此逻辑,维护成本较高。
      • 只能了解当前客户端的热点 key,无法实现规模化运维统计。
  • 代理端
    • 像 Twemproxy、Codis 这些基于代理的 Redis 分布式架构,所有客户端的请求都是通过代理端完成的。此架构是最适合做热点 key 统计的,因为代理是所有 Redis 客户端和服务端的桥梁。但并不是所有Redis都是采用此种架构。
  • Redis 服务端
    • 使用 monitor 命令统计热点 key 是很多开发和运维人员首先想到,monitor 命令可以监控到 Redis 执行的所有命令
    • 利用 monitor 命令就可以统计出一段时间内的热点 key 排行榜、命令排行榜、客户端分布等数据。
    • 但是此种方法会有两个问题:
      • monitor 命令在高并发条件下,会存在内存暴增和影响 Redis 性能的隐患,所以此种方法适合在短时间内使用。
      • 只能统计一个 Redis 节点的热点 key,对于 Redis 集群需要进行汇总统计。
  • 机器
    • Redis 客户端使用 TCP 协议与服务端进行交互,通信协议采用的是 RESP。如果站在机器的角度,可以通过对机器上所有 Redis 端口的 TCP 数据包进行抓取完成热点 key 的统计

解决热点 key 问题

  • 拆分复杂数据结构:如果当前 key 的类型是一个二级数据结构,例如哈希类型。如果该哈希元素个数较多,可以考虑将当前 hash 进行拆分,这样该热点 key 可以拆分为若干个新的 key 分布到不同 Redis 节点上,从而减轻压力。
  • 迁移热点key:以 Redis Cluster 为例,可以将热点 key 所在的 slot 单独迁移到一个新的 Redis 节点上,但此操作会增加运维成本。
  • 本地缓存加通知机制:可以将热点 key 放在业务端的本地缓存中,因为是在业务端的本地内存中,处理能力要高出 Redis 数十倍,但当数据更新时,此种模式会造成各个业务端和 Redis 数据不一致,通常会使用发布订阅机制来解决类似问题。

来源:《Redis 开发与运维》第 12 章 开发运维的“陷阱”

【Redis 开发与运维】开发运维的“陷阱”相关推荐

  1. 20款开发运维必备的顶级工具,速收

    开发运维工具与软件开发领域的最佳实践密切相关,也与必要的规范密切相关.在整个开发生命周期涉及到一大批新旧工具,从规划.编码.测试.发布到监控. 开发运维是那些还没有得到明确定义,就流传开来的科技时髦词 ...

  2. 【Redis】《Redis 开发与运维》笔记-Chapter12-开发运维的“ 陷阱”

    十二.开发运维的" 陷阱" 1.Linux配置优化之内存分配控制 1)vm.overcommit_memory Linux操作系统对大部分申请内存的请求都回复yes,以便能运行更多 ...

  3. php 运维系统开发,PHP开发运维管理系统笔记

    开发运维管理系统采用ThinkPHP框架+mysql进行开发.框架配置return array( //'配置项'=>'配置值' 'SHOW_PAGE_TRACE' => true, //允 ...

  4. 读书笔记:redis开发与运维 基础篇

     redis特性    1>速度快:redis所有数据都是存放在内存中,是redis速度快的主要原因,是有c编写,一般来说用c编写的程序距离操作系统近,执行速度更快,非阻塞I/O,使用epoll ...

  5. 高级开发运维从简单学:Redis哨兵和集群小贴士

    目录 写在前面 一.数据库服务器高可用 二. Sentinel (哨兵)是啥? 三.部署 Sentinel过程 1.初始化服务器 2.将普通的Redis服务器使用的代码替换成sentinel专用代码 ...

  6. 「Redis开发与运维」读书笔记

    第一章 初识Redis Redis的8个重要特性 速度快 内存存储数据 C语言实现 单线程架构,避免多线程竞争问题 Redis源码优化好 基于键值对的数据结构服务器 Redis 值可支持多种数据结构, ...

  7. Redis开发与运维笔记_1 初识2 API

    目录 概述 第1章 初识Redis 1.1 盛赞Redis 1.2 Redis特性 1.3 配置.启动.操作.关闭Redis 第2章 API的理解和使用 2.1 预备 2.1.1 全局命令 2.1.2 ...

  8. 《Redis开发与运维》读书笔记--初识Redis(一)

    目录 盛赞Redis Redis特性 redis使用场景 redis可以做什么? redis不可以做什么? 关于用好redis的两点建议 本章重点回顾 写在前面: 想必在写项目的过程中,我们很多时候都 ...

  9. 开发运维已死,无运维万岁

    在如今的IT发展趋势中,开发运维(DevOps )这个词非常流行.这个词是几年前随着单页应用程序(SPA)的盛行而开始火爆起来的.然而,在接下来的几年中,你将听到一个新的流行语:无运维(NoOps). ...

  10. 《Redis开发与运维》各章重点回顾

    第 1 章 初识 Redis Redis 8个特性:速度快.基于键值对的数据结构服务器.功能丰富.简单稳定.客户端语言多.持久化.主从复制.支持高可用和分布式. Redis 不是万金油,有些场景不适合 ...

最新文章

  1. 细说SSO单点登录(转)
  2. 多索引表 (8)表操作
  3. vc 只有顶级窗口可以弹出窗口_如何在Mac上允许弹出窗口
  4. java包装项目_项目包装组织
  5. 小学计算机教案表格式,小学信息技术教案表格数据处理.docx
  6. python product函数
  7. SORPAS-焊接仿真模拟软件
  8. win10企业版2016长期服务版本---低配置电脑最适合的win10版本
  9. linux运维工程师问题,2、Linux运维工程师之解决问题思路
  10. 记录常用的xss攻击代码,便于测试系统安全漏洞
  11. 自己用的unity学习笔记(一)——unity3d基础操作
  12. unity网络资源导入
  13. matlab元胞数组的创建和显示
  14. 【第4期-智能驾驶汽车系列术语概念解析】第5节:龙格现象
  15. Java 日志框架详解
  16. 【无标题】 2022年铜陵市外观设计专利申请条件及费用
  17. 微信公众平台使用百度API查询天气预报
  18. vue中关闭浏览器清除localStorage,并且刷新时保持状态不受影响
  19. 中国互联网乃至移动互联网发展最好的十个城市排名,我会这么排:北京,深圳,上海,杭州,广州,成都,武汉,南京,西安,厦门。
  20. ISO三体系认证多少钱?

热门文章

  1. Office 2007:另存为PDF或XPS
  2. vue下载导出Excel案例
  3. 用什么软件可以检测苹果耳机芯片_苹果现在要用 AirPods,彻底占据你的耳朵了...
  4. 2020年亚太杯数学建模竞赛赛题
  5. jieba 结巴分词详解
  6. 关于另类BT下载的想法
  7. 深度装机大师一键重装_做好电脑重装系统前后的这些注意事项,让你从此摆脱装机忧愁!...
  8. CRMEB商城公众号H5前端模板修改,nodejs使用教程
  9. 把html转换成word,怎么把html转换成word
  10. 《Go语言实战》读书笔记——关于Go语言的介绍