【Azure Redis 缓存 Azure Cache For Redis】Redis性能问题,发现Server Load非常的高,导致正常连接/操作不成功

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: 【Azure Redis 缓存 Azure Cache For Redis】Redis性能问题,发现Server Load非常的高,导致正常连接/操作不成功

问题描述

在正常使用Azure Redis的服务中,突然发现Redis 的CPU达到了100%, 正常的使用中发现性能问题严重。从Redis的门户图表中,观察到CPU, Connection,Lentency,Server Load都出现高的情况

CPU

Server Load

Lentency(Redis处理请求的延迟情况)

Connection(客户端连接数情况)

 

 

 

 

 

 

 

 

 

 

 

 

问题分析

根据以上的图表发现,在Connection高的情况下导致了CPU上升并持续到100%, 引起了Server Load比较高(有时达到100%),从而导致在整个Redis的延迟升高。

在Redis创建一个新的连接时,是非常昂贵的高消耗操作。同时在Azure中,每一种定价级别的Redis都有连接数的限制,如果达到限制都会导致性能问题。而根据Reids的官方文档说明,当前连接数就是因为超过了最大上限。

如基本层的连接数限制为(https://www.azure.cn/pricing/details/cache/)

缓存名称 缓存大小 基本 网络性能 客户端连接数量
C0 250 MB ¥0.14片/节点/小时(约¥104.16 /月) 256
C1 1 GB ¥0.35片/节点/小时(约¥260.40 /月) 中等 1000
C2 2.5 GB ¥0.57片/节点/小时(约¥424.08 /月) 中等 2000
C3 6 GB ¥1.14片/节点/小时(约 ¥848.16 /月) 5000
C4 13 GB ¥1.33片/节点/小时(约 ¥989.52 /月) 中等 10000
C5 26 GB ¥2.66片/节点/小时(约 ¥1979.04 /月) 15000
C6 53 GB ¥5.31片/节点/小时(约¥3950.64 /月) 最高 20000

 

 

 

 

 

 

 

 

 

 

而在处理请求的并发和性能上,可以参考(https://docs.azure.cn/zh-cn/azure-cache-for-redis/cache-planning-faq#azure-cache-for-redis-performance):

定价层 大小 CPU 核心数 可用带宽 1 KB 值大小 1 KB 值大小
标准缓存大小     兆位/秒(Mb/秒)/兆字节/秒(MB/秒) 非 SSL 请求数/秒 (RPS) SSL 请求数/秒 (RPS)
C0 250 MB 共享 100/12.5 15,000 7,500
C1 1 GB 1 500/62.5 38,000 20,720
C2 2.5 GB 2 500/62.5 41,000 37,000
C3 6 GB 4 1000/125 100,000 90,000
C4 13 GB 2 500/62.5 60,000 55,000
C5 26 GB 4 1,000 / 125 102,000 93,000
C6 53 GB 8 2,000 / 250 126,000 120,000

 

 

 

 

 

 

 

 

 

 

 

解决办法

使用连接池来改善连接问题, 如JedisPool,可以参考GitHub中的说明:https://gist.github.com/JonCole/925630df72be1351b21440625ff2671f#use-jedispool, (如链接不可访问,可以点击[转] Azure Redis Best Practices - Java)参考示例代码:

9     private static JedisPool pool;
 15     private static JedisPoolConfig config;
 16
 17     // Should be called exactly once during App Startup logic.
 18     public static void initializeSettings(String host, int port, String password, int connectTimeout, int operationTimeout) {
 19         Redis.host = host;
 20         Redis.port = port;
 21         Redis.password = password;
 22         Redis.connectTimeout = connectTimeout;
 23         Redis.operationTimeout = operationTimeout;
 24     }
 25
 26     // MAKE SURE to call the initializeSettings method first
 27     public static JedisPool getPoolInstance() {
 28         if (pool == null) { // avoid synchronization lock if initialization has already happened
 29             synchronized(staticLock) {
 30                 if (pool == null) { // don't re-initialize if another thread beat us to it.
 31                     JedisPoolConfig poolConfig = getPoolConfig();
 32                     boolean useSsl = port == 6380 ? true : false;
 33                     int db = 0;
 34                     String clientName = "MyClientName"; // null means use default
 35                     SSLSocketFactory sslSocketFactory = null; // null means use default
 36                     SSLParameters sslParameters = null; // null means use default
 37                     HostnameVerifier hostnameVerifier = new SimpleHostNameVerifier(host);
 38                     pool = new JedisPool(poolConfig, host, port, connectTimeout,operationTimeout,password, db,
 39                             clientName, useSsl, sslSocketFactory, sslParameters, hostnameVerifier);
 40                 }
 41             }
 42         }
 43         return pool;
 44     }
 45
 46     public static JedisPoolConfig getPoolConfig() {
 47         if (config == null) {
 48             JedisPoolConfig poolConfig = new JedisPoolConfig();
 49
 50             // Each thread trying to access Redis needs its own Jedis instance from the pool.
 51             // Using too small a value here can lead to performance problems, too big and you have wasted resources.
 52             int maxConnections = 200;
 53             poolConfig.setMaxTotal(maxConnections);
 54             poolConfig.setMaxIdle(maxConnections);
 55
 56             // Using "false" here will make it easier to debug when your maxTotal/minIdle/etc settings need adjusting.
 57             // Setting it to "true" will result better behavior when unexpected load hits in production
 58             poolConfig.setBlockWhenExhausted(true);
 59
 60             // How long to wait before throwing when pool is exhausted
 61             poolConfig.setMaxWaitMillis(operationTimeout);
 62
 63             // This controls the number of connections that should be maintained for bursts of load.
 64             // Increase this value when you see pool.getResource() taking a long time to complete under burst scenarios
 65             poolConfig.setMinIdle(50);
 66
 67             Redis.config = poolConfig;
 68         }
 69
 70         return config;
 71     }
114 }

如PHP, NodeJS, ASP.Net的代码,都可以在以上的GitHub中找到示例代码。

 

同时,也非常推荐在代码中使用Lazy模式。

Reconnecting with Lazy<T> pattern

We have seen a few rare cases where StackExchange.Redis fails to reconnect after a connection blip (for example, due to patching). Restarting the client or creating a new ConnectionMultiplexer will fix the issue. Here is some sample code that still uses the recommended Lazy<ConnectionMultiplexer>pattern while allowing apps to force a reconnection periodically. Make sure to update code calling into the ConnectionMultiplexer so that they handle any ObjectDisposedException errors that occur as a result of disposing the old one.

1 using System;
  2 using System.Threading;
  3 using StackExchange.Redis;
  4
  5 static class Redis
  6 {
 21     static string connectionString = "TODO: CALL InitializeConnectionString() method with connection string";
 22     static Lazy<ConnectionMultiplexer> multiplexer = CreateMultiplexer();
 23
 24     public static ConnectionMultiplexer Connection { get { return multiplexer.Value; } }
 25
 93
 94     private static Lazy<ConnectionMultiplexer> CreateMultiplexer()
 95     {
 96         return new Lazy<ConnectionMultiplexer>(() => ConnectionMultiplexer.Connect(connectionString));
 97     }

参考资料

Redis Best Practices: https://gist.github.com/JonCole/925630df72be1351b21440625ff2671f#reuse-connections (如链接不可访问,可以点击[转]Azure Redis Best Practices - PHP)

Azure Redis 缓存性能: https://docs.azure.cn/zh-cn/azure-cache-for-redis/cache-planning-faq#azure-cache-for-redis-performance

Reuse Connections: https://gist.github.com/JonCole/925630df72be1351b21440625ff2671f#php

Reuse Connections

The most common problem we have seen with PHP clients is that they either don't support persistent connections or the ability to reuse connections is disabled by default. When you don't reuse connections, it means that you have to pay the cost of establishing a new connection, including the SSL/TLS handshake, each time you want to send a request. This can add a lot of latency to your request time and will manifest itself as a performance problem in your application. Additionally, if you have a high request rate, this can cause significant CPU churn on both the Redis client-side and server-side, which can result in other issues.

As an example, the Predis Redis client has a "persistent" connection property that is false by default. Setting the "persistent" property to true will should improve behavior drastically.

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
2月前
|
缓存 NoSQL 关系型数据库
美团面试:MySQL有1000w数据,redis只存20w的数据,如何做 缓存 设计?
美团面试:MySQL有1000w数据,redis只存20w的数据,如何做 缓存 设计?
美团面试:MySQL有1000w数据,redis只存20w的数据,如何做 缓存 设计?
|
2月前
|
缓存 NoSQL Java
Redis+Caffeine构建高性能二级缓存
大家好,我是摘星。今天为大家带来的是Redis+Caffeine构建高性能二级缓存,废话不多说直接开始~
303 0
|
2月前
|
消息中间件 缓存 NoSQL
基于Spring Data Redis与RabbitMQ实现字符串缓存和计数功能(数据同步)
总的来说,借助Spring Data Redis和RabbitMQ,我们可以轻松实现字符串缓存和计数的功能。而关键的部分不过是一些"厨房的套路",一旦你掌握了这些套路,那么你就像厨师一样可以准备出一道道饕餮美食了。通过这种方式促进数据处理效率无疑将大大提高我们的生产力。
112 32
|
2月前
|
缓存 NoSQL Java
Redis:现代服务端开发的缓存基石与电商实践-优雅草卓伊凡
Redis:现代服务端开发的缓存基石与电商实践-优雅草卓伊凡
69 5
Redis:现代服务端开发的缓存基石与电商实践-优雅草卓伊凡
|
3月前
|
云安全 NoSQL 安全
【Azure Redis】关于Redis的两个安全漏洞在Azure Redis是否修复问题:CVE-2024-51741 和 CVE-2024-46981
本文探讨了两个 Redis 漏洞(CVE-2024-51741 和 CVE-2024-46981)在 Azure Redis 上是否存在安全风险。CVE-2024-51741 可能因格式错误的 ACL 触发拒绝服务,而 CVE-2024-46981 或因恶意 Lua 脚本导致远程代码执行。目前 Azure Redis 使用版本 6.0,不受上述漏洞影响,且 Azure 云服务会及时修复漏洞以确保安全。文章强调 Azure 遵循严格的安全标准,为用户提供可靠保障。
141 4
|
4月前
|
缓存 监控 NoSQL
Redis--缓存击穿、缓存穿透、缓存雪崩
缓存击穿、缓存穿透和缓存雪崩是Redis使用过程中可能遇到的常见问题。理解这些问题的成因并采取相应的解决措施,可以有效提升系统的稳定性和性能。在实际应用中,应根据具体场景,选择合适的解决方案,并持续监控和优化缓存策略,以应对不断变化的业务需求。
193 29
|
4月前
|
缓存 NoSQL Java
Redis应用—8.相关的缓存框架
本文介绍了Ehcache和Guava Cache两个缓存框架及其使用方法,以及如何自定义缓存。主要内容包括:Ehcache缓存框架、Guava Cache缓存框架、自定义缓存。总结:Ehcache适合用作本地缓存或与Redis结合使用,Guava Cache则提供了更灵活的缓存管理和更高的并发性能。自定义缓存可以根据具体需求选择不同的数据结构和引用类型来实现特定的缓存策略。
216 16
Redis应用—8.相关的缓存框架
|
3月前
|
人工智能 缓存 NoSQL
Redis 与 AI:从缓存到智能搜索的融合之路
Redis 已从传统缓存系统发展为强大的 AI 支持平台,其向量数据库功能和 RedisAI 模块为核心,支持高维向量存储、相似性搜索及模型服务。文章探讨了 Redis 在实时数据缓存、语义搜索与会话持久化中的应用场景,并通过代码案例展示了与 Spring Boot 的集成方式。总结来看,Redis 结合 AI 技术,为现代应用提供高效、灵活的解决方案。
|
7月前
|
存储 缓存 NoSQL
解决Redis缓存数据类型丢失问题
解决Redis缓存数据类型丢失问题
277 85
|
4月前
|
存储 缓存 NoSQL
Redis缓存设计与性能优化
Redis缓存设计与性能优化涵盖缓存穿透、击穿、雪崩及热点key重建等问题。针对缓存穿透,可采用缓存空对象或布隆过滤器;缓存击穿通过随机设置过期时间避免集中失效;缓存雪崩需确保高可用性并使用限流熔断组件;热点key重建利用互斥锁防止大量线程同时操作。此外,开发规范强调键值设计、命令使用和客户端配置优化,如避免bigkey、合理使用批量操作和连接池管理。系统内核参数如vm.swappiness、vm.overcommit_memory及文件句柄数的优化也至关重要。慢查询日志帮助监控性能瓶颈。
129 9
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等

登录插画

登录以查看您的控制台资源

管理云资源
状态一览
快捷访问