mirror of
https://github.com/boostorg/redis.git
synced 2026-01-19 04:42:09 +00:00
Adds Sentinel support (#345)
close #237 close #269 close #268 close #229
This commit is contained in:
committed by
GitHub
parent
00f3ec9b78
commit
bdd9c327c1
@@ -3,6 +3,7 @@
|
||||
* xref:cancellation.adoc[]
|
||||
* xref:serialization.adoc[]
|
||||
* xref:logging.adoc[]
|
||||
* xref:sentinel.adoc[]
|
||||
* xref:benchmarks.adoc[]
|
||||
* xref:comparison.adoc[]
|
||||
* xref:examples.adoc[]
|
||||
|
||||
@@ -15,7 +15,7 @@ The examples below show how to use the features discussed throughout this docume
|
||||
* {site-url}/example/cpp20_containers.cpp[cpp20_containers.cpp]: Shows how to send and receive STL containers and how to use transactions.
|
||||
* {site-url}/example/cpp20_json.cpp[cpp20_json.cpp]: Shows how to serialize types using Boost.Json.
|
||||
* {site-url}/example/cpp20_protobuf.cpp[cpp20_protobuf.cpp]: Shows how to serialize types using protobuf.
|
||||
* {site-url}/example/cpp20_resolve_with_sentinel.cpp[cpp20_resolve_with_sentinel.cpp]: Shows how to resolve a master address using sentinels.
|
||||
* {site-url}/example/cpp20_sentinel.cpp[cpp20_sentinel.cpp]: Shows how to use the library with a Sentinel deployment.
|
||||
* {site-url}/example/cpp20_subscriber.cpp[cpp20_subscriber.cpp]: Shows how to implement pubsub with reconnection re-subscription.
|
||||
* {site-url}/example/cpp20_echo_server.cpp[cpp20_echo_server.cpp]: A simple TCP echo server.
|
||||
* {site-url}/example/cpp20_chat_room.cpp[cpp20_chat_room.cpp]: A command line chat built on Redis pubsub.
|
||||
|
||||
@@ -25,8 +25,12 @@ xref:reference:boost/redis/basic_connection.adoc[`basic_connection`]
|
||||
|
||||
xref:reference:boost/redis/address.adoc[`address`]
|
||||
|
||||
xref:reference:boost/redis/role.adoc[`role`]
|
||||
|
||||
xref:reference:boost/redis/config.adoc[`config`]
|
||||
|
||||
xref:reference:boost/redis/sentinel_config.adoc[`sentinel_config`]
|
||||
|
||||
xref:reference:boost/redis/error.adoc[`error`]
|
||||
|
||||
xref:reference:boost/redis/logger.adoc[`logger`]
|
||||
|
||||
152
doc/modules/ROOT/pages/sentinel.adoc
Normal file
152
doc/modules/ROOT/pages/sentinel.adoc
Normal file
@@ -0,0 +1,152 @@
|
||||
//
|
||||
// Copyright (c) 2025 Marcelo Zimbres Silva (mzimbres@gmail.com),
|
||||
// Ruben Perez Hidalgo (rubenperez038 at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
= Sentinel
|
||||
|
||||
Boost.Redis supports Redis Sentinel deployments. Sentinel handling
|
||||
in `connection` is built-in: xref:reference:boost/redis/basic_connection/async_run-04.adoc[`async_run`]
|
||||
automatically connects to Sentinels, resolves the master's address, and connects to the master.
|
||||
|
||||
Configuration is done using xref:reference:boost/redis/sentinel_config.adoc[`config::sentinel`]:
|
||||
|
||||
[source,cpp]
|
||||
----
|
||||
config cfg;
|
||||
|
||||
// To enable Sentinel, set this field to a non-empty list
|
||||
// of (hostname, port) pairs where Sentinels are listening
|
||||
cfg.sentinel.addresses = {
|
||||
{"sentinel1.example.com", "26379"},
|
||||
{"sentinel2.example.com", "26379"},
|
||||
{"sentinel3.example.com", "26379"},
|
||||
};
|
||||
|
||||
// Set master_name to the identifier that you configured
|
||||
// in the "sentinel monitor" statement of your sentinel.conf file
|
||||
cfg.sentinel.master_name = "mymaster";
|
||||
----
|
||||
|
||||
Once set, the connection object can be used normally. See our
|
||||
our {site-url}/example/cpp20_sentinel.cpp[Sentinel example]
|
||||
for a full program.
|
||||
|
||||
== Connecting to replicas
|
||||
|
||||
By default, the library connects to the Redis master.
|
||||
You can connect to one of its replicas by using
|
||||
xref:reference:boost/redis/sentinel_config/server_role.adoc[`config::sentinel::server_role`].
|
||||
This can be used to balance load, if all your commands read data from
|
||||
the server and never write to it. The particular replica will be chosen randomly.
|
||||
|
||||
[source,cpp]
|
||||
----
|
||||
config cfg;
|
||||
|
||||
// Set up Sentinel
|
||||
cfg.sentinel.addresses = {
|
||||
{"sentinel1.example.com", "26379"},
|
||||
{"sentinel2.example.com", "26379"},
|
||||
{"sentinel3.example.com", "26379"},
|
||||
};
|
||||
cfg.sentinel.master_name = "mymaster";
|
||||
|
||||
// Ask the library to connect to a random replica of 'mymaster', rather than the master node
|
||||
cfg.sentinel.server_role = role::replica;
|
||||
----
|
||||
|
||||
|
||||
== Sentinel authentication
|
||||
|
||||
If your Sentinels require authentication,
|
||||
you can use xref:reference:boost/redis/sentinel_config/setup.adoc[`config::sentinel::setup`]
|
||||
to provide credentials.
|
||||
This request is executed immediately after connecting to Sentinels, and
|
||||
before any other command:
|
||||
|
||||
[source,cpp]
|
||||
----
|
||||
// Set up Sentinel
|
||||
config cfg;
|
||||
cfg.sentinel.addresses = {
|
||||
{"sentinel1.example.com", "26379"},
|
||||
{"sentinel2.example.com", "26379"},
|
||||
{"sentinel3.example.com", "26379"},
|
||||
};
|
||||
cfg.sentinel.master_name = "mymaster";
|
||||
|
||||
// By default, setup contains a 'HELLO 3' command.
|
||||
// Override it to add an AUTH clause to it with out credentials.
|
||||
cfg.sentinel.setup.clear();
|
||||
cfg.sentinel.setup.push("HELLO", 3, "AUTH", "sentinel_user", "sentinel_password");
|
||||
|
||||
// cfg.sentinel.setup applies to Sentinels, only.
|
||||
// Use cfg.setup to authenticate to masters/replicas.
|
||||
cfg.use_setup = true; // Required for cfg.setup to be used, for historic reasons
|
||||
cfg.setup.clear();
|
||||
cfg.setup.push("HELLO", 3, "AUTH", "master_user", "master_password");
|
||||
----
|
||||
|
||||
== Using TLS with Sentinels
|
||||
|
||||
You might use TLS with Sentinels only, masters/replicas only, or both by adjusting
|
||||
xref:reference:boost/redis/sentinel_config/use_ssl.adoc[`config::sentinel::use_ssl`]
|
||||
and xref:reference:boost/redis/config/use_ssl.adoc[`config::use_ssl`]:
|
||||
|
||||
[source,cpp]
|
||||
----
|
||||
// Set up Sentinel
|
||||
config cfg;
|
||||
cfg.sentinel.addresses = {
|
||||
{"sentinel1.example.com", "26379"},
|
||||
{"sentinel2.example.com", "26379"},
|
||||
{"sentinel3.example.com", "26379"},
|
||||
};
|
||||
cfg.sentinel.master_name = "mymaster";
|
||||
|
||||
// Adjust these switches to enable/disable TLS
|
||||
cfg.use_ssl = true; // Applies to masters and replicas
|
||||
cfg.sentinel.use_ssl = true; // Applies to Sentinels
|
||||
----
|
||||
|
||||
== Sentinel algorithm
|
||||
|
||||
This section details how `async_run` interacts with Sentinel.
|
||||
Most of the algorithm follows
|
||||
https://redis.io/docs/latest/develop/reference/sentinel-clients/[the official Sentinel client guidelines].
|
||||
Some of these details may vary between library versions.
|
||||
|
||||
* Connections maintain an internal list of Sentinels, bootstrapped from
|
||||
xref:reference:boost/redis/sentinel_config/addresses.adoc[`config::sentinel::addresses`].
|
||||
* The first Sentinel in the list is contacted by performing the following:
|
||||
** A physical connection is established.
|
||||
** The setup request is executed.
|
||||
** The master's address is resolved using
|
||||
https://redis.io/docs/latest/operate/oss_and_stack/management/sentinel/#sentinel-api[`SENTINEL GET-MASTER-NAME-BY-ADDR`].
|
||||
** If `config::sentinel::server_role` is `role::replica`, replica addresses are obtained using
|
||||
https://redis.io/docs/latest/operate/oss_and_stack/management/sentinel/#sentinel-api[`SENTINEL REPLICAS`].
|
||||
One replica is chosen randomly.
|
||||
** The address of other Sentinels also monitoring this master are retrieved using
|
||||
https://redis.io/docs/latest/operate/oss_and_stack/management/sentinel/#sentinel-api[`SENTINEL SENTINELS`].
|
||||
* If a Sentinel is unreachable, doesn't know about the configured master,
|
||||
or returns an error while executing the above requests, the next Sentinel in the list is tried.
|
||||
* If all Sentinels have been tried without success, `config::reconnect_wait_interval`
|
||||
is waited, and the process starts again.
|
||||
* After a successful Sentinel response, the internal Sentinel list is updated
|
||||
with any newly discovered Sentinels.
|
||||
Sentinels in `config::sentinel::addresses` are always kept in the list,
|
||||
even if they weren't present in the output of `SENTINEL SENTINELS`.
|
||||
* The retrieved address is used
|
||||
to establish a connection with the master or replica.
|
||||
A `ROLE` command is added at the end of the setup request.
|
||||
This is used to detect situations where a Sentinel returns outdated
|
||||
information due to a failover in process. If `ROLE` doesn't output
|
||||
the expected role (`"master"` or `"slave"`, depending on `config::sentinel::server_role`)
|
||||
`config::reconnect_wait_interval` is waited and Sentinel is contacted again.
|
||||
* The connection to the master/replica is run like any other connection.
|
||||
If network errors or timeouts happen, `config::reconnect_wait_interval`
|
||||
is waited and Sentinel is contacted again.
|
||||
Reference in New Issue
Block a user