Skip to content

Commit 6f46080

Browse files
committed
cluster checks are now unconditional and have exponential backoff. previously they ran at a fixed interval only when there were no commands that could generate a MOVE/ASK error. That wasn't good enough for detecting newly added slaves
1 parent eb1da51 commit 6f46080

File tree

8 files changed

+205
-93
lines changed

8 files changed

+205
-93
lines changed

src/nchan_commands.rb

Lines changed: 43 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -593,15 +593,6 @@
593593
default: "4m",
594594
info: "Send a keepalive command to redis to keep the Nchan redis clients from disconnecting. Set to 0 to disable."
595595

596-
nchan_redis_cluster_check_interval [:main, :srv, :upstream, :loc],
597-
:ngx_conf_set_sec_slot,
598-
[:loc_conf, :"redis.cluster_check_interval"],
599-
600-
group: "storage",
601-
tags: ['redis'],
602-
default: "5s",
603-
info: "Send a CLUSTER INFO command to each connected Redis node to see if the cluster config epoch has changed. Sent only when in Cluster mode and if any other command that may result in a MOVE error has not been sent in the configured time."
604-
605596
nchan_redis_load_scripts_unconditionally [:upstream],
606597
:ngx_conf_set_flag_slot,
607598
[:srv_conf, "redis.load_scripts_unconditionally"],
@@ -677,7 +668,7 @@
677668
default: "0.5 (increase delay by 50% each try)",
678669
info: "Add an exponentially increasing delay to Redis connection retries. `Delay[n] = (Delay[n-1] + jitter) * (nchan_redis_reconnect_delay_backoff + 1)`."
679670

680-
nchan_redis_reconnect_delay_max [:upstream],
671+
nchan_redis_reconnect_delay_max [:upstream],
681672
:ngx_conf_set_msec_slot,
682673
[:srv_conf, :"redis.reconnect_delay.max"],
683674

@@ -687,6 +678,48 @@
687678
value: "<time> (0 to disable)",
688679
info: "Maximum Redis reconnection delay after backoff and jitter."
689680

681+
nchan_redis_cluster_check_interval_min [:upstream],
682+
:ngx_conf_set_msec_slot,
683+
[:srv_conf, :"redis.cluster_check_interval.min"],
684+
685+
alt: :nchan_redis_cluster_check_interval,
686+
group: "storage",
687+
tags: ['redis'],
688+
value: "<time>",
689+
default: "1s (0 to disable)",
690+
info: "When connected to a cluster, periodically check the cluster state and layout via a random master node."
691+
692+
nchan_redis_cluster_check_interval_jitter [:upstream],
693+
:ngx_conf_set_jitter,
694+
[:srv_conf, :"redis.cluster_check_interval.jitter_multiplier"],
695+
696+
group: "storage",
697+
tags: ['redis'],
698+
value: "<floating point> >= 0, (0 to disable)",
699+
default: "0.2 (20% of inverval value)",
700+
info: "Introduce random jitter to Redis cluster chck interval, where the range is `±(cluster_check_interval * nchan_redis_cluster_check_interval_jitter) / 2`."
701+
702+
nchan_redis_cluster_check_interval_backoff [:upstream],
703+
:ngx_conf_set_exponential_backoff,
704+
[:srv_conf, :"redis.cluster_check_interval.backoff_multiplier"],
705+
706+
group: "storage",
707+
tags: ['redis'],
708+
value: "<floating point> >= 0, ratio of current delay",
709+
default: "2 (increase delay by 200% each try)",
710+
info: "Add an exponentially increasing delay to the Redis cluster check interval. `Delay[n] = (Delay[n-1] + jitter) * (nchan_redis_cluster_check_interval_backoff + 1)`."
711+
712+
nchan_redis_cluster_check_interval_max [:upstream],
713+
:ngx_conf_set_msec_slot,
714+
[:srv_conf, :"redis.cluster_check_interval.max"],
715+
716+
group: "storage",
717+
tags: ['redis'],
718+
value: "<time> (0 to disable)",
719+
default: "30s",
720+
info: "Maximum Redis cluster check interval after backoff and jitter."
721+
722+
690723
nchan_redis_cluster_recovery_delay [:upstream],
691724
:ngx_conf_set_msec_slot,
692725
[:srv_conf, :"redis.cluster_recovery_delay.min"],

src/nchan_config_commands.c

Lines changed: 52 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -755,19 +755,6 @@ static ngx_command_t nchan_commands[] = {
755755
offsetof(nchan_loc_conf_t, redis.ping_interval),
756756
NULL } ,
757757

758-
{ ngx_string("nchan_redis_cluster_check_interval"),
759-
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_UPS_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
760-
ngx_conf_set_sec_slot,
761-
NGX_HTTP_LOC_CONF_OFFSET,
762-
offsetof(nchan_loc_conf_t, redis.cluster_check_interval),
763-
NULL } ,
764-
{ ngx_string("nchan_redis_cluster_check_interval"), //alt for nchan_redis_cluster_check_interval
765-
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_UPS_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
766-
ngx_conf_set_sec_slot,
767-
NGX_HTTP_LOC_CONF_OFFSET,
768-
offsetof(nchan_loc_conf_t, redis.cluster_check_interval),
769-
NULL } ,
770-
771758
{ ngx_string("nchan_redis_load_scripts_unconditionally"),
772759
NGX_HTTP_UPS_CONF|NGX_CONF_TAKE1,
773760
ngx_conf_set_flag_slot,
@@ -885,6 +872,58 @@ static ngx_command_t nchan_commands[] = {
885872
offsetof(nchan_srv_conf_t, redis.reconnect_delay.max),
886873
NULL } ,
887874

875+
{ ngx_string("nchan_redis_cluster_check_interval_min"),
876+
NGX_HTTP_UPS_CONF|NGX_CONF_TAKE1,
877+
ngx_conf_set_msec_slot,
878+
NGX_HTTP_SRV_CONF_OFFSET,
879+
offsetof(nchan_srv_conf_t, redis.cluster_check_interval.min),
880+
NULL } ,
881+
{ ngx_string("nchan_redis_cluster_check_interval"), //alt for nchan_redis_cluster_check_interval_min
882+
NGX_HTTP_UPS_CONF|NGX_CONF_TAKE1,
883+
ngx_conf_set_msec_slot,
884+
NGX_HTTP_SRV_CONF_OFFSET,
885+
offsetof(nchan_srv_conf_t, redis.cluster_check_interval.min),
886+
NULL } ,
887+
888+
{ ngx_string("nchan_redis_cluster_check_interval_jitter"),
889+
NGX_HTTP_UPS_CONF|NGX_CONF_TAKE1,
890+
ngx_conf_set_jitter,
891+
NGX_HTTP_SRV_CONF_OFFSET,
892+
offsetof(nchan_srv_conf_t, redis.cluster_check_interval.jitter_multiplier),
893+
NULL } ,
894+
{ ngx_string("nchan_redis_cluster_check_interval_jitter"), //alt for nchan_redis_cluster_check_interval_jitter
895+
NGX_HTTP_UPS_CONF|NGX_CONF_TAKE1,
896+
ngx_conf_set_jitter,
897+
NGX_HTTP_SRV_CONF_OFFSET,
898+
offsetof(nchan_srv_conf_t, redis.cluster_check_interval.jitter_multiplier),
899+
NULL } ,
900+
901+
{ ngx_string("nchan_redis_cluster_check_interval_backoff"),
902+
NGX_HTTP_UPS_CONF|NGX_CONF_TAKE1,
903+
ngx_conf_set_exponential_backoff,
904+
NGX_HTTP_SRV_CONF_OFFSET,
905+
offsetof(nchan_srv_conf_t, redis.cluster_check_interval.backoff_multiplier),
906+
NULL } ,
907+
{ ngx_string("nchan_redis_cluster_check_interval_backoff"), //alt for nchan_redis_cluster_check_interval_backoff
908+
NGX_HTTP_UPS_CONF|NGX_CONF_TAKE1,
909+
ngx_conf_set_exponential_backoff,
910+
NGX_HTTP_SRV_CONF_OFFSET,
911+
offsetof(nchan_srv_conf_t, redis.cluster_check_interval.backoff_multiplier),
912+
NULL } ,
913+
914+
{ ngx_string("nchan_redis_cluster_check_interval_max"),
915+
NGX_HTTP_UPS_CONF|NGX_CONF_TAKE1,
916+
ngx_conf_set_msec_slot,
917+
NGX_HTTP_SRV_CONF_OFFSET,
918+
offsetof(nchan_srv_conf_t, redis.cluster_check_interval.max),
919+
NULL } ,
920+
{ ngx_string("nchan_redis_cluster_check_interval_max"), //alt for nchan_redis_cluster_check_interval_max
921+
NGX_HTTP_UPS_CONF|NGX_CONF_TAKE1,
922+
ngx_conf_set_msec_slot,
923+
NGX_HTTP_SRV_CONF_OFFSET,
924+
offsetof(nchan_srv_conf_t, redis.cluster_check_interval.max),
925+
NULL } ,
926+
888927
{ ngx_string("nchan_redis_cluster_recovery_delay"),
889928
NGX_HTTP_UPS_CONF|NGX_CONF_TAKE1,
890929
ngx_conf_set_msec_slot,

src/nchan_defs.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@
99
#define NCHAN_DEFAULT_REDIS_CLUSTER_CONNECT_TIMEOUT_MSEC 15000
1010
#define NCHAN_DEFAULT_REDIS_CLUSTER_MAX_FAILING_TIME_MSEC 30000
1111

12+
#define NCHAN_REDIS_DEFAULT_CLUSTER_CHECK_INTERVAL_MIN_MSEC 1000
13+
#define NCHAN_REDIS_DEFAULT_CLUSTER_CHECK_INTERVAL_BACKOFF_MULTIPLIER 2
14+
#define NCHAN_REDIS_DEFAULT_CLUSTER_CHECK_INTERVAL_JITTER_MULTIPLIER 0.2
15+
#define NCHAN_REDIS_DEFAULT_CLUSTER_CHECK_INTERVAL_MAX_MSEC 30000
16+
1217
#define NCHAN_DEFAULT_REDIS_RECONNECT_DELAY_MIN_MSEC 500
1318
#define NCHAN_DEFAULT_REDIS_RECONNECT_DELAY_BACKOFF_MULTIPLIER 0.5
1419
#define NCHAN_DEFAULT_REDIS_RECONNECT_DELAY_JITTER_MULTIPLIER 0.1

src/nchan_setup.c

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,10 @@ static void *nchan_create_srv_conf(ngx_conf_t *cf) {
146146
scf->redis.cluster_recovery_delay.jitter_multiplier = NGX_CONF_UNSET;
147147
scf->redis.cluster_recovery_delay.backoff_multiplier = NGX_CONF_UNSET;
148148
scf->redis.cluster_recovery_delay.max = NGX_CONF_UNSET_MSEC;
149+
scf->redis.cluster_check_interval.min = NGX_CONF_UNSET_MSEC;
150+
scf->redis.cluster_check_interval.jitter_multiplier = NGX_CONF_UNSET;
151+
scf->redis.cluster_check_interval.backoff_multiplier = NGX_CONF_UNSET;
152+
scf->redis.cluster_check_interval.max = NGX_CONF_UNSET_MSEC;
149153
scf->redis.cluster_max_failing_msec = NGX_CONF_UNSET_MSEC;
150154
scf->redis.load_scripts_unconditionally = NGX_CONF_UNSET;
151155
scf->redis.optimize_target = NCHAN_REDIS_OPTIMIZE_UNSET;
@@ -197,6 +201,22 @@ static char *nchan_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) {
197201
}
198202
ngx_conf_merge_msec_value(conf->redis.cluster_recovery_delay.max, prev->redis.cluster_recovery_delay.max, NCHAN_DEFAULT_REDIS_CLUSTER_RECOVERY_DELAY_MAX_MSEC);
199203

204+
205+
ngx_conf_merge_msec_value(conf->redis.cluster_check_interval.min, prev->redis.cluster_check_interval.min, NCHAN_REDIS_DEFAULT_CLUSTER_CHECK_INTERVAL_MIN_MSEC);
206+
if(prev->redis.cluster_check_interval.jitter_multiplier == NGX_CONF_UNSET) {
207+
conf->redis.cluster_check_interval.jitter_multiplier = NCHAN_REDIS_DEFAULT_CLUSTER_CHECK_INTERVAL_JITTER_MULTIPLIER;
208+
}
209+
else {
210+
conf->redis.cluster_check_interval.jitter_multiplier = prev->redis.cluster_check_interval.jitter_multiplier;
211+
}
212+
if(prev->redis.cluster_check_interval.backoff_multiplier == NGX_CONF_UNSET) {
213+
conf->redis.cluster_check_interval.backoff_multiplier = NCHAN_REDIS_DEFAULT_CLUSTER_CHECK_INTERVAL_BACKOFF_MULTIPLIER;
214+
}
215+
else {
216+
conf->redis.cluster_check_interval.backoff_multiplier = prev->redis.cluster_check_interval.backoff_multiplier;
217+
}
218+
ngx_conf_merge_msec_value(conf->redis.cluster_check_interval.max, prev->redis.cluster_check_interval.max, NCHAN_REDIS_DEFAULT_CLUSTER_CHECK_INTERVAL_MAX_MSEC);
219+
200220
ngx_conf_merge_value(conf->redis.load_scripts_unconditionally, prev->redis.load_scripts_unconditionally, 0);
201221

202222
MERGE_UNSET_CONF(conf->redis.optimize_target, prev->redis.optimize_target, NCHAN_REDIS_OPTIMIZE_UNSET, NCHAN_REDIS_OPTIMIZE_CPU);
@@ -294,7 +314,6 @@ static void *nchan_create_loc_conf(ngx_conf_t *cf) {
294314
ngx_memzero(&lcf->redis, sizeof(lcf->redis));
295315
lcf->redis.url_enabled=NGX_CONF_UNSET;
296316
lcf->redis.ping_interval = NGX_CONF_UNSET;
297-
lcf->redis.cluster_check_interval=NGX_CONF_UNSET;
298317
lcf->redis.upstream_inheritable=NGX_CONF_UNSET;
299318
lcf->redis.storage_mode = REDIS_MODE_CONF_UNSET;
300319
lcf->redis.nostore_fastpublish = NGX_CONF_UNSET;
@@ -561,10 +580,6 @@ static char * nchan_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) {
561580
ngx_conf_merge_value(conf->redis.ping_interval, up->redis.ping_interval, NGX_CONF_UNSET);
562581
ngx_conf_merge_value(conf->redis.ping_interval, prev->redis.ping_interval, NCHAN_REDIS_DEFAULT_PING_INTERVAL_TIME);
563582

564-
if(up)
565-
ngx_conf_merge_value(conf->redis.cluster_check_interval, up->redis.cluster_check_interval, NGX_CONF_UNSET);
566-
ngx_conf_merge_value(conf->redis.cluster_check_interval, prev->redis.cluster_check_interval, NCHAN_REDIS_DEFAULT_CLUSTER_CHECK_INTERVAL_TIME);
567-
568583
if(up)
569584
ngx_conf_merge_value(conf->redis.nostore_fastpublish, up->redis.nostore_fastpublish, NGX_CONF_UNSET);
570585
ngx_conf_merge_value(conf->redis.nostore_fastpublish, prev->redis.nostore_fastpublish, 0);

src/nchan_types.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ typedef struct {
3939
ngx_str_t url;
4040
ngx_flag_t url_enabled;
4141
time_t ping_interval;
42-
time_t cluster_check_interval;
4342
ngx_str_t namespace;
4443
nchan_redis_storage_mode_t storage_mode;
4544
ngx_int_t nostore_fastpublish;
@@ -335,6 +334,7 @@ typedef struct {
335334
ngx_int_t load_scripts_unconditionally;
336335
nchan_backoff_settings_t reconnect_delay;
337336
nchan_backoff_settings_t cluster_recovery_delay;
337+
nchan_backoff_settings_t cluster_check_interval;
338338
nchan_redis_optimize_t optimize_target;
339339
ngx_int_t master_weight;
340340
ngx_int_t slave_weight;

0 commit comments

Comments
 (0)