问题描述

在正常使用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. DataStax Bulk Loader教程(一)

    DataStax Bulk Loader - dsbulk是在DSE 6 引入的一种新的批量加载方法.(点击这里下载DataStax Bulk Loader). 它提供了将数据加载(load)到Dat ...

  2. 回归 | js实用代码片段的封装与总结(持续更新中...)

      上一次更博还是去年10月28号了,截至今天已经有整整4个月没有更新博客了,没更新博客不是代表不学了,期间我已经用vue做了两个项目,微信小程序做了一个项目,只是毕竟找到工作了,想偷偷懒,你懂的. ...

  3. 【大数据】MapReduce开发小实战

    Before:前提:hadoop集群应部署完毕. 一.实战科目:做一个Map Reduce分布式开发,开发内容为统计文件中的单词出现次数. 二.战前准备 1.本人在本地创建了一个用于执行MR的的文件, ...

  4. Element-UI:级联选择器:Cannot read property 'level' of null"

    当级联选择时如果其选择内容需要动态变化时,如果没有选择就不会报错的:而当做出选择后又要动态变化级联选择器内容时,就会报错/ 错误:这个错误的原因是当选择后,再更新内容时,选择器仍会关联原来的数据,导致 ...

  5. 机器学习-线性规划(LP)

    线性规划问题 首先引入如下的问题: 假设食物的各种营养成分.价格如下表: Food Energy(能量) Protein(蛋白质) Calcium(钙) Price Oatmeal(燕麦) 110 4 ...

  6. kubernetes的思考

    初识k8s kubernetes,从接触到今年6月接触到现在有3个月了,严格来说是断断续续的接触,没有一直持续学习.在未接触之前,这个技术对我来说,有点像传说,运维同行对此评价普遍是比较难懂,概念庞大 ...

  7. keras中的mask操作

    使用背景 最常见的一种情况, 在NLP问题的句子补全方法中, 按照一定的长度, 对句子进行填补和截取操作. 一般使用keras.preprocessing.sequence包中的pad_sequenc ...

  8. spark源码分析, 任务反序列化及执行

    1 ==> 接受消息,org.apache.spark.executor.CoarseGrainedExecutorBackend#receive case LaunchTask(data) = ...

  9. 中秋礼物!开源即时通信GGTalk安卓版全新源码!

    经过连续两个多月的努力(开发.调试.测试.改bug),我们终于赶在中秋国庆之前能把全新的GGTalk Android版本献给大家. 4年之前我们就推出了GGTalk Android的第一个版本,但是功 ...

  10. Centos-系统内存信息-free

    free 显示系统内存信息,包括物理内存.虚拟内存.共享内存和系统缓存 相关选项 -b 以字节byte为单位显示内存使用情况 -k  以k为单位显示内存使用情况 -m 以MB为单位显示内存使用情况 - ...