11个提高 Redis 性能的技巧(redis 性能优化)
wptr33 2025-01-29 18:21 25 浏览
众所周知,Redis 是基于内存型的数据库,因而其有出色的性能。理论上说,单节点Redis可以处理高达10万QPS的流量。如此高性能也意味着如果使用过程中出现延迟,就达不到预期。
所以,在使用Redis时,如何不断发挥其高性能,避免操作延迟的发生是我们需要关注的重点。对此,本文总结了11条的建议。
1. 避免存储键值很大的Key
键值很大的Key,通俗叫法:bigkey。
存储bigkey不仅会像以前文章提到过的那样占用过多的内存,而且对Redis的性能影响也很大。由于 Redis 是在单线程中处理请求的,所以当我们的应用程序写入bigkey时,会消耗更多的时间在“内存分配”上,此时操作延迟就会大大增加。
同样,删除bigkey时,“内存释放”过程也是需要时间的。而且,当我们读取bigkey时,更多的时间会花费在“网络数据传输”上。这时,后续要执行的请求就会排队,Redis的性能也就下降了。
所以,我们的应用程序应尽量不要存储bigkey,以避免操作延迟。
如果确实需要存储bigkey,可以将bigkey拆分成多个小key进行存储。
2. 不适应过于复杂的命令
Redis 以单线程处理请求。除了操作bigkey时后续的请求会出现排队的情况外,执行复杂度过高的命令时也会出现这种情况。
因为执行复杂度过高的命令会消耗更多的CPU资源,而主线程中的其他请求只能等待,此时也会出现排队延迟。
所以,我们应尽量避免执行如 SORT,SINTER, SINTERSTORE,ZUNIONSTORE和ZINTERSTORE等聚合命令。
对于这些聚合操作,建议在客户但执行,不要让 Redis 承担过多的计算工作。
3. 关注DEL命令的时间复杂度
删除某个key时,如果操作不正确,也会影响Redis的性能。
删除key时,我们通常使用DEL命令。回想一下,DEL的时间复杂度是怎样的?
O(1)?其实是不一定的。
当删除值为String类型的key时,时间复杂度确实是O(1)。
但是当我们要删除的key是List/Hash/Set/ZSet类型时,它的复杂度实际上是O(N),N代表元素的数量。也就是说,在删除某个key时,元素越多,DEL的执行速度就越慢。
原因是删除大量元素时,需要依次回收每个元素的内存,元素越多,花费的时间就越长。而且,这个过程默认实在主线程中执行的,必然会阻塞主线程,导致性能问题。
那么,删除元素比较多的key时应该如何处理呢?
建议是批量删除:
- 对于List类型:多次执行LPOP/RPOP,知道删除所有元素。
- 对于Hash/Set/ZSet类型:先执行HSCAN/SREM/SCAN查询元素,然后执行HDEL/SREM/ZREM依次删除各个元素。
这部不得不感到惊讶!一个小的删除操作,如果不小心,也会导致性能问题。所以,操作时要格外小心。
4. 启用lazy-free机制
如果无法避免存储bigkey的发生,那么建议启用Redis的lazy-free机制(4.0+版本支持)。
启用这个机制后,当Redis删除一个bigkey时,释放内存的耗时操作将在后台线程中执行,这样可以最大程度地避免对主线程的影响。
5. 执行O(N)命令时,注意N的大小
避免使用过于复杂的命令之后,也不是就可以高枕无忧了!
当执行O(N)的命令时,还需要注意N的大小。
如果一次查询的数据过多,在网络传输过程中也会花费很长时间,增加操作延迟。
所以,对于容器类型(List/Hash/Set/ZSet),当元素数量未知时,千万不要盲目执行LANGE key 0 -1、HGETALL、SMEMBERS、ZRANGE key 0 -1等命令。
查询数据时,可遵循以下原则:
- 首选查询数据元素的个数(涉及命令:LLEN、HLEN、SCARD、ZCARD)。
- 如果元素数量比较少,可以一次性查询出所有数据。
- 如果元素数量非常多,则批量查询数据(涉及命令:LRANGE、HSCAN、SSCAN、ZSCAN)。
6. 使用批处理命令而不是单独的命令
当需要同时操作多个key时,应该使用批量处理命令来处理。
批量操作相对于多个单独操作的优势在于,它可以显著减少客户端和服务器之间网络I/O的往返次数。
以下是给出的建议:
- 对于String/Hash类型:使用MGET/MSET代替GET/SET,使用 HMGET/HMSET代替HGET/HSET。
- 对于其他数据类型,使用 Pipeline 将多个命令一次性打包发送到服务器执行。
7. 避免key集中过期
Redis 会以一种定时、惰性的方式清理过期的密钥,这个过程在主线程中执行。 如果业务中存在大量集中过期的键,那么当 Redis 清理过期键时,也会存在阻塞主线程的风险。
为了避免这种情况,在设置过期时间时,可以添加一个随机时间来分散这些key的过去时间,从而减少集中过期对主线程的影响。
8. 长连接操作Redis,合理配置连接池
我们应使用长连接允许Redis,并避免短连接。短连接操作Redis时,每次都需要TCP三次握手和四次挥手,这个过程也会增加操作时间耗时。
同时,我们的客户端应用以连接池的方式访问Redis,并配置合理的参数。当长连接不操作Redis时,应及时释放连接资源。
9. 只是要 db0
虽然Redis提供了16个数据库,但推荐只使用db 0。为什么呢?以下是总结的三个原因:
- 在一个连接上操作多个数据库数据时,每次都需要先执行 SELECT,这会给Redis带来额外的压力。
- 使用多个数据库的目的是为了根据不同的业务线来存储数据。那么为什么不将它们拆分并存储在多个实例呢?部署多个实例,拆分存储,多个业务线不会互相影响,也可以提高Redis的访问性能。
- Redis Cluster 只支持 db 0,如果以后想迁移 Redis Cluster,会增加迁移成本。
10. 采用读写分离+分片集群
如果我们的业务的读取请求量很大,那么我们可以部署多个从库来实现读写分离,让 Redis 的从库分担读取压力,从而提高性能。
如果我们的业务的写入请求量也非常大,单个实例已经无法支撑这么大的写入流量,那么这时候就需要使用分片集群来分担写入压力。
11. 不要启用AOF或配置AOF每秒刷盘
对于数据丢失不敏感的业务,建议不要启用AOF,避免AOF写入磁盘导致Redis性能下降。
如需确实需要启用AOF,那么建议将其配置为 appendfsynce everysec,并将数据持久化的磁盘刷新操作放到后台线程执行,以尽量减少Redis写入磁盘对性能的影响。
以上就是Redis高性能方面的实用优化,如果你非常关心Redis的性能问题,你可以结合这几个方面进行针对性的优化。当然,您还有其他好的方案,欢迎您不吝赐教。
相关推荐
- [常用工具] git基础学习笔记_git工具有哪些
-
添加推送信息,-m=messagegitcommit-m“添加注释”查看状态...
- centos7安装部署gitlab_centos7安装git服务器
-
一、Gitlab介1.1gitlab信息GitLab是利用RubyonRails一个开源的版本管理系统,实现一个自托管的Git项目仓库,可通过Web界面进行访问公开的或者私人项目。...
- 太高效了!玩了这么久的Linux,居然不知道这7个终端快捷键
-
作为Linux用户,大家肯定在Linux终端下敲过无数的命令。有的命令很短,比如:ls、cd、pwd之类,这种命令大家毫无压力。但是,有些命令就比较长了,比如:...
- 提高开发速度还能保证质量的10个小窍门
-
养成坏习惯真是分分钟的事儿,而养成好习惯却很难。我发现,把那些对我有用的习惯写下来,能让我坚持住已经花心思养成的好习惯。...
- 版本管理最好用的工具,你懂多少?
-
版本控制(Revisioncontrol)是一种在开发的过程中用于管理我们对文件、目录或工程等内容的修改历史,方便查看更改历史记录,备份以便恢复以前的版本的软件工程技术。...
- Git回退到某个版本_git回退到某个版本详细步骤
-
在开发过程,有时会遇到合并代码或者合并主分支代码导致自己分支代码冲突等问题,这时我们需要回退到某个commit_id版本1,查看所有历史版本,获取git的某个历史版本id...
- Kubernetes + Jenkins + Harbor 全景实战手册
-
Kubernetes+Jenkins+Harbor全景实战手册在现代企业级DevOps体系中,Kubernetes(K8s)、Jenkins和Harbor组成的CI/CD流水...
- git常用命令整理_git常见命令
-
一、Git仓库完整迁移完整迁移,就是指,不仅将所有代码移植到新的仓库,而且要保留所有的commit记录1.随便找个文件夹,从原地址克隆一份裸版本库...
- 第三章:Git分支管理(多人协作基础)
-
3.1分支基本概念分支是Git最强大的功能之一,它允许你在主线之外创建独立的开发线路,互不干扰。理解分支的工作原理是掌握Git的关键。核心概念:HEAD:指向当前分支的指针...
- 云效Codeup怎么创建分支并进行分支管理
-
云效Codeup怎么创建分支并进行分支管理,分支是为了将修改记录分叉备份保存,不受其他分支的影响,所以在同一个代码库里可以同时进行多个修改。创建仓库时,会自动创建Master分支作为默认分支,后续...
- git 如何删除本地和远程分支?_git怎么删除远程仓库
-
Git分支对于开发人员来说是一项强大的功能,但要维护干净的存储库,就需要知道如何删除过时的分支。本指南涵盖了您需要了解的有关本地和远程删除Git分支的所有信息。了解Git分支...
- git 实现一份代码push到两个git地址上
-
一直以来想把自己的博客代码托管到github和coding上想一次更改一次push两个地址一起更新今天有空查资料实践了下本博客的github地址coding的git地址如果是Gi...
- git操作:cherry-pick和rebase_git cherry-pick bad object
-
在编码中经常涉及到分支之间的代码同步问题,那就需要cherry-pick和rebase命令问题:如何将某个分支的多个commit合并到另一个分支,并在另一个分支只保留一个commit记录解答:假设有两...
- 模型文件硬塞进 Git,GitHub 直接打回原形:使用Git-LFS管理大文件
-
前言最近接手了一个计算机视觉项目代码是屎山就不说了,反正我也不看代码主要就是构建一下docker镜像,测试一下部署的兼容性这本来不难但是,国内服务器的网络环境实在是恶劣,需要配置各种镜像(dock...
- 防弹少年团田柾国《Euphoria》2周年 获世界实时趋势榜1位 恭喜呀
-
当天韩国时间凌晨3时左右,该曲在Twitter上以“2YearsWithEuphoria”的HashTag登上了世界趋势1位。在韩国推特实时趋势中,从上午开始到现在“Euphoria2岁”的Has...
- 一周热门
-
-
C# 13 和 .NET 9 全知道 :13 使用 ASP.NET Core 构建网站 (1)
-
程序员的开源月刊《HelloGitHub》第 71 期
-
详细介绍一下Redis的Watch机制,可以利用Watch机制来做什么?
-
假如有100W个用户抢一张票,除了负载均衡办法,怎么支持高并发?
-
Java面试必考问题:什么是乐观锁与悲观锁
-
如何将AI助手接入微信(打开ai手机助手)
-
SparkSQL——DataFrame的创建与使用
-
redission YYDS spring boot redission 使用
-
一文带你了解Redis与Memcached? redis与memcached的区别
-
如何利用Redis进行事务处理呢? 如何利用redis进行事务处理呢英文
-
- 最近发表
- 标签列表
-
- git pull (33)
- git fetch (35)
- mysql insert (35)
- mysql distinct (37)
- concat_ws (36)
- java continue (36)
- jenkins官网 (37)
- mysql 子查询 (37)
- python元组 (33)
- mybatis 分页 (35)
- vba split (37)
- redis watch (34)
- python list sort (37)
- nvarchar2 (34)
- mysql not null (36)
- hmset (35)
- python telnet (35)
- python readlines() 方法 (36)
- munmap (35)
- docker network create (35)
- redis 集合 (37)
- python sftp (37)
- setpriority (34)
- c语言 switch (34)
- git commit (34)