百度360必应搜狗淘宝本站头条
当前位置:网站首页 > IT技术 > 正文

11个提高 Redis 性能的技巧(redis 性能优化)

wptr33 2025-01-29 18:21 21 浏览

众所周知,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等命令。

查询数据时,可遵循以下原则:

  1. 首选查询数据元素的个数(涉及命令:LLEN、HLEN、SCARD、ZCARD)。
  2. 如果元素数量比较少,可以一次性查询出所有数据。
  3. 如果元素数量非常多,则批量查询数据(涉及命令: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。为什么呢?以下是总结的三个原因:

  1. 在一个连接上操作多个数据库数据时,每次都需要先执行 SELECT,这会给Redis带来额外的压力。
  2. 使用多个数据库的目的是为了根据不同的业务线来存储数据。那么为什么不将它们拆分并存储在多个实例呢?部署多个实例,拆分存储,多个业务线不会互相影响,也可以提高Redis的访问性能。
  3. Redis Cluster 只支持 db 0,如果以后想迁移 Redis Cluster,会增加迁移成本。

10. 采用读写分离+分片集群

如果我们的业务的读取请求量很大,那么我们可以部署多个从库来实现读写分离,让 Redis 的从库分担读取压力,从而提高性能。

如果我们的业务的写入请求量也非常大,单个实例已经无法支撑这么大的写入流量,那么这时候就需要使用分片集群来分担写入压力。

11. 不要启用AOF或配置AOF每秒刷盘

对于数据丢失不敏感的业务,建议不要启用AOF,避免AOF写入磁盘导致Redis性能下降。

如需确实需要启用AOF,那么建议将其配置为 appendfsynce everysec,并将数据持久化的磁盘刷新操作放到后台线程执行,以尽量减少Redis写入磁盘对性能的影响。

以上就是Redis高性能方面的实用优化,如果你非常关心Redis的性能问题,你可以结合这几个方面进行针对性的优化。当然,您还有其他好的方案,欢迎您不吝赐教。

相关推荐

redis的八种使用场景

前言:redis是我们工作开发中,经常要打交道的,下面对redis的使用场景做总结介绍也是对redis举报的功能做梳理。缓存Redis最常见的用途是作为缓存,用于加速应用程序的响应速度。...

基于Redis的3种分布式ID生成策略

在分布式系统设计中,全局唯一ID是一个基础而关键的组件。随着业务规模扩大和系统架构向微服务演进,传统的单机自增ID已无法满足需求。高并发、高可用的分布式ID生成方案成为构建可靠分布式系统的必要条件。R...

基于OpenWrt系统路由器的模式切换与网页设计

摘要:目前商用WiFi路由器已应用到多个领域,商家通过给用户提供一个稳定免费WiFi热点达到吸引客户、提升服务的目标。传统路由器自带的Luci界面提供了工厂模式的Web界面,用户可通过该界面配置路...

这篇文章教你看明白 nginx-ingress 控制器

主机nginx一般nginx做主机反向代理(网关)有以下配置...

如何用redis实现注册中心

一句话总结使用Redis实现注册中心:服务注册...

爱可可老师24小时热门分享(2020.5.10)

No1.看自己以前写的代码是种什么体验?No2.DooM-chip!国外网友SylvainLefebvre自制的无CPU、无操作码、无指令计数器...No3.我认为CS学位可以更好,如...

Apportable:拯救程序员,IOS一秒变安卓

摘要:还在为了跨平台使用cocos2d-x吗,拯救objc程序员的奇葩来了,ApportableSDK:FreeAndroidsupportforcocos2d-iPhone。App...

JAVA实现超买超卖方案汇总,那个最适合你,一篇文章彻底讲透

以下是几种Java实现超买超卖问题的核心解决方案及代码示例,针对高并发场景下的库存扣减问题:方案一:Redis原子操作+Lua脚本(推荐)//使用Redis+Lua保证原子性publicbo...

3月26日更新 快速施法自动施法可独立设置

2016年3月26日DOTA2有一个79.6MB的更新主要是针对自动施法和快速施法的调整本来内容不多不少朋友都有自动施法和快速施法的困扰英文更新日志一些视觉BUG修复就不翻译了主要翻译自动施...

Redis 是如何提供服务的

在刚刚接触Redis的时候,最想要知道的是一个’setnameJhon’命令到达Redis服务器的时候,它是如何返回’OK’的?里面命令处理的流程如何,具体细节怎么样?你一定有问过自己...

lua _G、_VERSION使用

到这里我们已经把lua基础库中的函数介绍完了,除了函数外基础库中还有两个常量,一个是_G,另一个是_VERSION。_G是基础库本身,指向自己,这个变量很有意思,可以无限引用自己,最后得到的还是自己,...

China's top diplomat to chair third China-Pacific Island countries foreign ministers' meeting

BEIJING,May21(Xinhua)--ChineseForeignMinisterWangYi,alsoamemberofthePoliticalBureau...

移动工作交流工具Lua推出Insights数据分析产品

Lua是一个适用于各种职业人士的移动交流平台,它在今天推出了一项叫做Insights的全新功能。Insights是一个数据平台,客户可以在上面实时看到员工之间的交流情况,并分析这些情况对公司发展的影响...

Redis 7新武器:用Redis Stack实现向量搜索的极限压测

当传统关系型数据库还在为向量相似度搜索的性能挣扎时,Redis7的RedisStack...

Nginx/OpenResty详解,Nginx Lua编程,重定向与内部子请求

重定向与内部子请求Nginx的rewrite指令不仅可以在Nginx内部的server、location之间进行跳转,还可以进行外部链接的重定向。通过ngx_lua模块的Lua函数除了能实现Nginx...