mirror of
https://codeberg.org/redict/redict.git
synced 2025-01-23 00:28:26 -05:00
Cluster: set slot error if we receive an update for a busy slot.
By manually modifying nodes configurations in random ways, it is possible to create the following scenario: A is serving keys for slot 10 B is manually configured to serve keys for slot 10 A receives an update from B (or another node) where it is informed that the slot 10 is now claimed by B with a greater configuration epoch, however A still has keys from slot 10. With this commit A will put the slot in error setting it in IMPORTING state, so that redis-trib can detect the issue.
This commit is contained in:
parent
1ed0ad77f0
commit
a2ff90919f
@ -1099,9 +1099,7 @@ void clusterSetNodeAsMaster(clusterNode *n) {
|
|||||||
* The 'sender' is the node for which we received a configuration update.
|
* The 'sender' is the node for which we received a configuration update.
|
||||||
* Sometimes it is not actaully the "Sender" of the information, like in the case
|
* Sometimes it is not actaully the "Sender" of the information, like in the case
|
||||||
* we receive the info via an UPDATE packet. */
|
* we receive the info via an UPDATE packet. */
|
||||||
void clusterUpdateSlotsConfigWith(clusterNode *sender, uint64_t senderConfigEpoch,
|
void clusterUpdateSlotsConfigWith(clusterNode *sender, uint64_t senderConfigEpoch, unsigned char *slots) {
|
||||||
unsigned char *slots)
|
|
||||||
{
|
|
||||||
int j;
|
int j;
|
||||||
clusterNode *curmaster, *newmaster = NULL;
|
clusterNode *curmaster, *newmaster = NULL;
|
||||||
|
|
||||||
@ -1112,15 +1110,34 @@ void clusterUpdateSlotsConfigWith(clusterNode *sender, uint64_t senderConfigEpoc
|
|||||||
|
|
||||||
for (j = 0; j < REDIS_CLUSTER_SLOTS; j++) {
|
for (j = 0; j < REDIS_CLUSTER_SLOTS; j++) {
|
||||||
if (bitmapTestBit(slots,j)) {
|
if (bitmapTestBit(slots,j)) {
|
||||||
|
/* The slot is already bound to the sender of this message. */
|
||||||
|
if (server.cluster->slots[j] == sender) continue;
|
||||||
|
|
||||||
|
/* The slot is in importing state, it should be modified only
|
||||||
|
* manually via redis-trib (example: a resharding is in progress
|
||||||
|
* and the migrating side slot was already closed and is advertising
|
||||||
|
* a new config. We still want the slot to be closed manually). */
|
||||||
|
if (server.cluster->importing_slots_from[j]) continue;
|
||||||
|
|
||||||
/* We rebind the slot to the new node claiming it if:
|
/* We rebind the slot to the new node claiming it if:
|
||||||
* 1) The slot was unassigned or the new node claims it with a
|
* 1) The slot was unassigned or the new node claims it with a
|
||||||
* greater configEpoch.
|
* greater configEpoch.
|
||||||
* 2) We are not currently importing the slot. */
|
* 2) We are not currently importing the slot. */
|
||||||
if (server.cluster->slots[j] == sender ||
|
|
||||||
server.cluster->importing_slots_from[j]) continue;
|
|
||||||
if (server.cluster->slots[j] == NULL ||
|
if (server.cluster->slots[j] == NULL ||
|
||||||
server.cluster->slots[j]->configEpoch < senderConfigEpoch)
|
server.cluster->slots[j]->configEpoch < senderConfigEpoch)
|
||||||
{
|
{
|
||||||
|
/* Was this slot mine, and still contains keys? Something
|
||||||
|
* odd happened, put the slot in importing state so that
|
||||||
|
* redis-trib fix can detect the condition (and no further
|
||||||
|
* updates will be processed before the slot gets fixed). */
|
||||||
|
if (server.cluster->slots[j] == myself &&
|
||||||
|
countKeysInSlot(j) &&
|
||||||
|
sender != myself)
|
||||||
|
{
|
||||||
|
redisLog(REDIS_WARNING,"Slot update for a slot I still have keys received. Putting the slot in IMPORTING state. Please run the 'redis-trib fix' command.");
|
||||||
|
server.cluster->importing_slots_from[j] = sender;
|
||||||
|
}
|
||||||
|
|
||||||
if (server.cluster->slots[j] == curmaster)
|
if (server.cluster->slots[j] == curmaster)
|
||||||
newmaster = sender;
|
newmaster = sender;
|
||||||
clusterDelSlot(j);
|
clusterDelSlot(j);
|
||||||
|
Loading…
Reference in New Issue
Block a user