userver: userver/storages/redis/component.hpp Source File
Loading...
Searching...
No Matches
component.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/storages/redis/component.hpp
4/// @brief @copybrief components::Redis
5
6#include <memory>
7#include <string>
8#include <unordered_map>
9
10#include <userver/components/component_base.hpp>
11#include <userver/components/component_fwd.hpp>
12#include <userver/dynamic_config/source.hpp>
13#include <userver/rcu/rcu.hpp>
14#include <userver/storages/redis/impl/base.hpp>
15#include <userver/storages/redis/impl/wait_connected_mode.hpp>
16#include <userver/testsuite/redis_control.hpp>
17#include <userver/utils/statistics/entry.hpp>
18
19USERVER_NAMESPACE_BEGIN
20
21namespace redis {
22class Sentinel;
23class ThreadPools;
24} // namespace redis
25
26/// Components, clients and helpers for different databases and storages
27namespace storages {}
28
29/// Redis client
30namespace storages::redis {
31class Client;
32class SubscribeClient;
33class SubscribeClientImpl;
34} // namespace storages::redis
35
36namespace components {
37
38// clang-format off
39
40/// @ingroup userver_components
41///
42/// @brief Redis client component
43///
44/// Provides access to a redis cluster.
45///
46/// ## Dynamic options:
47/// * @ref REDIS_COMMANDS_BUFFERING_SETTINGS
48/// * @ref REDIS_DEFAULT_COMMAND_CONTROL
49/// * @ref REDIS_METRICS_SETTINGS
50/// * @ref REDIS_PUBSUB_METRICS_SETTINGS
51/// * @ref REDIS_RETRY_BUDGET_SETTINGS
52/// * @ref REDIS_REPLICA_MONITORING_SETTINGS
53/// * @ref REDIS_SUBSCRIBER_DEFAULT_COMMAND_CONTROL
54/// * @ref REDIS_SUBSCRIPTIONS_REBALANCE_MIN_INTERVAL_SECONDS
55/// * @ref REDIS_WAIT_CONNECTED
56///
57/// ## Static options:
58/// Name | Description | Default value
59/// ---- | ----------- | -------------
60/// thread_pools.redis_thread_pool_size | thread count to serve Redis requests | -
61/// thread_pools.sentinel_thread_pool_size | thread count to serve sentinel requests. | -
62/// groups | array of redis clusters to work with excluding subscribers | -
63/// groups.[].config_name | key name in secdist with options for this cluster | -
64/// groups.[].db | name to refer to the cluster in components::Redis::GetClient() | -
65/// groups.[].sharding_strategy | one of RedisCluster, KeyShardCrc32, KeyShardTaximeterCrc32 or KeyShardGpsStorageDriver | "KeyShardTaximeterCrc32"
66/// groups.[].allow_reads_from_master | allows read requests from master instance | false
67/// subscribe_groups | array of redis clusters to work with in subscribe mode | -
68/// subscribe_groups.[].config_name | key name in secdist with options for this cluster | -
69/// subscribe_groups.[].db | name to refer to the cluster in components::Redis::GetSubscribeClient() | -
70/// subscribe_groups.[].sharding_strategy | either RedisCluster or KeyShardTaximeterCrc32 | "KeyShardTaximeterCrc32"
71///
72/// ## Static configuration example:
73///
74/// ```
75/// # yaml
76/// redis:
77/// groups:
78/// - config_name: cats
79/// db: hello_service_cats_catalogue
80/// sharding_strategy: RedisCluster
81/// - config_name: dogs
82/// db: hello_service_dogs_catalogue
83/// subscribe_groups:
84/// - config_name: food
85/// db: hello_service_pet_food_orders
86/// thread_pools:
87/// redis_thread_pool_size: 8
88/// sentinel_thread_pool_size: 1
89/// ```
90///
91/// ## Secdist format
92///
93/// If a `config_name` option is provided, for example
94/// `groups.some.config_name: some_name_of_your_database`, then the Secdist
95/// entry for that alias should look like following:
96/// @code{.json}
97/// {
98/// "redis_settings": {
99/// "some_name_of_your_database": {
100/// "password": "the_password_of_your_database",
101/// "sentinels": [
102/// {"host": "the_host1_of_your_database", "port": 11564}
103/// ],
104/// "shards": [
105/// {"name": "test_master0"}
106/// ]
107/// }
108/// }
109/// }
110/// @endcode
111///
112/// ## Cluster Redis setup
113///
114/// Redis cluster is the new recommended way of setting up Redis servers
115/// with improved stability.
116///
117/// To start, set `sharding_strategy: RedisCluster` in the static config
118/// as shown above.
119///
120/// Secdist configuration is simplified:
121///
122/// 1. `"shards"` field is ignored, you can specify an empty array there;
123/// 2. `"sentinels"` field should contain some of the cluster nodes. They are
124/// only used for topology discovery; it is not necessary to list all nodes.
125
126// clang-format on
127class Redis : public ComponentBase {
128public:
129 Redis(const ComponentConfig& config, const ComponentContext& component_context);
130
131 ~Redis() override;
132
133 /// @ingroup userver_component_names
134 /// @brief The default name of components::Redis
135 static constexpr std::string_view kName = "redis";
136
137 std::shared_ptr<storages::redis::Client>
138 GetClient(const std::string& name, USERVER_NAMESPACE::redis::RedisWaitConnected wait_connected = {}) const;
139 [[deprecated("use GetClient()")]] std::shared_ptr<redis::Sentinel> Client(const std::string& name) const;
140 std::shared_ptr<storages::redis::SubscribeClient>
141 GetSubscribeClient(const std::string& name, USERVER_NAMESPACE::redis::RedisWaitConnected wait_connected = {}) const;
142
143 static yaml_config::Schema GetStaticConfigSchema();
144
145private:
146 void OnConfigUpdate(const dynamic_config::Snapshot& cfg);
147
148 void Connect(
149 const ComponentConfig& config,
150 const ComponentContext& component_context,
151 const testsuite::RedisControl& testsuite_redis_control
152 );
153
154 void WriteStatistics(utils::statistics::Writer& writer);
155 void WriteStatisticsPubsub(utils::statistics::Writer& writer);
156
157 std::shared_ptr<redis::ThreadPools> thread_pools_;
158 std::unordered_map<std::string, std::shared_ptr<redis::Sentinel>> sentinels_;
159 std::unordered_map<std::string, std::shared_ptr<storages::redis::Client>> clients_;
160 std::unordered_map<std::string, std::shared_ptr<storages::redis::SubscribeClientImpl>> subscribe_clients_;
161
162 dynamic_config::Source config_;
163 concurrent::AsyncEventSubscriberScope config_subscription_;
164
165 utils::statistics::Entry statistics_holder_;
166 utils::statistics::Entry subscribe_statistics_holder_;
167
168 redis::MetricsSettings::StaticSettings static_metrics_settings_;
169 rcu::Variable<redis::MetricsSettings> metrics_settings_;
170 rcu::Variable<redis::PubsubMetricsSettings> pubsub_metrics_settings_;
171};
172
173template <>
174inline constexpr bool kHasValidate<Redis> = true;
175
176} // namespace components
177
178USERVER_NAMESPACE_END