tencent cloud

Tencent Cloud Distributed Cache (Redis OSS-Compatible)

Redigoコネクションプール接続分散の実践

下载
聚焦模式
字号
最后更新时间: 2026-10-20 19:07:18
本文档由 AI 翻译
本文では、redigoクライアントを使用してクラウド分散キャッシュデータベース(Redis互換)に接続する際に、接続プールを改造することで接続を均等に使用し、「ホット接続」による負荷の偏りを回避する方法を説明します。

業務シナリオ

同時実行性の高いGoサービスでは、業務は通常redigo接続プールで接続を再利用してRedisにアクセスします。このとき、以下の問題がよく発生します:
接続負荷の偏り: redigo公式接続プールはキュー先頭から接続を取得し、使用済み接続を再びキュー先頭に戻すため、最も使用頻度の高い少数の接続が継続的に再利用され、その他の接続は長期間アイドル状態になります。
Proxyノードの負荷偏り: クラウド上の複数Proxyノード構成では、接続分布が不均一になると、一部のProxyノードに過大なリクエストが集中し、パフォーマンスのボトルネックになります。
拡張の効果が顕著でない: リクエストが少数の接続とノードに集中するため、インスタンスのスペックやノードを増やしても、全体のスループットは線形的に向上しにくいです。
接続プールをラウンドロビン方式に変更し(接続は使用後にキューの末尾に戻す)、接続を均等に使用できるようにすることで、上記の偏り問題を緩和し、高同時実行シーンにおける安定性とリソース使用率を向上させることができます。

背景情報

redigo公式接続プールの接続取得・返却メカニズムは以下の通りです:
公式接続プールはキュー先頭からの接続取得(popFront)のみをサポートし、使用済み接続をキュー先頭に戻します(pushFront)。
使用済みの接続をキュー先頭に戻した後、再びキュー先頭から取得するため、最も使用頻度の高い接続が継続的に再利用されます。
接続をラウンドロビン方式で使用できないため、最終的にProxy接続または負荷の不均衡問題が発生します。
この問題に対して、redigoソースコード内のpool.goファイルを変更し、pushBackメソッドを追加して、使用済み接続をキューの末尾に戻すことで、接続のラウンドロビンを実現できます。

前提条件

クラウド分散キャッシュデータベースインスタンスを作成し、インスタンスの接続アドレスとアクセスパスワードを取得しました。
Go実行環境をインストールし、プロジェクトにredigo依存関係を導入しました。
redigo依存ソースコードを変更できる条件を備えています(例えば、プライベートforkまたはvendorディレクトリで変更を管理します)。
説明:
本文のpushBackメソッドとLifoフィールドはredigo公式のものではなく、公式pool.goのカスタマイズ改造です。redigo公式接続プール(現時点のmaster時点)のidleListはpushFront、popFront、popBackメソッドのみを提供し、接続返却時にpushFront(キュー先頭に戻す)を採用するため、それ自体がLIFO(後入れ先出し)動作となり、公式にはLifo設定項目はありません。接続をFIFO(ラウンドロビン)に変更して均等に使用する必要がある場合は、本文に従ってpushBackを追加し、返却ロジックを改造する必要があります。具体的にはredigo公式ソースコードを基準とし、ご自身でコンパイルして検証してください。

操作手順

ステップ1:idleListにpushBackメソッドを追加する

pool.goでidleListにpushBackメソッドを追加し、接続をキューの末尾に追加します:
// idle connect push list back
func (l *idleList) pushBack(pc *poolConn) {
if l.count == 0 {
l.front = pc
l.back = pc
pc.prev = nil
pc.next = nil
} else {
pc.prev = l.back
l.back.next = pc
l.back = pc
pc.next = nil
}
l.count++
}

ステップ2:Pool構造体にLifo設定フィールドを追加する

Pool構造体にLifoフィールドを追加し、接続の返却位置を制御します:
// idle connection in the pool method
// True: pushBack, False: pushFront, default False
Lifo bool

ステップ3:接続返却ロジックでLifoに基づき戻す位置を判断する

接続返却(put)ロジックでは、Lifoに基づいて接続をキューの先頭に戻すか末尾に戻すかを決定します:
if p.Lifo == true {
p.idle.pushBack(pc) // キューの末尾に戻します。
} else {
p.idle.pushFront(pc) // キューの先頭に戻します(デフォルト)
}

ステップ4:接続プール初期化時にLifoを有効にする

接続プールを作成する際に、Lifoをtrueに設定し、使用済み接続をキューの末尾に戻すことで、接続のラウンドロビンと負荷分散を実現します:
// 接続プールを確立します。
redisClient = &redis.Pool{
MaxIdle: maxIdle,
MaxActive: maxActive,
IdleTimeout: MaxIdleTimeout * time.Second,
Wait: true,
Lifo: true, // trueに設定すると、使用済み接続をキューの末尾に戻します。
Dial: func() (redis.Conn, error) {
con, err := redis.Dial("tcp", conf["Host"].(string),
redis.DialPassword(conf["Password"].(string)),
redis.DialDatabase(int(conf["Db"].(int64))),
redis.DialConnectTimeout(timeout*time.Second),
redis.DialReadTimeout(timeout*time.Second),
redis.DialWriteTimeout(timeout*time.Second))
if err != nil {
return nil, err
}
return con, nil
},
}

検証方法

改造を完了し、Lifo: trueを設定した後、以下の方法で接続が均等に使用されていることを確認できます:
ビジネスが一定時間継続してリクエストを行った後、インスタンス監視を通じて各Proxyノードの接続数とリクエスト量が均衡に近づき、少数のノードに集中しなくなったかどうかを観察します。
クライアント側で接続の使用分布を統計し、リクエストが長期間少数の固定接続に集中しなくなったことを確認します。

よくあるご質問

Q:改造後にredigo依存関係をアップグレードした際、変更が失われた場合はどうすればよいですか。
サードパーティライブラリのソースコードを直接変更した後、依存関係をアップグレードする際に変更が上書きされる可能性があります。プライベートforkまたはvendorディレクトリでこの変更を管理し、十分にテストしてから本番環境に適用することをお勧めします。
Q:公式のredigoにはこの改造が含まれていますか。アップグレード後に再処理が必要ですか。
公式には備わっていません。現時点のmaster時点では、redigo公式接続プールにLifoフィールドとpushBackメソッドは存在しません。接続返却時はpushFront(キュー先頭に戻す)を採用しており、それ自体がLIFO動作となります。本文のFIFOラウンドロビン機能はカスタマイズ改造によるものであり、依存関係をアップグレードした後はこの変更を再度マージする必要があります(forkまたはvendorで管理することをお勧めします)。適用前に、使用バージョンの公式ソースコードを確認し、ご自身でコンパイルして検証してください。

帮助和支持

本页内容是否解决了您的问题?

填写满意度调查问卷,共创更好文档体验。

文档反馈