Hiredisパッケージは、Redisプロトコルを使用してコマンドをマーシャリングし、Redisサーバーに送信します。次に、同期的に応答を待ちます。
ソケットを処理する関数は、hiredis.cファイルにあります。
int redisBufferRead(redisContext *c)
int redisBufferWrite(redisContext *c, int *done)
これらの関数では、EAGAINエラーは処理されますが、「システムコールの中断」メッセージに対応するEINTRエラーは処理されません。
その結果、hiredisが書き込みまたは(より可能性が高い)読み取り操作を実行しているときにプロセスが受信するUnixシグナルが操作を中断し、このエラーを引き起こす可能性があります。
まず、アプリケーションが受信する信号の種類を理解する必要があります。信号の性質とアプリケーションに応じて、この状況を処理するさまざまな方法があります。
- Redis呼び出しを行う前にシグナルハンドラーをマスキングまたは延期する
- シグナルをイベントループハンドラー(存在する場合)にバインドして、予期しないときにシグナルが処理されるのを回避します
- すべてのシグナルを処理するために特定のスレッドを専用にします(そしてこのスレッドでのRedis呼び出しを回避します)
- SA_RESTARTオプション(sigaction内)を使用して、中断されたシステムコールを自動的に再生するようにシステムに指示します
- 操作を再試行してください(ただし、実行できない場合があります)
個人的には、より優雅な方法で状況を処理するために、hiredisを好みます(つまり、EAGAINのようにEINTRを処理します)。
アップデート:
EAGAINエラーは通常、次の2つの状況で返されます。
クライアント側でredisSetTimeout()関数を呼び出すには、ソケットのSO_RCVTIMEOプロパティとSO_SNDTIMEOプロパティを設定するだけであることに注意してください。これは、サーバー側のアイドルタイムアウトであるRedis構成ファイルで定義されているタイムアウトとはまったく関係ありません(RedisサーバーはN秒を超えて非アクティブになっている場合に接続を閉じることができます)。
2番目の状況でEAGAINを取得するということは、Redisインスタンスが指定されたタイムアウトに対して十分に応答しないことを意味します。単にタイムアウトを増やすか、Redisサーバー側の遅延の問題をさらに調査することをお勧めします。