Redis 优化

news2025/2/22 11:47:58

目录

优雅的 key

删除 Bigkey

恰当的数据类型

批处理优化

Pipeline

集群下的批处理

服务端优化

持久化配置

慢查询

命令以及安全配置

内存安全和配置

内存缓冲区配置

集群最佳实践

集群带宽问题

集群还是主从


优雅的 key

删除 Bigkey

Bigkey 内存占用较多,即便删除这样的 key 也是比较耗时的,这同样也会导致主线程阻塞,引发一系列问题

在 redis 3.0 版本以前,如果是集合类型,都是先遍历 big key 的元素,再逐个删除,最后再删除 key

来到 redis 4.0 及以后官方就提供了异步删除的命令 :unlink

恰当的数据类型

比如存储一个对象类型的数据,我们推荐三种存储方式

  • json 字符串:实现简单粗暴,缺点:数据耦合吗,不够灵活

  • 字段打散:可以灵活访问对象中的任意字段,缺点:占用空间大,没办法做到统一控制

  • hash:低层使用 ziplist ,占用空间小,可以灵活的访问对象中的任意字段,缺点:代码相对复杂

这么对比下来,hash 完美胜出,但是这还不是最优解,下面是 hash 可能还存在的问题

hash 的 entry 数量超过 500 时,会使用哈希表而不是 Ziplist ,这样也会导致内存占用过大的问题,但是我们可以通过 hash-max-ziplist-entries 配置 entry 上限,但是 entry 过多的话还是会导致 bigkey 的问题再次出现

那么如何优化呢?

拆分 string 类型,假如有 hash 类型的 key ,其中有 100 万对 field 和 value ,field 是自增 id,这个 key 存在什么问题?如何优化呢?

有一个方案就是将每一个 hash 再次才分成多个小的 hash ,这样外层的一个 key 就可以掌管多个内部的 key ,也就是相当于掌管里面所有的 hash ,我们只需要对内部的 hash 的做优化就可以了,如果内部 hash 过于庞大的话,再考虑对外部的 hash 做优化就可以基本解决这个问题

  • key 的最佳实践

    • 固定格式的 key

    • 足够精简,不超过 44 个字节

    • 不包含特殊字符

  • value 的最佳实践

    • 合理拆分数据,拒绝 big key

    • 选择适合的数据类型

    • hash 结构的 entry 最好不要超过 1000

    • 设置合适的超时时间

批处理优化

Pipeline

单个命令的执行流程:一次命令的响应时间 = 1 次往返的网络传输耗时 + 1 次 Redis 执行命令耗时

那么 N 次命令的执行流程也是一个逻辑,但是如果是这样的话,网络传输的往返次数就会非常耗时,如果我们将要请求的 N 条数据一次打包好,然后只往返一次,那么就可以大大减少网络传输的耗时,也可以减少网络拥堵,在 Redis 中我们可以使用比如 mset 的命令可以打包一串数据只发送一次请求,但是在这里我们也还是要注意,在打包一次传输的时候,还是不能一次性打包太多数据,不然当带宽占满后还是会造成网络堵塞的情况,反而得不偿失,拿这里的 mset 举例子,利用 mset 批量插入数据时最好不要一次插入 10 万条数据

原生的批处理命令具有局限性,比如:mset 只能处理字符串,hmset 只能处理 hash 而且 key 是不变的,变的仅仅只有 value ,sadd 还是 key 不能变而且只能处理 set 集合,所以这些命令都具备局限性

这个时候我们就可以使用本章要说明的 pipeline ,它和 mset 很像,但是它允许你传入任何命令

注意事项:批处理时不建议一次携带太多数据,其次 pipeline 的多个命令之间不具备原子性

集群下的批处理

如 mset 或者 pipeline 这样的批处理需要在一次请求中携带多条命令,而此时 redis 如果是一个集群,那么批处理的多个 key 必须落在一共插槽中,否则就会导致执行失败

串行命令串行 slot并行 slothash_tag
实现思路for 循环遍历,依次执行每一条命令在客户端计算每个 key 的 slot ,将 slot 一致分为一组,每组都利用 Pipeline 批处理,串行执行各组命令在客户端计算每个 key 的 slot ,将 slot 一致分为一组,每组都利用 Pipeline 批处理,并行执行各组命令将所有 key 设置相同的 hash_tag,则所有 key 的 slot 一定相同
耗时N 次网络消耗 + N 次网阔耗时m 次网络耗时 + n 次命令耗时,m = key 的 slot 个数1 次网络耗时 + n 次命令耗时1 次网络耗时 + n 次命令耗时
优点实现简单耗时较短耗时非常短耗时非常短且实现非常简单
缺点耗时非常久实现稍微复杂,slot 越多,耗时越久实现复杂容易出现数据倾斜

在这张表上,我们可以看到最后一个 hash_tag 是最好的,但是也存在一定的风险,这相当于把 redis 中的所有的数据都同化了,这就是数据倾斜,所以在实际的开发中我们还是更加推荐并行 slot

服务端优化

持久化配置

Redis 的持久化是用来保护数据的安全性的

  • 但是对于一些作为缓存的数据就不需要去做持久化操作了

  • 建议关闭 RDB 使用 AOF

  • 利用脚本定期为 slave 上做 RDB 数据备份

  • 设置合理的 rewrite 阈值,避免频繁的 bgrewrite

  • 配置 no-appendfsync-on-rewrite = yes , 禁止在 rewrite 期间做 aof ,避免因 aof 引起的阻塞

部署的相关建议

  • redis 实例的物理机要预留足够的内存空间,应对 fork 和 rewrite

  • 单个 redis 实例内存上限不要太大,比如 4G 或者 8G 。可以加快 fork 的速度,减少主从同步,数据迁移的压力

  • 不要与 cpu 密集型的服务部署在一起

  • 不要与高硬盘负载的服务部署在一起

慢查询

在 redis 中执行耗时达到了某个阈值的命令,称之为慢查询

  • slowlog-log-slower-than 慢查询阈值,单位是微秒。默认是 10000 ,建议是 1000

  • 慢查询会被放入慢查询日志当中,日志的长度有上限,可以通过配置指定

  • slowlog-max-len 慢查询日志本质是一个列队默认长度是 128 ,建议 1000

修改这两个配置可以使用 config set 命令,比如 config set slowlog-log-slower-than ,get 是同理,即查看配置

  • slowlog len 查询慢查询日志的长度

  • slowlog get[n] 读取 n 条慢查询日志

  • slowlog reset 清空慢查询列表

命令以及安全配置

Redis 会绑定在 0.0.0.0:6379 ,这样将会使得 redis 服务暴露在公网上,而 redis 如果没有做身份认证,就会出现严重的安全漏洞

漏洞重现方式 Redis未授权访问配合SSH key文件利用分析-腾讯云开发者社区-腾讯云

漏洞出现的几个核心的原因

  • redis 未设置密码

  • 利用 redis 的 config set 命令动态修改 redis 配置

  • 使用了 root 账号权限启动了 redis

为了避免这种情况的发生,这里给出一些建议:

  • Redis 一定要设置密码

  • 禁止线上使用下面命令:key,flushall,flushdb, config set 等命令,可以利用 rename-command 禁用(这条命令悠着点用,典型的弹道偏左)

  • bind 限制网卡,禁止外网网卡访问

  • 开启防火墙

  • 不要使用 root 账号登录 redis

  • 不要使用默认端口

内存安全和配置

当 redis 内存不足时,可能会导致 key 频繁被删除,响应时间变长,QPS 不稳定等问题。当内存使用率达到 90% 以上时我们就需要提高警惕了,并且快速定位到内存占用大的原因

内存占用说明
数据内存是 redis 最主要的部分,存储 redis 的键值信息,主要问题是 bigkey 问题,内存碎片问题
进程内存redis 主进程运行本身很定需要占用内存,如代码,常量池等,这部分内存大约几兆,在大多数生产环境中与 redis 数据占用内存相比可以忽略
缓冲区内存一般包括客户端缓冲区,AOF 缓冲区,复制缓冲区等,客户端缓冲区又包括输入缓冲区和输出缓冲区。这部分内存占用波动较大,不当使用 bigkey ,可能会导致内存溢出

什么是内存碎片:内存碎片是在内存分配的过程中产生的,redis 低层采用的内存分配策略是  LRU ,这种策略它会提前鉴定很多个不同的内存大小,比如说 8 字节,16 字节,32 字节,48 字节 等,不过它是有一套自己的内存分配规则,也不一定是我这里说的 2 的次方,当我们要向 redis 申请一段内存的时候,比如我们这个数据的大小是 10 个字节,如果这个时候这个 10 个字节正好是在 8 - 16 之间的一个阈值,则 redis 就会给这段数据分配 16 个字节的内存,这个时候多出来的内存我们就称之为内存碎片,想要解决内存碎片的问题,我们可以定期的去重启 redis 服务

redis 提供了一些命令,可以查看目前 redis 的内存的一个分配情况分别是 info memory 和 memory xxx

  • memory doctor 内存诊断策略

  • memory purge 清除一些数据

  • memory status 查看内存状态

  • memory usege 查看某个 key 的内存占用情况

内存缓冲区配置
  • 复制缓冲区:主从复制的 repl_backlog_buf ,如果太小可能导致频繁的全量复制,影响性能,通过 repl-backlog-size 来设置,默认 1mb

  • AOF 缓冲区:AOF 刷盘之前的缓存区域,AOF 执行 rewrite 的缓冲区。无法设置容量上限

  • 客户端缓冲区:分为输入缓冲区和输出缓冲区,输入缓冲区最大 1G 且不能设置(这种概率还是比较小的,只要我们控制好慢查询就可以很好的避免这种情况的发生),输出缓冲区可以设置

默认配置

当前 redis 连接了多少的客户端 info clients , clients list 可以查看当前所有的连接到 redis 的所有的客户端的详细信息

集群最佳实践

在 redis 的默认配置中,如果发现任意一条插槽不可用,则整个集群都会停止服务,为了保证高可用特性,这里建议 cluster-require-full-coverage 设置为 no ,这样做就是会牺牲一定的数据完整性,但是保障了业务的基本运作

集群带宽问题

集群节点之间会不断的 ping 来判断集群之间其他节点的状态,每次 ping 携带的信息至少包括

  • 插槽信息

  • 集群状态信息

集群中的节点越多,集群的信息就会越庞大,10 个节点的相关信息就可以达到大约 1kb,此时的节点之间的互通带宽的占用率就会提高,为了解决这一问题,我们可以:

  • 避免大集群,集群节点数不要太多,最好少于 1000 ,如果业务庞大则建立多个集群

  • 避免在单个物理机上运行多个 redis 实例

  • 配置合适的 cluster-node-timeout 值

集群还是主从

集群虽然具备高可用,能够实现故障自动修复,但是如果使用不当,一样会出现一些问题

  • 集群完整性问题

  • 集群带宽问题

  • 数据倾斜问题

  • 客户端性能问题

  • 命令的集群兼容性问题

  • lua 和事务问题

单体 redis 已经能达到万进别的 QPS 了,并且也具备很高的高可用特性,如果主从能够满足业务需求,尽量不要搭建 redis 集群

至此,我总结的 Redis 优化完成,有什么不足还请大佬指点

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2162586.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

线程池和JUC

1. 线程池 1.1 线程状态介绍 当线程被创建并启动以后,它既不是一启动就进入了执行状态,也不是一直处于执行状态。线程对象在不同的时期有不同的状态。那么Java中的线程存在哪几种状态呢?Java中的线程 状态被定义在了java.lang.Thread.Stat…

微服务学习笔记之Docker

目录 认识Docker 安装Docker 安装yum工具 配置Docker的yum源 更新yum,建立缓存 安装Docker 启动并校验 配置镜像加速 Docker常见命令 命令 演示 给命令起别名 Docker数据卷 认识数据卷 数据卷常见命令 nginx的html目录挂载演示 数据卷挂载本地目录或…

强制类型转换

问题 最近在研读公司项目的时候发现一段很有意思的代码: if (a instanceof b) {B ent (B) a;if (!useGivenAuditAttributes) {ent.createdAt MyDateUtils.now();ent.createdBy AppContext.instance.loginUser.userId;ent.lastUpdatedAt ent.createdAt;ent.las…

如何把python(.py或.ipynb)文件打包成可运行的.exe文件?

将 Python 程序打包成可执行的 .exe 文件,通常使用工具如 PyInstaller。这是一个常用的 Python 打包工具,可以将 Python 程序打包成独立的可执行文件,即使没有安装 Python 也能运行。 步骤: 1. 安装 PyInstaller 使用 conda 安…

【shell脚本5】Shell脚本学习--条件控制

目录 条件判断:if语句 分支控制:case语句 条件判断:if语句 语法格式: if [ expression ] thenStatement(s) to be executed if expression is true fi 注意:expression 和方括号([ ])之间必须有空格,否…

centos7 配置 docker 国内镜像源

1.修改配置文件/etc/docker/daemon.json sudo vim /etc/docker/daemon.json2.增加或修改以下配置内容 {"registry-mirrors": ["https://dockerproxy.com","https://hub-mirror.c.163.com","https://mirror.baidubce.com","http…

谷歌浏览器如何更改下载文件存放的方式及其路径?

1、点击谷歌浏览器右上角的【三个点】 2、选择【设置】,再选择【下载内容】 3、打开【下载完成后显示下载内容】开关, 则:下载网页上的东西之后,会显示在【谷歌浏览器】的右侧,并显示具体下载文件在右侧:…

PR视频剪辑工具全指南:开启专业剪辑之旅

pr视频剪辑可以说是视频剪辑里的一把好手,就是如果你想在这方面深耕那还是掌握这个工具的使用比较方便。如果你只是刚入门,那也有不少可以快速帮你剪辑出片的工具。这次我介绍几款我用过的视频剪辑工具,助你开启视频剪辑大门。 1.福昕视频剪…

vue echarts tooltip动态绑定模板,并且处理vue事件绑定

先上代码: tooltip: {// 这里是车辆iconshow: true,// trigger: "item",// backgroundColor: "transparent",appendToBody: true,textStyle: {color: "#ffffff" //设置文字颜色},formatter: (params) > {const TruckTooltip Vue.…

Java-数据结构-排序(三) |ू・ω・` )

目录 ❄️一、归并排序: ☞ 基本思想: ☞ 代码: ☞ 归并排序的非递归方法: ❄️二、排序算法的分析: ❄️三、非基于比较的排序: ❄️总结: ❄️一、归并排序: ☞ 基本思想&#xf…

在一个.NET Core项目中使用RabbitMQ进行即时消息管理

为了在一个.NET Core项目中使用RabbitMQ进行即时消息管理,以下是详细的全程操作指南,包括安装、配置、编写代码和调试使用。 一、安装RabbitMQ 1. 安装Erlang RabbitMQ依赖Erlang,因此需要先安装Erlang。 Windows: 下载并运行Erlang安装…

人工智能-机器学习-深度学习-分类与算法梳理

目前人工智能的概念层出不穷,容易搞混,理清脉络,有益新知识入脑。 为便于梳理,本文只有提纲,且笔者准备仓促,敬请勘误,不甚感激。 请看右边目录索引 。 人工智能 三大派系 符号主义(Symbolists…

[附源码]宠物领养管理系统+SpringBoot

今天带来一款优秀的项目:宠物领养管理系统源码 。 系统采用的流行的前后端分离结构,内含功能包括"管理端",“用户领养端”,“宠物管理”,“权限登录”等功能。 如果您有任何问题,也请联系小编&a…

keepalived+lvs集群

目录 一、环境 二、配置 1、master 1.在master上安装配置Keepalived 2.在master上修改配置文件 2、backup 1.在backup(192.168.229.12)上安装keepalived 2.在backup上修改配置文件 3、master和backup上启动服务 4、web服务器配置 1.web1和web…

使用Java基于GeoTools读取Shapefile矢量数据属性信息-以某市POI数据为例

前言 在之前的博客中,我们讲过在GDAL中如何读取空间数据的属性和数据信息,也简单的讲过如何在GeoTools中读取Shapefile文件的属性信息和数据信息。对于空间矢量数据库,就像我们传统的二维数据库的表字段和表数据的关系,在研究表数…

BERT训练之数据集处理(代码实现)

目录 1读取文件数据 2.生成下一句预测任务的数据 3.预测下一个句子 4.生成遮蔽语言模型任务的数据 5.从词元中得到遮掩的数据 6.将文本转化为预训练数据集 7.封装函数类 8.调用 import os import random import torch import dltools 1读取文件数据 def _read_wiki(data_d…

Java框架学习(Spring)(ioc)(01)

简介:以本片记录在尚硅谷学习ssm-spring-ioc时遇到的小知识 详情移步:想参考的朋友建议全部打开相互配合学习! 视频: 014-spring-框架概念理解_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1AP411s7D7?p14&vd_sou…

SpringBoot框架在文档管理中的创新应用

第3章 系统分析 3.1 需求分析 在线文档管理系统主要是为了提高工作人员的工作效率和更方便快捷的满足员工,更好存储所有数据信息及快速方便的检索功能,对系统的各个模块是通过许多今天的发达系统做出合理的分析来确定考虑员工的可操作性,遵循…

峟思助力堤防工程安全:构建多功能防洪屏障

堤防工程,作为水利建设中至关重要的防护体系,不仅守护着江河、湖泊及滨海区域的安全,更是确保人民生命财产安全的坚固防线。在现代社会,随着技术的进步与安全意识的提升,堤防工程不仅限于传统的防洪功能,更…

SpringBoot和JPA初探

目录 SpringBoot和JPA初探0.准备条件1.创建JPA项目2.项目3.总结 SpringBoot和JPA初探 我们使用SpringBootJPA做一个简单的API接口演示,通过一个简单的例子让大家对Spring Data JPA有一个整体的认知。 0.准备条件 IntelliJ IDEAjdk 1.8mysql 8.0maven 3.8.x 1.创…