问题描述

在正常使用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 Practiceshttps://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.

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

  1. 【Azure Redis 缓存 Azure Cache For Redis】如何设置让Azure Redis中的RDB文件暂留更久(如7天)

    问题描述 Azure Redis和所有的Redis服务一样,可以让你保留存储在Redis中的数据.以防万一在Redis服务器出现故障的时候能尽可能小的减少数据的损失.在Azure Redis服务中,默 ...

  2. 【Azure Redis 缓存 Azure Cache For Redis】Azure Redis由低级别(C)升级到高级别(P)的步骤和注意事项, 及对用户现有应用的潜在影响,是否需要停机时间窗口,以及这个时间窗口需要多少的预估问题

    问题描述 由于Azure Redis的性能在不同级别表现不同,当需要升级/缩放Redis的时候,从使用者的角度,需要知道有那些步骤? 注意事项? 潜在影响?停机事件窗口? 升级预估时间? 解决方案 从 ...

  3. spring boot redis 缓存(cache)集成

    Spring Boot 集成教程 Spring Boot 介绍 Spring Boot 开发环境搭建(Eclipse) Spring Boot Hello World (restful接口)例子 sp ...

  4. 【Azure Redis 缓存 Azure Cache For Redis】在创建高级层Redis(P1)集成虚拟网络(VNET)后,如何测试VNET中资源如何成功访问及配置白名单的效果

    当使用Azure Redis高级版时候,为了能更好的保护Redis的安全,启用了虚拟网路,把Redis集成在Azure中的虚拟网络,只能通过虚拟网络VENT中的资源进行访问,而公网是不可以访问的.但是 ...

  5. 【Azure Redis 缓存 Azure Cache For Redis】使用Redis自带redis-benchmark.exe命令测试Azure Redis的性能

    问题描述 关于Azure Redis的性能问题,在官方文档中,可以查看到不同层级Redis的最大连接数,每秒处理请求的性能. 基本缓存和标准缓存 C0 (250 MB) 缓存 - 最多支持 256 个 ...

  6. 【Azure Redis 缓存 Azure Cache For Redis】Redis出现 java.net.SocketTimeoutException: Read timed out 异常

    问题描述 在使用Azure Redis时,遇见Read Timed out异常, Redis的客户端使用的时jedis.问题发生时,执行redis部分指令出错,大部分get指令,set指令能正常执行. ...

  7. 【Azure Redis 缓存 Azure Cache For Redis】当使用Jedis客户端连接Redis时候,遇见JedisConnectionException: Could not get a resource from the pool / Redis connection lost

    问题情形 当在执行Redis一直指令时,有可能会遇见如下几种错误: 1) redis.clients.jedis.exceptions.JedisConnectionException: Could ...

  8. 【Azure Redis 缓存】Windows版创建 Redis Cluster 实验 (精简版)

    简介 学习Redis Cluster的第一步,即本地搭建Redis Cluster.但是在Redis的官方文档中,是介绍在Linux系统中搭建Redis Cluster.本文主要介绍在Windows系 ...

  9. Redis缓存篇(一)Redis是如何工作的

    Redis提供了高性能的数据存取功能,所以广泛应用在缓存场景中,既能有效地提升业务应用的响应速度,还可以避免把高并发压力发送到数据库层. 因为Redis用作缓存的普遍性以及它在业务应用中的重要作用,所 ...

随机推荐

  1. 学习 | less入门

    最近在写css的时候,发现自己写的css特别长,觉得自己写的特别low,所以为了加快自己的开发效率,又重新温习了less,下面就是我学习less的过程. less是不能被浏览器识别的,要转换成css, ...

  2. 4.Strom-可靠性保证

  3. 种子爆破&[GWCTF 2019]枯燥的抽奖

    伪随机数的爆破,种子爆破 做到了一道题,就是有个伪随机数爆破的漏洞,当时尽管是看到了这两个敏感的函数,但是先去看其他的了,没有看到什么漏洞,所以我当时是准备直接强行爆破,之后看到使用伪随机数爆破的方式 ...

  4. JUC 常用4大并发工具类

    什么是JUC? JUC就是java.util.concurrent包,这个包俗称JUC,里面都是解决并发问题的一些东西 该包的位置位于java下面的rt.jar包下面 4大常用并发工具类: Count ...

  5. MySQL表关系总结

    一对多关系  : 一对多关系是关系数据库中两个表之间的一种关系,该关系中第一个表中的单个行可以与第二个表中的一个或多个行相关,但第二个表中的一个行只可以与第一个表中的一个行相关. 一对多关系,一般是一 ...

  6. 高并发场景-请求合并(二)揭秘HystrixCollapser-利用Queue和线程池异步实现

    背景 在互联网的高并发场景下,请求会非常多,但是数据库连接池比较少,或者说需要减少CPU压力,减少处理逻辑的,需要把单个查询,用某些手段,改为批量查询多个后返回. 如:支付宝中,查询"个人信 ...

  7. JMeter Websocket 二进制Binary压力测试或接口测试

    背景 最近在做游戏项目,做好java服务端,需要本地调试Websock服务,并且是二进制binary形式传输,网上的很多都是text形式传输的测试页面,所以不符合要求.为了解决websocket的二进 ...

  8. CSS实现图片圆角显示

    问题描述 在自定义博客园侧边栏公告时,想增加博客头像,但图片默认显示成是方形的,不是很好看,想着改成圆角显示会漂亮些 解决方案 增加css样式 border-radius:25px; 上面的像素值根据 ...

  9. 上部:问道 | R语言数据分析(北京邮电大学)自整理笔记

    第1章 气象万千 数以等观 数据分析:发现数据背后的规律 等号的重要性,建立模型 第2章所谓学习.归类而已 2.1所谓学习,归类而已(1) ps:机器学习只是归归类? 有监督学习--分类:无监督学习- ...

  10. 独立看第一个C++程序到最终结果log----2019-04-16

    (如果一个人夸你,千万别相信,一个人真优秀是不需要说出来的,所以别人夸你的时候也是自己最松懈的时候,千万不能飘,只能说明自己不是很差而已,世界上优秀的人很多,一直优秀到最后的人却是凤毛菱角. 如果一个 ...