Why implement this function ❓

How to implement this function ❓

What are the disadvantages of this method ❓

Are there any other ways ❓

Why is this required

For example, in a shopping mall system, the order service and the inventory service are separate, and the purchase module implementation uses message compensation (via redis list) to modify the inventory of goods. If the inventory service restarts unexpectedly during message processing, one or more valid messages may be lost. So that’s not a good implementation for the robustness of the system.

How did the message get lost in 🌰? Can I get it back?

Since the pop of the list is sent directly to the server, redis will delete the data from the server during this process, so when the pop message comes out, the message is essentially deleted from the server. So there is no guarantee that a message has been consumed.

Based on the reliability of the system, it is necessary to do the message confirmation function

How to implement this function

Redis uses commands to manipulate data.

So here’s the process.

128.0.0.2:6379 > lpop list_key_name;> value_is_ok;127.0.0.1:6379 > set random_key_name value_is_ok;> ok
Copy the code

If value_is_OK can get the value back, but the client failed to set the value… Well, that’s not quite right. That’s gonna lose data, too

There’s something wrong there, but I can’t put my finger on it…

💡 Therefore, this operation needs to be done in a command. Lua is used to “back up” values. So the script needs to finish popping the value out of the list and then setting it to a string or hash.

Pop the message out of the queue and copy the message to string
(random_str_key) (random_str_key) (random_str_key) (random_str_key) (random_str_key) (random_str_key) (random_str_key
local list_key = KEYS[1];
local random_str_key = KEYS[2];
local res = {};

local opt_value = redis.call('lpop', list_key);
-- Operation failed
if (not opt_value) then
    res[1] = 2;
    res[2] = random_str_key;
    res[3] = 'nil';
    return res;
end

redis.call('set', random_str_key, opt_value);
res[1] = 1;
res[2] = random_str_key;
res[3] = opt_value;

return res;
Copy the code
Confirm that message consumption is complete
Delete string (); delete string (
local random_str_key = KEYS[1];
return redis.call('del',random_str_key);
Copy the code
Message consumption error, need to re-place the message queue
local list_key = KEYS[1];
local random_str_key = KEYS[2];
local res = {};

Get the message out first
local opt_value = redis.call('get', random_str_key);
Delete message
redis.call('del', random_str_key);
Return to the list
redis.call('rpush', list_key, opt_value);

res[1] = 1;
res[2] = random_str_key;
res[3] = opt_value;
return res;
Copy the code

So there are three scripts

local pullScript = "local list_key = KEYS[1]; local random_str_key = KEYS[2]; local res = {}; local opt_value = redis.call('lpop', list_key); if (not opt_value) then res[1] = 2; res[2] = random_str_key; res[3] = 'nil'; return res; end redis.call('set', random_str_key, opt_value); res[1] = 1; res[2] = random_str_key; res[3] = opt_value; return res;"

local ackScript ="local random_str_key = KEYS[1]; return redis.call('del',random_str_key);";



local cancelScript = "local list_key = KEYS[1]; local random_str_key = KEYS[2]; local res = {}; local opt_value = redis.call('get', random_str_key); redis.call('del', random_str_key); redis.call('rpush', list_key, opt_value); res[1] = 1; res[2] = random_str_key; res[3] = opt_value; return res;";


Copy the code

What are the downsides of this approach

A potential problem with this approach is that if the client crashes, the client is unable to manipulate messages without human intervention

In addition, the LPOP method will have messages that are not blocking reads, so there is no way to be responsive, so the client needs to constantly poll

Is there any other way

  • To be responsive, insert the id of the message into the list when the message is posted, copy it into the string, delete the result after the message is consumed, and re-insert the value into the list when it is cancelled

Find the 👍 code