Skip to content

Commit 0b7f6d2

Browse files
Added a new failover option, which excludes masters for readonly
failover
1 parent 05e38d5 commit 0b7f6d2

File tree

4 files changed

+30
-14
lines changed

4 files changed

+30
-14
lines changed

cluster_library.c

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1072,10 +1072,12 @@ static int cluster_dist_write(redisCluster *c, const char *cmd, size_t sz,
10721072
int i, count=1, *nodes;
10731073
RedisSock *redis_sock;
10741074

1075-
/* Allocate enough memory for the master and all of our slaves */
1075+
/* Determine our overall node count */
10761076
if (c->master[c->cmd_slot]->slaves) {
10771077
count += zend_hash_num_elements(c->master[c->cmd_slot]->slaves);
10781078
}
1079+
1080+
/* Allocate memory for master + slaves or just slaves */
10791081
nodes = emalloc(sizeof(int)*count);
10801082

10811083
/* Populate our array with the master and each of it's slaves, then
@@ -1084,15 +1086,19 @@ static int cluster_dist_write(redisCluster *c, const char *cmd, size_t sz,
10841086
fyshuffle(nodes, count);
10851087

10861088
/* Iterate through our nodes until we find one we can write to or fail */
1087-
for (i = nomaster; i < count; i++) {
1089+
for (i = 0; i < count; i++) {
1090+
/* Skip if this is the master node and we don't want to query that */
1091+
if (nomaster && nodes[i] == 0)
1092+
continue;
1093+
10881094
/* Get the slave for this index */
10891095
redis_sock = cluster_slot_sock(c, c->cmd_slot, nodes[i]);
10901096
if (!redis_sock) continue;
10911097

10921098
/* Connect to this node if we haven't already */
10931099
CLUSTER_LAZY_CONNECT(redis_sock);
10941100

1095-
/* If we're not on the master, attempt to send the READONLY commadn to
1101+
/* If we're not on the master, attempt to send the READONLY command to
10961102
* this slave, and skip it if that fails */
10971103
if (nodes[i] == 0 || redis_sock->readonly ||
10981104
cluster_send_readonly(redis_sock TSRMLS_CC) == 0)
@@ -1127,7 +1133,10 @@ static int cluster_dist_write(redisCluster *c, const char *cmd, size_t sz,
11271133
* If we're unable to communicate with this slot's master, we attempt the query
11281134
* against any slaves (at random) that this master has.
11291135
* REDIS_FAILOVER_DISTRIBUTE:
1130-
* We pick at random from the master and any slaves it has. This option is
1136+
* We pick at random from the master and any slaves it has. This option will
1137+
* load balance between masters and slaves
1138+
* REDIS_FAILOVER_DISTRIBUTE_SLAVES:
1139+
* We pick at random from slave nodes of a given master. This option is
11311140
* used to load balance read queries against N slaves.
11321141
*
11331142
* Once we are able to find a node we can write to, we check for MOVED or
@@ -1138,7 +1147,7 @@ static int cluster_sock_write(redisCluster *c, const char *cmd, size_t sz,
11381147
{
11391148
redisClusterNode **seed_node;
11401149
RedisSock *redis_sock;
1141-
int failover;
1150+
int failover, nomaster;
11421151

11431152
/* First try the socket requested */
11441153
redis_sock = c->cmd_sock;
@@ -1170,9 +1179,14 @@ static int cluster_sock_write(redisCluster *c, const char *cmd, size_t sz,
11701179
CLUSTER_LAZY_CONNECT(redis_sock);
11711180
if (CLUSTER_SEND_PAYLOAD(redis_sock, cmd, sz) ||
11721181
!cluster_dist_write(c, cmd, sz, 1 TSRMLS_CC)) return 0;
1173-
} else if (!cluster_dist_write(c, cmd, sz, 0 TSRMLS_CC)) {
1174-
/* We were able to write to a master or slave at random */
1175-
return 0;
1182+
} else {
1183+
/* Include or exclude master node depending on failover option and
1184+
* attempt to make our write */
1185+
nomaster = failover == REDIS_FAILOVER_DISTRIBUTE_SLAVES;
1186+
if (!cluster_dist_write(c, cmd, sz, nomaster TSRMLS_CC)) {
1187+
/* We were able to write to a master or slave at random */
1188+
return 0;
1189+
}
11761190
}
11771191

11781192
/* Don't fall back if direct communication with this slot is required. */

common.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,11 @@ typedef enum _PUBSUB_TYPE {
6666
#define REDIS_OPT_SCAN 4
6767

6868
/* cluster options */
69-
#define REDIS_OPT_FAILOVER 5
70-
#define REDIS_FAILOVER_NONE 0
71-
#define REDIS_FAILOVER_ERROR 1
72-
#define REDIS_FAILOVER_DISTRIBUTE 2
73-
69+
#define REDIS_OPT_FAILOVER 5
70+
#define REDIS_FAILOVER_NONE 0
71+
#define REDIS_FAILOVER_ERROR 1
72+
#define REDIS_FAILOVER_DISTRIBUTE 2
73+
#define REDIS_FAILOVER_DISTRIBUTE_SLAVES 3
7474
/* serializers */
7575
#define REDIS_SERIALIZER_NONE 0
7676
#define REDIS_SERIALIZER_PHP 1

redis.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -532,6 +532,7 @@ static void add_class_constants(zend_class_entry *ce, int is_cluster TSRMLS_DC)
532532
zend_declare_class_constant_long(ce, ZEND_STRL("FAILOVER_NONE"), REDIS_FAILOVER_NONE TSRMLS_CC);
533533
zend_declare_class_constant_long(ce, ZEND_STRL("FAILOVER_ERROR"), REDIS_FAILOVER_ERROR TSRMLS_CC);
534534
zend_declare_class_constant_long(ce, ZEND_STRL("FAILOVER_DISTRIBUTE"), REDIS_FAILOVER_DISTRIBUTE TSRMLS_CC);
535+
zend_declare_class_constant_long(ce, ZEND_STRL("FAILOVER_DISTRIBUTE_SLAVES"), REDIS_FAILOVER_DISTRIBUTE_SLAVES TSRMLS_CC);
535536
}
536537
#ifdef HAVE_REDIS_IGBINARY
537538
zend_declare_class_constant_long(ce, ZEND_STRL("SERIALIZER_IGBINARY"), REDIS_SERIALIZER_IGBINARY TSRMLS_CC);

redis_commands.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2970,7 +2970,8 @@ void redis_setoption_handler(INTERNAL_FUNCTION_PARAMETERS,
29702970
val_long = atol(val_str);
29712971
if (val_long == REDIS_FAILOVER_NONE ||
29722972
val_long == REDIS_FAILOVER_ERROR ||
2973-
val_long == REDIS_FAILOVER_DISTRIBUTE)
2973+
val_long == REDIS_FAILOVER_DISTRIBUTE ||
2974+
val_long == REDIS_FAILOVER_DISTRIBUTE_SLAVES)
29742975
{
29752976
c->failover = val_long;
29762977
RETURN_TRUE;

0 commit comments

Comments
 (0)