【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
目录
打赏
0
0
0
0
203
分享
相关文章
Redis--缓存击穿、缓存穿透、缓存雪崩
缓存击穿、缓存穿透和缓存雪崩是Redis使用过程中可能遇到的常见问题。理解这些问题的成因并采取相应的解决措施,可以有效提升系统的稳定性和性能。在实际应用中,应根据具体场景,选择合适的解决方案,并持续监控和优化缓存策略,以应对不断变化的业务需求。
104 29
Redis应用—8.相关的缓存框架
本文介绍了Ehcache和Guava Cache两个缓存框架及其使用方法,以及如何自定义缓存。主要内容包括:Ehcache缓存框架、Guava Cache缓存框架、自定义缓存。总结:Ehcache适合用作本地缓存或与Redis结合使用,Guava Cache则提供了更灵活的缓存管理和更高的并发性能。自定义缓存可以根据具体需求选择不同的数据结构和引用类型来实现特定的缓存策略。
125 16
Redis应用—8.相关的缓存框架
Redis 与 AI:从缓存到智能搜索的融合之路
Redis 已从传统缓存系统发展为强大的 AI 支持平台,其向量数据库功能和 RedisAI 模块为核心,支持高维向量存储、相似性搜索及模型服务。文章探讨了 Redis 在实时数据缓存、语义搜索与会话持久化中的应用场景,并通过代码案例展示了与 Spring Boot 的集成方式。总结来看,Redis 结合 AI 技术,为现代应用提供高效、灵活的解决方案。
Redis原理—5.性能和使用总结
本文详细探讨了Redis的阻塞原因、性能优化、缓存相关问题及数据库与缓存的一致性问题。同时还列举了不同缓存操作方案下的并发情况,帮助读者理解并选择合适的缓存管理策略。最终得出结论,在实际应用中应尽量采用“先更新数据库再删除缓存”的方案,并结合异步重试机制来保证数据的一致性和系统的高性能。
Redis原理—5.性能和使用总结
Redis缓存设计与性能优化
Redis缓存设计与性能优化涵盖缓存穿透、击穿、雪崩及热点key重建等问题。针对缓存穿透,可采用缓存空对象或布隆过滤器;缓存击穿通过随机设置过期时间避免集中失效;缓存雪崩需确保高可用性并使用限流熔断组件;热点key重建利用互斥锁防止大量线程同时操作。此外,开发规范强调键值设计、命令使用和客户端配置优化,如避免bigkey、合理使用批量操作和连接池管理。系统内核参数如vm.swappiness、vm.overcommit_memory及文件句柄数的优化也至关重要。慢查询日志帮助监控性能瓶颈。
73 9
缓存与数据库的一致性方案,Redis与Mysql一致性方案,大厂P8的终极方案(图解+秒懂+史上最全)
缓存与数据库的一致性方案,Redis与Mysql一致性方案,大厂P8的终极方案(图解+秒懂+史上最全)
解决Redis缓存数据类型丢失问题
解决Redis缓存数据类型丢失问题
230 85
Redis,分布式缓存演化之路
本文介绍了基于Redis的分布式缓存演化,探讨了分布式锁和缓存一致性问题及其解决方案。首先分析了本地缓存和分布式缓存的区别与优劣,接着深入讲解了分布式远程缓存带来的并发、缓存失效(穿透、雪崩、击穿)等问题及应对策略。文章还详细描述了如何使用Redis实现分布式锁,确保高并发场景下的数据一致性和系统稳定性。最后,通过双写模式和失效模式讨论了缓存一致性问题,并提出了多种解决方案,如引入Canal中间件等。希望这些内容能为读者在设计分布式缓存系统时提供有价值的参考。感谢您的阅读!
156 6
Redis,分布式缓存演化之路
|
2月前
|
Redis Plus 来了,性能炸裂!
Redis Plus 来了,性能炸裂!
100 21
在资源加载优化中,如何利用浏览器缓存提升性能?
通过以上这些方法,可以有效地利用浏览器缓存来提升资源加载的性能,减少网络请求次数,提高用户体验和应用的响应速度。同时,需要根据具体的应用场景和资源特点进行灵活调整和优化,以达到最佳的效果。此外,随着技术的不断发展和变化,还需要持续关注和学习新的缓存优化方法和策略。
145 53

热门文章

最新文章

AI助理

你好,我是AI助理

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