有助于确定导致ElastiCache for Redis高负载原因的信息
这是2023年AWS游戏圣诞节倒数日历的第一篇文章。
首先
除了游戏开发外,Redis也可以在各种广泛场景中使用,如Leaderboard和Pub/Sub等,通过数据缓存和灵活的数据类型。ElastiCache for Redis是Redis的托管服务。由于其在一些情况下具有重要的作用,并且连接数和命令执行数量往往很高,因此经常会出现Redis(ElastiCache)的负载较大的情况。
在AWS re:Invent 2023大会上,ElastiCache Serverless正式发布,这是一个非常有趣的宣布。ElastiCache Serverless可以根据流量模式自动调整容量,使得在高负载环境下更容易进行扩展。然而,由于费用也会随着容量的增加而扩展,因此需要正确应对意外的应用程序错误或低效的实现方式导致的高负载。正确识别高负载的原因,并通过改进应用程序来在成本与性能之间取得平衡,这非常重要。
我将介绍在调查导致高负荷的原因(可能是应用程序未正确使用)和趋势时的一些建议。根据我的经验,游戏开发中,应用程序和基础设施部门可能会分开,这常常导致对这类问题的调查责任不清晰。我希望能够轻松地进行调查并顺利解决问题!
查看 CloudWatch 的指标

通常情况下,我们会从检查默认已经安装好的ElastiCache指标开始。以下指南已经准备好,可以作为注视哪些指标的参考。
在确认指标并了解负载趋势后,参考以下re:Post的问答也能制定对策。
作为对策,可以考虑将实例类型改为更大的类型,或者在运行在集群模式下的集群上添加节点。
为了确定具体成为瓶颈的命令,需要采取以下所述的方法。
将慢查询日志输出到CloudWatch Logs中
在使用Redis集群的引擎版本6.0及以上版本中,支持慢日志功能,并且您可以明确启用该功能以输出日志。您可以选择将日志传输到CloudWatch日志或Kinesis Data Firehose作为日志目标。
通过在参数组的“slowlog-log-slower-than”中设置阈值(μs),可以将执行时间超过阈值的命令输出为慢日志。如果您的调查目的是输出所有命令,可以设置为“0”来输出所有命令。

以下是将结果输出到CloudWatch Logs时的示例。
由于可以在Insights中进行筛选和排序,因此调查变得更加容易。
然而,正如上述所述,命令参数会被截断,无法识别键/值。此外,虽然可以使用CLIENT SETNAME命令给客户端添加任意名称作为客户端名称,但由于字符串”ClientName”在中途被截断,因此很难注册包含文件名和行号的长字符串,类似于堆栈跟踪信息。如果使用redis-cli命令行界面中的SHOWLOG命令,可以查看更详细的慢日志,因此同时使用此命令可能会更好。
SLOWLOG GET 1
1) 1) (integer) 62054744
2) (integer) 1701266759
3) (integer) 0
4) 1) "SET"
2) "key"
3) "value"
5) "172.31.12.235:59914"
6) "my-app#Error_at_file:///home/ec2-user/environment/adv2023/test.mjs:7:37_at_file:///home/ec2-user/environment/adv2023/test.mjs:7:92_at_runMicrotasks_(<anonymous>)_at_processTicksAndRejections_(node:internal/process/task_queues:96:5)"
Redis 监视器
Redis MONITOR是一个调试命令,它在流中返回Redis服务器处理的所有命令。它有助于理解数据库中正在发生的事情。这个命令已经实现在redis-cli中,并且也可以在ElastiCache中使用。
如果你想要确认当前流程中有哪些命令的话,把它们作为CloudWatch Logs的慢查询日志输出会更容易后续进行搜索,不过如果你更注重方便性的话,Redis MONITOR可能更好用。
请注意,在实际环境中运行时,需要注意到MONITOR会产生较高的负载,根据文档,仅运行一个MONITOR客户端可能导致吞吐量下降50%以上。
MONITOR
1701267313.987149 [0 172.31.12.235:45766] "CLIENT" "SETNAME" "my-app#Error_at_file:///home/ec2-user/environment/adv2023/test.mjs:7:37_at_file:///home/ec2-user/environment/adv2023/test.mjs:7:92_at_runMicrotasks_(<anonymous>)_at_processTicksAndRejections_(node:internal/process/task_queues:96:5)"
1701267313.987625 [0 172.31.12.235:45766] "SET" "key" "value"
1701267313.987981 [0 172.31.12.235:45766] "GET" "key"
1701267313.990282 [0 172.31.12.235:45784] "CLIENT" "SETNAME" "my-app#Error_at_file:///home/ec2-user/environment/adv2023/test.mjs:7:37_at_file:///home/ec2-user/environment/adv2023/test.mjs:7:92_at_runMicrotasks_(<anonymous>)_at_processTicksAndRejections_(node:internal/process/task_queues:96:5)"
1701267313.990723 [0 172.31.12.235:45784] "SET" "key" "value"
1701267313.991091 [0 172.31.12.235:45784] "GET" "key"
把下面的句子用中文表达出来,只需要一种选项:
….
redis-faina 社
Facebook制作的工具(当前已归档)
为了分析Redis MONITOR命令的结果并显示统计信息,有助于确定频繁执行的命令和键。这个工具仅使用Python的标准包进行实现,因此非常容易使用。然而,需要注意它是一个使用Redis MONITOR的工具。
以下是一个实际执行的例子
redis-cli -h エンドポイント MONITOR | head -n 10000 | ./redis-faina.py
Overall Stats
========================================
Lines Processed 10000
Commands/Sec 1029.13
Top Prefixes
========================================
key 1700 (17.00%)
counter 600 (6.00%)
myset 500 (5.00%)
Top Keys
========================================
mylist 4900 (49.00%)
key:__rand_int__ 1700 (17.00%)
myset 1099 (10.99%)
counter:__rand_int__ 600 (6.00%)
myset:__rand_int__ 500 (5.00%)
Top Commands
========================================
LRANGE 2000 (20.00%)
PING 1200 (12.00%)
LPUSH 1100 (11.00%)
INCR 600 (6.00%)
SET 600 (6.00%)
GET 600 (6.00%)
LPOP 600 (6.00%)
RPOP 600 (6.00%)
Command Time (microsecs)
========================================
Median 29.25
75% 44.25
90% 74.0
99% 9279.0
Heaviest Commands (microsecs)
========================================
MSET 5253914.25
LRANGE 924210.25
PING 559702.75
LPUSH 513888.25
INCR 324686.0
SET 324561.25
LPOP 320195.0
GET 308743.0
Slowest Calls
========================================
1057570.0 "MSET" "key:__rand_int__" "xxx" "key:__rand_int__" "xxx" "key:__rand_int__" "xxx" ...
1040329.0 "MSET" "key:__rand_int__" "xxx" "key:__rand_int__" "xxx" "key:__rand_int__" "xxx" ...
1040218.0 "MSET" "key:__rand_int__" "xxx" "key:__rand_int__" "xxx" "key:__rand_int__" "xxx" ...
1032906.0 "MSET" "key:__rand_int__" "xxx" "key:__rand_int__" "xxx" "key:__rand_int__" "xxx" ...
1030291.0 "MSET" "key:__rand_int__" "xxx" "key:__rand_int__" "xxx" "key:__rand_int__" "xxx" ...
86542.0 "LPOP" "mylist"
80689.0 "LPUSH" "mylist" "xxx"
78757.0 "RPOP" "mylist"
Redis流量统计
通过分析tcpdump的pcap数据并生成报告,相较于Redis MONITOR,它具有不给集群带来负载的优点,还可以输出命令传输的字节数统计。
然而,预构建的分发文件出现了404错误,如果要从源代码构建,需要安装Perl依赖包等,因此安装过程稍微有些困难。
# cpanm install
$ curl -L https://cpanmin.us | perl - --sudo App::cpanminus
$ cpanm --local-lib=~/perl5 local::lib && eval $(perl -I ~/perl5/lib/perl5/ -Mlocal::lib)
# redis-traffic-stats install
$ git clone https://github.com/hirose31/redis-traffic-stats.git
$ cd redis-traffic-stats/
# Net::Pcap のインストールでエラーが出たので、libpcap-develをインストール: sudo yum install libpcap-devel
$ cpanm --installdeps .
$ perl Build.PL
$ ./Build
$ ./Build test
$ ./Build install
例子的用法
$ tcpdump -s 65535 tcp port 6379 -w redis.pcap -i eth0 $ redis-traffic-stats -r redis.pcap
pcapfile: redis.pcap
read pcap data and rebuild TCP stream ......................................... done (41057 pkt)
process Redis protocol ............ done
# redis-traffic-stats
## Summary
* Duration:
* 2023-11-29 15:16:10 - 2023-11-29 15:16:16 (6s)
* Total Traffic:
* 1607003 bytes (267833.83 bytes/sec)
* Total Requests:
* 6486 requests (Avg 1081.00 req/sec, Peak 1621.00 req/sec)
## Top Commands
### By count
Command | Count | Pct | Req/sec
-----------------|-------:|-------:|---------:
LRANGE | 1445 | 22.28 | 240.83
LPUSH | 733 | 11.30 | 122.17
PING | 690 | 10.64 | 115.00
HSET | 396 | 6.11 | 66.00
LPOP | 393 | 6.06 | 65.50
GET | 377 | 5.81 | 62.83
SET | 371 | 5.72 | 61.83
SADD | 371 | 5.72 | 61.83
MSET | 371 | 5.72 | 61.83
INCR | 343 | 5.29 | 57.17
### By traffic
Command | Bytes | Byte/sec
-----------------|----------:|-------------:
LRANGE | 1588650 | 264775.00
LPUSH | 5131 | 855.17
PING | 2760 | 460.00
INCR | 2401 | 400.17
RPUSH | 2394 | 399.00
LPOP | 1179 | 196.50
GET | 1131 | 188.50
RPOP | 1026 | 171.00
SET | 742 | 123.67
MSET | 742 | 123.67
## Command Detail
### LRANGE
Key | Bytes | Byte/sec | Count | Pct | Req/sec
---------------------|----------:|-------------:|-------:|-------:|---------:
mylist | 1588650 | 264775.00 | 1445 | 100.00 | 240.83
### LPUSH
Key | Bytes | Byte/sec | Count | Pct | Req/sec
---------------------|----------:|-------------:|-------:|-------:|---------:
mylist | 5131 | 855.17 | 733 | 100.00 | 122.17
### PING
Key | Bytes | Byte/sec | Count | Pct | Req/sec
---------------------|----------:|-------------:|-------:|-------:|---------:
### INCR
Key | Bytes | Byte/sec | Count | Pct | Req/sec
---------------------|----------:|-------------:|-------:|-------:|---------:
counter:__rand_int__ | 2401 | 400.17 | 343 | 100.00 | 57.17
### RPUSH
Key | Bytes | Byte/sec | Count | Pct | Req/sec
---------------------|----------:|-------------:|-------:|-------:|---------:
mylist | 2394 | 399.00 | 342 | 100.00 | 57.00
### LPOP
Key | Bytes | Byte/sec | Count | Pct | Req/sec
---------------------|----------:|-------------:|-------:|-------:|---------:
mylist | 1179 | 196.50 | 393 | 100.00 | 65.50
### GET
Key | Bytes | Byte/sec | Count | Pct | Req/sec
---------------------|----------:|-------------:|-------:|-------:|---------:
key:__rand_int__ | 1131 | 188.50 | 377 | 100.00 | 62.83
### RPOP
Key | Bytes | Byte/sec | Count | Pct | Req/sec
---------------------|----------:|-------------:|-------:|-------:|---------:
mylist | 1026 | 171.00 | 342 | 100.00 | 57.00
### SET
Key | Bytes | Byte/sec | Count | Pct | Req/sec
---------------------|----------:|-------------:|-------:|-------:|---------:
key:__rand_int__ | 742 | 123.67 | 371 | 100.00 | 61.83
### MSET
Key | Bytes | Byte/sec | Count | Pct | Req/sec
---------------------|----------:|-------------:|-------:|-------:|---------:
key:__rand_int__ | 742 | 123.67 | 371 | 100.00 | 61.83
### HSET
Key | Bytes | Byte/sec | Count | Pct | Req/sec
---------------------|----------:|-------------:|-------:|-------:|---------:
myset:__rand_int__ | 396 | 66.00 | 396 | 100.00 | 66.00
### SADD
Key | Bytes | Byte/sec | Count | Pct | Req/sec
---------------------|----------:|-------------:|-------:|-------:|---------:
myset | 371 | 61.83 | 371 | 100.00 | 61.83
### SPOP
Key | Bytes | Byte/sec | Count | Pct | Req/sec
---------------------|----------:|-------------:|-------:|-------:|---------:
myset | 80 | 13.33 | 312 | 100.00 | 52.00
## Slow Commands
Time | Command
------:|------------------------------------------------------------------------
0.044 | LRANGE mylist 0 599
0.044 | LRANGE mylist 0 599
0.043 | LRANGE mylist 0 599
0.043 | SADD myset element:__rand_int__
0.043 | LRANGE mylist 0 599
0.043 | LRANGE mylist 0 599
0.043 | LRANGE mylist 0 599
0.042 | SADD myset element:__rand_int__
0.042 | LRANGE mylist 0 599
0.042 | LRANGE mylist 0 599
最后
上述的信息有助于确定ElastiCache for Redis的高负荷原因。如果还有其他有用的信息,欢迎留言或提出编辑请求!
(免责)本篇文章内容仅代表个人观点,与所属企业或组织无关。