キャッシュのためにRedisクラスタを使う方法
TLDR: If you are already familiar with Redis and it's just looking for a way to spin-up a fully configured Redis Cluster using Docker, here is the Github repo. Just clone this repo, go to your terminal, run
docker-compose up
and you should be good to go.
Redisとは
Redisはキーバリューストアです.ラフな条件では、それはデータベースのように動作しますが、それはメモリにデータを保持します.つまり、読み込みと書き込みは、リレーショナルデータベースと比較して、より高速なオーダーですPostgreSQL. REDISがリレーショナルデータベースに取って代わらないことに言及することは重要です.それは独自のユースケースを持っています、そして、我々はこのポストで彼らのいくつかを調査します.
Redisの詳細については、彼らのウェブサイトをご覧くださいhere. そこには良いドキュメントとどのようにあなたのマシンにインストールする方法を見つける.しかし、我々はこのポストの間にデモを構築する予定ですDocker and docker-compose それはスピンし、あなたのために全体のRedisクラスタを構成します.必要な唯一のものはDockerです.
キャッシュのためのREDISの使用
ある種のデータへの高速アクセスが必要な場合は、このデータをできるだけアプリケーション層に近づける方法を考える必要があります.データ量が十分小さい場合は、このデータをローカルメモリに保持するのが一般的です.しかし、私たちがWebアプリケーションについて話し、特に無条件で、潜在的に複数のサーバで実行できるものについて話をすると、クラスタ内の他のサーバがこの同じデータに素早くアクセスできることを確認するのと同様に、必要なデータが存在することを保証することはできません.
これは、データベースが便利です.私たちは中央の場所にこのデータを書くことができます、そして、他のサーバーは彼らが必要とするときはいつでも、このデータを得ることができます.いくつかのデータベースの問題は、あなたが本当に燃える高速アクセスを必要とするならば、それらのいくつかは弾丸速度でそれを届けることができないでしょう.Redisは一般的にデータの特定のビットへの高速かつ信頼性の高いアクセスを必要とするたびにデータベースへの移動です.また、期限切れのときに自動的に削除されるように、期限切れのポリシーをそのデータに設定する方法も用意しています.
REDISは通常、保存するための良い選択です.
どのようなクラスタを使用するポイントですか?
通常、単一のサーバーインスタンスで起動するのが一般的です.おそらく、データベースサーバに接続されていて、おそらく長い間、サーバーを接続できます.しかし、一度、さまざまな国と時折別の大陸間でアプリケーションをスケールする必要があります、それはおそらくあなたのアプリケーションは24日、週7日利用できるようにする必要があることを意味します.また、ロバスト性と信頼性をアプリケーションに埋め込む必要があります.
ネットワーク内の問題や故障したハードウェアのために、データベースサーバのいずれかが下がったときに何が起こるかを考える必要があります.あなたが1つのインスタンスだけを持っているならば、あなたは水で死んでいます.バックアップがある場合は、新しいインスタンスを回転させることができるまでの時間がかかるだろう、すべてのあなたの標準に設定し、バックアップを復元し、ビジネスでそれを戻す.
あなたのアプリケーションがミッションクリティカルであるならば、あなたは数時間の間オフラインになる余裕がありません.一部のアプリケーションでも、全体の年の数分でオフラインにすることはできません.これは、そのような問題が発生したときにレプリカを持つクラスタがあなたの肌を保存できる場所です.
Redisクラスタは、データが自動的に信頼性と可用性の高いレベルを与える複数のREDISインスタンス間で共有されることを確認します.これらのインスタンスのいずれかが何らかの種類の失敗を経験した場合、他のノードは、アプリケーションに対して正常にコンテンツを提供することができます.
Redisクラスタの回転
私は最近、1つのRedisインスタンスを使用してクラスタからの大規模なWebアプリケーションを移動しましたmultiple shards , 複数のレプリカを含む.私たちがクラスタ構成全体を提供するAWSインフラストラクチャを使用している間、私は単にすべてが生産で働くと信じることができませんでした.私は開発中にRedisクラスタをサポートすることができたことを確認しなければならなかったので、いくつかのREDISコンテナを配布し、自動的にクラスタを形成するためのセットアップを作成しました.
アプリケーションからRedisに接続するには、それを実行できるライブラリが必要です(そうでなければホイールを再起動する必要があります).使っている間IORedis このデモでNODEJSアプリケーションの場合は、別の言語を使用している場合は、別のコネクタを探す必要がありますLettuce for Java またはgo-redis for Go .
The entire setup is ready for you in this Github repository here, so you don't have to worry about creating anything from scratch. You can clone it and give it a spin while we will be walking through the files from this repo along the rest of this blogpost.
Dockerfileの作成
私たちはDockerHubから利用できる標準的なREDISイメージを使用している間、いくつかのREDISコンテナを紡ぎます.それは我々がクラスタを形成することができる方法でREDISにコマンドを出すことができる特別なコンテナーを構築するところです.
アット
redis/Dockerfile
次のコンテンツがあります.FROM redis:latest
COPY ./entrypoint.sh /entrypoint.sh
RUN chmod 755 /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
REDISに基づいてカスタムDockerイメージを構築するために、このDockerFileを使用します.ここの秘密のソースは、実際に redis/entrypoint.sh
. このスクリプトを見てみましょう.#!/bin/sh
# Using the redis-cli tool available as default in the Redis base image
# we need to create the cluster so they can coordinate with each other
# which key slots they need to hold per shard
# wait a little so we give some time for the Redis containers
# to spin up and be available on the network
sleep 5
# redis-cli doesn't support hostnames, we must match the
# container IP addresses from our docker-compose configuration.
# `--cluster-replicas 1` Will make sure that every master
# node will have its replica node.
echo "yes" | redis-cli --cluster create \
173.18.0.2:6379 \
173.18.0.3:6379 \
173.18.0.4:6379 \
173.18.0.5:6379 \
173.18.0.6:6379 \
173.18.0.7:6379 \
--cluster-replicas 1
echo "🚀 Redis cluster ready."
ここで我々はredis-cli
コマンドを発行する.このコマンドはクラスタを作成し、このスクリプトを起動するときに到達できる特定のREDISインスタンスを指しています.私たちはハードコード化されたIPアドレスを使用していますdocker-compose.yml
後でファイル.このクラスタは3シャードで構成されている.各シャードはすべての書き込みに対して責任があるマスターノードを持っていますが、データのコピーを保持するレプリカノードもあります.Redisクラスタシャードは最大500レプリカ(少なくともAWSで)を持つことができます.現在のマスターが利用できなくなるならば、複製ノードは引き継ぐ力とマスターノードになります.
今、我々の中に
redis
フォルダにもredis.conf
. このファイルはそれぞれのRedisコンテナにコピーされ、REDISインスタンスをクラスタの一部として動作させるように指示します.その内容を見てみましょう.# Custom config file to enable cluster mode
# on all Redis instances started via Docker
port 6379
cluster-enabled yes
# The cluster file is created and managed by Redis
# We just need to declare it here
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
そこにはあまり行かない.重要な部分はcluster-enabled yes
これにより、Redisインスタンスがクラスタの一部として動作することができます.我々は今、いくつかのredisコンテナをスピンして、彼らがお互いに話すことを確認する方法が必要です.我々のプロジェクトのルートフォルダでdocker-compose.yml
. 見てみましょうvolumes:
redis_1_data: {}
redis_2_data: {}
redis_3_data: {}
redis_4_data: {}
redis_5_data: {}
redis_6_data: {}
# This volume is specific for the demo Express application
# built in this repo. You probably won't need that on your own setup.
node_modules: {}
services:
app:
container_name: express_app
image: express_app
build:
context: .
environment:
PORT: 4000
NODE_ENV: production
REDIS_CLUSTER_URLS: 'redis_1:6379,redis_2:6379,redis_3:6379,redis_4:6379,redis_5:6379,redis_6:6379'
volumes:
- .:/app
- node_modules:/app/node_modules
command: [ "npm", "run", "dev" ]
depends_on:
- redis_1
- redis_2
- redis_3
- redis_4
- redis_5
- redis_6
- cluster_initiator
ports:
- "4000:4000"
stdin_open: true
networks:
redis_cluster_net:
ipv4_address: 173.18.0.10
# Here we have six Redis containers with Cluster mode enabled,
# three of them will work as master nodes and each one of
# will have a replica, so in case of failures, the replica becomes the master.
# They are configured by the `cluster_initiator` container.
redis_1:
image: 'redis:latest'
container_name: redis_1
ports:
- "6379"
volumes:
- redis_1_data:/data
- ./redis/redis.conf:/usr/local/etc/redis/redis.conf
command: [ "redis-server", "/usr/local/etc/redis/redis.conf" ]
networks:
redis_cluster_net:
ipv4_address: 173.18.0.2
redis_2:
image: 'redis:latest'
container_name: redis_2
ports:
- "6379"
volumes:
- redis_2_data:/data
- ./redis/redis.conf:/usr/local/etc/redis/redis.conf
command: [ "redis-server", "/usr/local/etc/redis/redis.conf" ]
networks:
redis_cluster_net:
ipv4_address: 173.18.0.3
redis_3:
image: 'redis:latest'
container_name: redis_3
ports:
- "6379"
volumes:
- redis_3_data:/data
- ./redis/redis.conf:/usr/local/etc/redis/redis.conf
command: [ "redis-server", "/usr/local/etc/redis/redis.conf" ]
networks:
redis_cluster_net:
ipv4_address: 173.18.0.4
redis_4:
image: 'redis:latest'
container_name: redis_4
ports:
- "6379"
volumes:
- redis_4_data:/data
- ./redis/redis.conf:/usr/local/etc/redis/redis.conf
command: [ "redis-server", "/usr/local/etc/redis/redis.conf" ]
networks:
redis_cluster_net:
ipv4_address: 173.18.0.5
redis_5:
image: 'redis:latest'
container_name: redis_5
ports:
- "6379"
volumes:
- redis_5_data:/data
- ./redis/redis.conf:/usr/local/etc/redis/redis.conf
command: [ "redis-server", "/usr/local/etc/redis/redis.conf" ]
networks:
redis_cluster_net:
ipv4_address: 173.18.0.6
redis_6:
image: 'redis:latest'
container_name: redis_6
ports:
- "6379"
volumes:
- redis_6_data:/data
- ./redis/redis.conf:/usr/local/etc/redis/redis.conf
command: [ "redis-server", "/usr/local/etc/redis/redis.conf" ]
networks:
redis_cluster_net:
ipv4_address: 173.18.0.7
# Ephemeral container to create the Redis cluster connections.
# Once the setup is done, this container shuts down
# and the cluster can be used by the service app container
cluster_initiator:
container_name: cluster_initiator
build:
context: redis
dockerfile: Dockerfile
tty: true
depends_on:
- redis_1
- redis_2
- redis_3
- redis_4
- redis_5
- redis_6
networks:
redis_cluster_net:
ipv4_address: 173.18.0.8
# Web UI to browse through our Redis data across all nodes
redis_commander:
image: rediscommander/redis-commander:latest
container_name: redis_web
environment:
REDIS_HOSTS: "local:redis_1:6379,local:redis_2:6379,local:redis_3:6379"
ports:
- "5000:8081"
depends_on:
- redis_1
- redis_2
- redis_3
- redis_4
- redis_5
- redis_6
- cluster_initiator
networks:
redis_cluster_net:
ipv4_address: 173.18.0.9
# Rename the default network so we can easily identify it
# Across all containers
networks:
redis_cluster_net:
driver: bridge
ipam:
driver: default
config:
- subnet: 173.18.0.0/16
これは長いものですが、ここはこれですdocker-compose.yml
ですentrypoint.sh
スクリプトredis.conf
ファイルをクラスタとして機能することができますentrypoint.sh
スクリプトとクラスタ接続を作成するdocker-compose up
すべてが準備ができたら、あなたのブラウザを開いてlocalhost:4000
. そこには、キー/値のペアを入力することができますRedisとそれを保存する前に入力している特定のキーを検索することができますので、redisから取得することができますし、画面上のコンテンツを表示するデモのWebアプリケーションを持っている.JavaScript側で接続がどのように設定されているのか疑問に思っている場合は、見てみましょう
src/service/redisClient.js
ファイル.const Redis = require('ioredis')
/**
* Get an existing Redis client instance. Build one if necessary
* @return {Cluster|null} redis client
* */
function buildRedisClient() {
try {
// cluster URLs should be passed in with the following format:
// REDIS_CLUSTER_URLS=10.0.0.1:6379,10.0.0.2:6379,10.0.0.3:6379
const nodes = process.env.REDIS_CLUSTER_URLS.split(',').map(url => {
const [host, port] = url.split(':')
return { host, port }
})
const client = new Redis.Cluster(nodes, {
redisOptions: {
enableAutoPipelining: true,
},
})
client.on('error', error => {
console.error('Redis Error', error)
})
// Redis emits this error when an something
// occurs when connecting to a node when using Redis in Cluster mode
client.on('node error', (error, node) => {
console.error(`Redis error in node ${node}`, error)
})
return client
} catch (error) {
console.error('Could not create a Redis cluster client', error)
return null
}
}
module.exports = buildRedisClient
この部分はとても簡単です.クラスタのURLを環境から読み込み、Redis.Cluster
Resisioライブラリの使用そこから、我々は問題のコマンドを始めることができますredis.set
, redis.get
or redis.exists
アプリケーション全体.ここではどのように我々はこのレポ内のデモエクスプレスアプリケーションでそれを行う:const buildRedisClient = require('./service/redisClient')
const redis = buildRedisClient()
// Have a look at src/index.js for a complete implementation
app.post('/save-data', async (request, response) => {
const { key, value } = request.body
await redis.set(key, value)
return response.status(201).render('home/index', {
layout: 'default',
dataSaved: true,
})
})
app.post('/search', async (request, response) => {
const { key } = request.body
const value = await redis.get(key)
return response.status(200).render('home/index', {
layout: 'default',
value,
})
})
クラスタに格納されているデータを調べたい場合はlocalhost:5000
とレッズコマンダーUIを参照します.そこにすべてのマスターノードを見ることができるし、すべてのキーと値を探索する必要があります.いくつかのキーが1つのマスターノードに格納され、他のキーが他のノードに格納されます.これはRedisによって行われたデータ配布で、クラスタ全体に負荷分散を提供します.
私は、このDockerセットアップがあなたの開発ワークフローを助けることができることを望みます.ご質問がございましたらお気軽に.
Reference
この問題について(キャッシュのためにRedisクラスタを使う方法), 我々は、より多くの情報をここで見つけました https://dev.to/bpaulino0/how-to-use-redis-cluster-for-caching-4ojfテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol