有助于确定导致ElastiCache for Redis高负载原因的信息

这是2023年AWS游戏圣诞节倒数日历的第一篇文章。

首先

除了游戏开发外,Redis也可以在各种广泛场景中使用,如Leaderboard和Pub/Sub等,通过数据缓存和灵活的数据类型。ElastiCache for Redis是Redis的托管服务。由于其在一些情况下具有重要的作用,并且连接数和命令执行数量往往很高,因此经常会出现Redis(ElastiCache)的负载较大的情况。

在AWS re:Invent 2023大会上,ElastiCache Serverless正式发布,这是一个非常有趣的宣布。ElastiCache Serverless可以根据流量模式自动调整容量,使得在高负载环境下更容易进行扩展。然而,由于费用也会随着容量的增加而扩展,因此需要正确应对意外的应用程序错误或低效的实现方式导致的高负载。正确识别高负载的原因,并通过改进应用程序来在成本与性能之间取得平衡,这非常重要。

 

我将介绍在调查导致高负荷的原因(可能是应用程序未正确使用)和趋势时的一些建议。根据我的经验,游戏开发中,应用程序和基础设施部门可能会分开,这常常导致对这类问题的调查责任不清晰。我希望能够轻松地进行调查并顺利解决问题!

查看 CloudWatch 的指标

Screenshot 2023-11-29 at 20.26.53.png

通常情况下,我们会从检查默认已经安装好的ElastiCache指标开始。以下指南已经准备好,可以作为注视哪些指标的参考。

 

在确认指标并了解负载趋势后,参考以下re:Post的问答也能制定对策。

 

作为对策,可以考虑将实例类型改为更大的类型,或者在运行在集群模式下的集群上添加节点。

为了确定具体成为瓶颈的命令,需要采取以下所述的方法。

将慢查询日志输出到CloudWatch Logs中

在使用Redis集群的引擎版本6.0及以上版本中,支持慢日志功能,并且您可以明确启用该功能以输出日志。您可以选择将日志传输到CloudWatch日志或Kinesis Data Firehose作为日志目标。

通过在参数组的“slowlog-log-slower-than”中设置阈值(μs),可以将执行时间超过阈值的命令输出为慢日志。如果您的调查目的是输出所有命令,可以设置为“0”来输出所有命令。

 

Screenshot 2023-11-29 at 23.09.02.png

以下是将结果输出到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的高负荷原因。如果还有其他有用的信息,欢迎留言或提出编辑请求!

(免责)本篇文章内容仅代表个人观点,与所属企业或组织无关。

bannerAds