Skip to content

Commit f8547e5

Browse files
committed
Added GEORADIUS(BYMEMBER)_RO variants for read-only operations.
Issue redis#4084 shows how for a design error, GEORADIUS is a write command because of the STORE option. Because of this it does not work on readonly slaves, gets redirected to masters in Redis Cluster even when the connection is in READONLY mode and so forth. To break backward compatibility at this stage, with Redis 4.0 to be in advanced RC state, is problematic for the user base. The API can be fixed into the unstable branch soon if we'll decide to do so in order to be more consistent, and reease Redis 5.0 with this incompatibility in the future. This is still unclear. However, the ability to scale GEO queries in slaves easily is too important so this commit adds two read-only variants to the GEORADIUS and GEORADIUSBYMEMBER command: GEORADIUS_RO and GEORADIUSBYMEMBER_RO. The commands are exactly as the original commands, but they do not accept the STORE and STOREDIST options.
1 parent 01a4b98 commit f8547e5

File tree

3 files changed

+32
-11
lines changed

3 files changed

+32
-11
lines changed

src/geo.c

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -452,13 +452,14 @@ void geoaddCommand(client *c) {
452452
#define SORT_ASC 1
453453
#define SORT_DESC 2
454454

455-
#define RADIUS_COORDS 1
456-
#define RADIUS_MEMBER 2
455+
#define RADIUS_COORDS (1<<0) /* Search around coordinates. */
456+
#define RADIUS_MEMBER (1<<1) /* Search around member. */
457+
#define RADIUS_NOSTORE (1<<2) /* Do not acceot STORE/STOREDIST option. */
457458

458459
/* GEORADIUS key x y radius unit [WITHDIST] [WITHHASH] [WITHCOORD] [ASC|DESC]
459460
* [COUNT count] [STORE key] [STOREDIST key]
460461
* GEORADIUSBYMEMBER key member radius unit ... options ... */
461-
void georadiusGeneric(client *c, int type) {
462+
void georadiusGeneric(client *c, int flags) {
462463
robj *key = c->argv[1];
463464
robj *storekey = NULL;
464465
int storedist = 0; /* 0 for STORE, 1 for STOREDIST. */
@@ -473,19 +474,19 @@ void georadiusGeneric(client *c, int type) {
473474
/* Find long/lat to use for radius search based on inquiry type */
474475
int base_args;
475476
double xy[2] = { 0 };
476-
if (type == RADIUS_COORDS) {
477+
if (flags & RADIUS_COORDS) {
477478
base_args = 6;
478479
if (extractLongLatOrReply(c, c->argv + 2, xy) == C_ERR)
479480
return;
480-
} else if (type == RADIUS_MEMBER) {
481+
} else if (flags & RADIUS_MEMBER) {
481482
base_args = 5;
482483
robj *member = c->argv[2];
483484
if (longLatFromMember(zobj, member, xy) == C_ERR) {
484485
addReplyError(c, "could not decode requested zset member");
485486
return;
486487
}
487488
} else {
488-
addReplyError(c, "unknown georadius search type");
489+
addReplyError(c, "Unknown georadius search type");
489490
return;
490491
}
491492

@@ -522,11 +523,17 @@ void georadiusGeneric(client *c, int type) {
522523
return;
523524
}
524525
i++;
525-
} else if (!strcasecmp(arg, "store") && (i+1) < remaining) {
526+
} else if (!strcasecmp(arg, "store") &&
527+
(i+1) < remaining &&
528+
!(flags & RADIUS_NOSTORE))
529+
{
526530
storekey = c->argv[base_args+i+1];
527531
storedist = 0;
528532
i++;
529-
} else if (!strcasecmp(arg, "storedist") && (i+1) < remaining) {
533+
} else if (!strcasecmp(arg, "storedist") &&
534+
(i+1) < remaining &&
535+
!(flags & RADIUS_NOSTORE))
536+
{
530537
storekey = c->argv[base_args+i+1];
531538
storedist = 1;
532539
i++;
@@ -671,10 +678,20 @@ void georadiusCommand(client *c) {
671678
}
672679

673680
/* GEORADIUSBYMEMBER wrapper function. */
674-
void georadiusByMemberCommand(client *c) {
681+
void georadiusbymemberCommand(client *c) {
675682
georadiusGeneric(c, RADIUS_MEMBER);
676683
}
677684

685+
/* GEORADIUS_RO wrapper function. */
686+
void georadiusroCommand(client *c) {
687+
georadiusGeneric(c, RADIUS_COORDS|RADIUS_NOSTORE);
688+
}
689+
690+
/* GEORADIUSBYMEMBER_RO wrapper function. */
691+
void georadiusbymemberroCommand(client *c) {
692+
georadiusGeneric(c, RADIUS_MEMBER|RADIUS_NOSTORE);
693+
}
694+
678695
/* GEOHASH key ele1 ele2 ... eleN
679696
*
680697
* Returns an array with an 11 characters geohash representation of the

src/server.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,9 @@ struct redisCommand redisCommandTable[] = {
291291
{"command",commandCommand,0,"lt",0,NULL,0,0,0,0,0},
292292
{"geoadd",geoaddCommand,-5,"wm",0,NULL,1,1,1,0,0},
293293
{"georadius",georadiusCommand,-6,"w",0,georadiusGetKeys,1,1,1,0,0},
294-
{"georadiusbymember",georadiusByMemberCommand,-5,"w",0,georadiusGetKeys,1,1,1,0,0},
294+
{"georadius_ro",georadiusroCommand,-6,"r",0,georadiusGetKeys,1,1,1,0,0},
295+
{"georadiusbymember",georadiusbymemberCommand,-5,"w",0,georadiusGetKeys,1,1,1,0,0},
296+
{"georadiusbymember_ro",georadiusbymemberroCommand,-5,"r",0,georadiusGetKeys,1,1,1,0,0},
295297
{"geohash",geohashCommand,-2,"r",0,NULL,1,1,1,0,0},
296298
{"geopos",geoposCommand,-2,"r",0,NULL,1,1,1,0,0},
297299
{"geodist",geodistCommand,-4,"r",0,NULL,1,1,1,0,0},

src/server.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1956,8 +1956,10 @@ void replconfCommand(client *c);
19561956
void waitCommand(client *c);
19571957
void geoencodeCommand(client *c);
19581958
void geodecodeCommand(client *c);
1959-
void georadiusByMemberCommand(client *c);
1959+
void georadiusbymemberCommand(client *c);
1960+
void georadiusbymemberroCommand(client *c);
19601961
void georadiusCommand(client *c);
1962+
void georadiusroCommand(client *c);
19611963
void geoaddCommand(client *c);
19621964
void geohashCommand(client *c);
19631965
void geoposCommand(client *c);

0 commit comments

Comments
 (0)