8
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

朝日新聞社Advent Calendar 2023

Day 12

Redisクラスターで読み取りクエリをプライマリとレプリカで負荷分散したい

Last updated at Posted at 2023-12-11

はじめに

この記事は朝日新聞社 Advent Calendar 2023の12日目の記事です。🎉

Redis一般の話をしますが、ここではAWS EalastiCache for Redisを例にお話しします。

一般的なElastiCache for Redisの構成

ElastiCacheをクラスターモードで運用する場合、writerインスタンスに対し5台までのreadインスタンスを配置することが一般的と思います。

Redis構成の課題

この構成の際、レプリカインスタンス間、プライマリとレプリカインスタンス間でそれぞれ負荷分散が行われることを想定すると思います。
しかし、実際には単純にgetコマンドを発行するだけだと、クラスターエンドポイントをアプリケーションで読み込んでも負荷分散は行われません。
readインスタンスへ送られるクエリは、全てwriteインスタンスにリダイレクトされます。

使用しているElastiCacheをAmazon Cloudwatch上でメトリクスを確認すると、GetTypeCmdsがprimaryの数しか存在していないことがわかります。

スクリーンショット 2023-11-29 22.45.16.png

メトリクス上でも、読み取りのクエリは全てプライマリインスタンスに向けて発行されていそうです。

※GetTypeCmdsメトリクスは、クラスター内で発行された読み取り系コマンドの合計数を出すメトリクスです。

原因

Redisをクラスターモードで動作させる場合、クエリは全て各種シャードのプライマリに対して送られます。
そのため、レプリカに対してクエリが発行された場合はリダイレクトによってプライマリインスタンスに対して送られます。

解決策

Redisリファレンスのクラスターモードの解説にある通りですが、この挙動はREADONLYコマンドを発行することで無効化することができます。

例えば、goアプリケーションでgo-redisでの実装の場合、cluster.goClusterOptions構造体にReadonlyのプロパティがあるのでこちらを有効にしましょう。

client := redis.NewClusterClient(&redis.ClusterOptions{
    Addrs:         []string{addr},
	ReadOnly:      true, // READONLYコマンドの発行
})

なお、余談ですが、go-redisにはRouteByLatencyRouteRandomlyのオプションが用意されていて、レプリカの優先度をレイテンシ優先かランダムアクセスかで制御できます。

client := redis.NewClusterClient(&redis.ClusterOptions{
    Addrs:             []string{addr},
	ReadOnly:          true, // READONLYコマンドの発行
    // RouteByLatency: true, // READONLYコマンド発行時、レイテンシ低いレプリカにアクセス
	// RouteRandomly:  true, // READONLYコマンド発行時、ランダムにレプリカにアクセス
})

まとめ

Redisのドキュメントを読めば書いてあることではありますが、携わるプロダクトでRedisの負荷分散ができていないものがあったので、気になって調べました。

この案内はAWSのre:Postにも投稿されていましたが、私は調査して初めて知りました。
https://repost.aws/ja/knowledge-center/elasticache-redis-client-readonly

クラスターモードを有効にする際、レプリカで負荷分散したい場合はREADONLYを有効にしてみてください。

参考

おまけ

本項ではレプリカにも読み取りクエリを発行することでプライマリとの負荷分散を意図するものですが、逆にプライマリにしか意図的にクエリを発行させないコマンド(既存のREADONELYを無効化するもの)として、READWRITEコマンドも存在します。

8
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?