Redis のバッファ メカニズムは、クライアントがコマンドを送信する速度とサーバーがコマンドを処理する速度の差のバランスを取ることです。クライアントの書き込みが速すぎるか、サーバーの読み取りが遅すぎる場合、これはバッファ オーバーフローが発生すると、一連のパフォーマンス上の問題が発生します。これについては、以下で詳しく説明します。
Redis はクライアントごとに入力バッファと出力バッファを割り当てます。入力バッファにはクライアントのリクエスト コマンドが一時的に保存され、Redis メイン スレッドからコマンドが取得されます。 Redis がコマンドを処理した後、以下に示すように、結果が出力バッファに書き込まれ、出力バッファを介してクライアントに返されます
入力バッファ オーバーフローは、一般に 2 つの状況によって発生します。
データの書き込みが速すぎるか、bigkey に書き込まれたデータがデータ バッファ領域をいっぱいにします。
サーバーのデータ処理が遅すぎます。通常、メイン スレッドがブロックされ、クライアントのリクエストに正常に応答できません。
client list
を使用して、入力バッファの特定の情報を表示できます
127.0.0.1:6379> client list id=13 addr=127.0.0.1:50484 fd=7 name= age=1136 idle=1 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=26 qbuf-free=32742 obl=0 oll=0 omem=0 events=r cmd=client user=default id=14 addr=127.0.0.1:50486 fd=8 name= age=1114 idle=6 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=client user=default
各接続前のクライアントには、もう 1 つの入力バッファ情報があります。上記のコマンドは、2 つのクライアントへのローカル接続の結果です。バッファを表示するときは、主に 2 つのメモリ関連パラメータに注目します。
qbuf : 使用されているバッファの長さ (バイト単位、0 はバッファが割り当てられていないことを意味します)。
qbuf-free: バッファー内の残りの空きスペース (バイト単位)、上記のクライアントの qbuf=26、空きバッファー qbuf-free=32742、および割り当てられた合計メモリー サイズ26 32742=32768 バイト、つまり 32KB です。
入力バッファ情報の qbuf-free が非常に小さく、qbuf が非常に大きい場合は、入力バッファがオーバーフローしかけている可能性があるので注意が必要です。大量のリクエストが入力バッファに書き込まれているため、Redis の解決策はこのクライアントとの接続を閉じることで、ビジネス データに正常にアクセスできなくなります。
もう 1 つの問題は、入力バッファがクライアントごとに存在することです。すべてのクライアントの入力バッファ メモリの合計が maxmemory 設定を超えると、メモリの削除が発生し、削除されたデータの一部が再度アクセスされます。バックグラウンドデータベースから取得する必要があり、取得時間は Redis から直接読み取るよりも明らかに遅いため、これも Redis の遅延の理由です。
入力バッファ オーバーフローの本質は、バッファの容量が不足していることなので、最初のアイデアは入力バッファのサイズを拡張することです。 Redis はこれを提供しません。入力バッファ サイズの構成を変更してください。Redis では、各クライアントの入力バッファが 1G を超えることができない必要があります。これは各クライアントごとであることに注意してください。 ! ! 、クライアントの入力バッファが 1G を超えると、クライアント接続が切断されるため、これは機能しません。
その場合、クライアントからのデータのサイズとサーバーによるコマンド処理の速度のみを送信できます。クライアントは、bigkey の書き込みを避ける必要があります。bigkey には欠点が多すぎるため、通常は分割する必要があります。 、サーバー上のコマンド処理速度は、一般にメインスレッドがブロックされているかどうかに依存します。AOF ファイルの書き換え、キー値の削除、スレッドのフォークなどのブロック操作を避けるように努める必要があります。
サーバーの場合、クライアントの入力情報は通常予測できませんが、出力情報はほとんど予測可能です。たとえば、Set コマンドは単純な OK を返します。別の例は、いくつかのエラー メッセージです。Redis は、これらの定数リターン メッセージに 16 KB の固定バッファ スペースを割り当てます。つまり、出力バッファは 2 つの部分に分割されます。1 つの部分は出力バッファの固定リターン メッセージで、もう 1 つの部分は出力バッファの固定リターン メッセージです。は変数の戻りメッセージです。
出力バッファオーバーフローは3つの状況に分けられます
bigkeyなどの大容量のキー値を出力する場合。
Monitor コマンドの実行
127.0.0.1:6379> monitor OK 1652184977.609761 [0 127.0.0.1:50484] "get" "name" 1652185391.529292 [0 127.0.0.1:50484] "set" "test" "lisi" ......
モニターを実行し続けると、常に出力バッファーが占有されます。つまり、占有時間が長くなるほど、出力バッファーがオーバーフローしやすくなります。したがって、Monitor コマンドはデバッグにのみ適しています。環境では実行できず、本番環境では実行できません。
出力バッファの設定が無理です
設定内容は
持续写入的时间限制和持续写入的容量限制,当超过持续写入时间限制和容量限制,服务端也会强制关闭和客户端的连接。
客户端种类
在聊缓冲区配置时,我们需要先了解下客户端的种类,本文中强调的客户端并不是单纯指通过命令./redis-cli -c -h 127.0.0.1 -p 6379
去连接Redis服务器这类客户端称为常规客户端,我们还有通过消息订阅Redis频道的客户端,还有一种最为特殊的主从同步,从节点也是一个特殊的客户端称为从节点客户端。
配置项client-output-buffer-limit
也是针对这三种,给出了不一样的配置,如下所示
## 普通客户端配置 client-output-buffer-limit normal 0 0 0 ## 从节点客户端配置 client-output-buffer-limit replica 256mb 64mb 60 ## 消息订阅频道的客户端 client-output-buffer-limit pubsub 32mb 8mb 60 ######################配置解释###################### ## 第一个参数:代表分配给客户端的缓存大小,为0代表没有限制 ## 第二个参数:表示持续写入的最大内存,为0代表没有限制 ## 第三个参数:表示持续写入的最长时间,为0代表没有限制
普通客户端设置
普通客户端就是传输的一些普通的指令,一个指令发送完需要等待其返回后才会发送下一个指令,也就是说只要不是返回的bigkey数据,占用输出缓冲区的内存就极少,能够立即发送给客户端响应,所以一般正常客户端默认配置都是0,也就是不限制。
消息订阅频道客户端
当订阅频道产生消息后,会将消息通过输出缓冲区发送给客户端,这种属于非阻塞的方式,一瞬间可能有多个指令到达,所以需要指定缓冲区大小。
如何解决输出缓冲区溢出
到这里其实我们已经能够得到输出缓冲区溢出的解决方案了
bigkey应当避免使用。
Monitor命令只在调试的时候使用,不能应用到生产。
合理设置输出缓冲区上限、持续写入时间上限以及持续写入内存容量上限。
除了输入缓冲区和输出缓冲区外在主从集群场景下还存在两种缓冲区,我们称为复制缓冲区和复制积压缓冲区,这两个缓冲区的溢出和输入输出缓冲区稍有不同。
复制缓冲区这个名词看着很陌生,但是我们之前在聊主从同步时讲过,主从全量同步期间从节点会加载主节点的RDB文件,这时主节点同样还能写入数据,但是从节点在加载RDB文件没办法实时同步,所以Redis就为每一个从节点开辟了一片空间,用来存放主从全量同步期间产生的操作命令,这就是replication buffer,也就是复制缓冲区。
复制缓冲区什么时候会溢出呢?
当从节点在加载RDB文件这个过程中如果存在大量的写操作就会造成复制缓冲区内存溢出。
从节点加载RDB文件的时间过长。
发生溢出后,主节点会关闭与从节点的连接,导致全量同步失败。
解决复制缓冲区溢出
控制主节点实例的大小,减小生成的RDB文件,这样就能减少从节点加载RDB文件的时间,减小复制缓冲区的压力。
从节点其本质就是主节点的特殊客户端,所以使用的是输出缓冲区(也就是指replication buffer),可以设置client-output-buffer-limit replica 256mb 64mb 60
扩大缓冲区大小。
注意:主节点上的复制缓冲区会为每一个从节点分配一个,那么从节点的数量过多即使每个从节点没有达到maxmemory,但累加的结果也会给主节点带来内存压力。
复制积压缓冲区溢出
主从集群在写操作时会将操作写入复制缓冲区和复制积压缓冲区中,一旦网络发送故障后恢复连接,在2.8版本之前主从节点会进行全量同步开销非常大,所以2.8版本后还是采用了增量同步,仅仅将网络断开这段时间的操作同步给从节点,所以在网络恢复连接后从节点会将自己的复制偏移量slave_repl_offset发送给主节点,主节点将自身的写入偏移量master_repl_offset和slave_repl_offset在复制积压缓冲区中做对比得到网络断连期间的操作。
复制积压缓冲区又叫repl_backlog_buffer,是一个环形缓冲区,同步示意图如下。
复制积压缓冲区溢出其实也就是因为复制积压缓冲区是一个有限环形结构,一般主节点写入偏移量要大于从节点的读取偏移量,但如果写入偏移量覆盖了从节点的读取偏移量这就引发了复制积压缓冲区溢出。
通常、repl_backlog_size パラメータのサイズを調整し、レプリケーション バックログ バッファのサイズを拡張し、マスター ノードの書き込みオフセットを減らして、マスター ノードの読み取りオフセットをカバーします。スレーブノードのリスク。
以上がRedisのバッファ機構の分析例の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。