当前位置:网站首页>Red envelope rain: a wonderful encounter between redis and Lua
Red envelope rain: a wonderful encounter between redis and Lua
2022-06-27 10:23:00 【InfoQ】

1 Overall process

- The operating system is configured with the total amount of red envelope rain activities and the number of red envelopes , Calculate the amount of each red packet in advance and store it in Redis in ;
- Grab the red packet rain interface , The user clicks on the red packet falling on the screen , Initiate a request to grab a red envelope ;
- TCP After the gateway receives the request to grab the red packet , Call the question answering system to grab the red envelope dubbo service , The essence of red envelope service is to execute Lua Script , Pass the result through TCP The gateway returns to the front end ;
- If users get red envelopes , Asynchronous tasks will start from Redis in Get the red packet information , Call the balance system , Return the amount to the user account .
2 Red envelopes Redis Design
- Same activity , Users can only grab red envelopes once ;
- The number of red envelopes is limited , A red packet can only be snatched by one user .
- Operation pre allocation red packet list ;

{
// Red envelope number
redPacketId : '365628617880842241'
// Red envelope amount
amount : '12.21'
}
- User red packet collection record list ;

{
// Red envelope number
redPacketId : '365628617880842241'
// Red envelope amount
amount : '12.21',
// The user id
userId : '265628617882842248'
}
- The user's red envelope is weight proof Hash surface ;

- adopt hexist Command to judge red packet collection record weight prevention Hash Has the user in the table received a red envelope , If the user has not received a red envelope , The process continues ;
- From the operation pre allocation red packet list rpop Send out a red packet data ;
- Operation red envelope receiving record weight proof Hash surface , call HSET The command stores the user's claim record ;
- Receive the red envelope information lpush Enter the user's red packet collection record list .
- Execute multiple commands , Whether atomicity can be guaranteed , If a command fails , Whether you can roll back ;
- In the process of execution , High concurrency scenarios , Whether isolation can be maintained ;
- The next steps depend on the results of the previous steps .
3 How things work
- The transaction open , Use MULTI , This command marks that the client executing this command switches from the non transactional state to the transactional state ;
- Order to join the team ,MULTI After opening the transaction , Client commands are not immediately executed , Instead, it is put into a transaction queue ;
- Execute a transaction or discard . If you receive EXEC The order of , The commands in the transaction queue will be executed , If it is DISCARD The transaction is discarded .
redis> MULTI
OK
redis> SET msg "hello world"
QUEUED
redis> GET msg
QUEUED
redis> EXEC
1) OK
1) hello world


4 The transaction ACID
4.1 Atomicity
redis> MULTI
OK
redis> SET msg "other msg"
QUEUED
redis> wrongcommand ### Deliberately write wrong commands
(error) ERR unknown command 'wrongcommand'
redis> EXEC
(error) EXECABORT Transaction discarded because of previous errors.
redis> GET msg
"hello world"
redis> MULTI
OK
redis> SET msg "other msg"
QUEUED
redis> SET mystring "I am a string"
QUEUED
redis> HMSET mystring name "test"
QUEUED
redis> SET msg "after"
QUEUED
redis> EXEC
1) OK
2) OK
3) (error) WRONGTYPE Operation against a key holding the wrong kind of value
4) OK
redis> GET msg
"after"
- The order to join the team is wrong , Will abandon the transaction execution , Guaranteed atomicity ;
- Normal when ordered to join the team , perform EXEC Error after command , There is no guarantee of atomicity ;
4.2 Isolation,
- Uncommitted read (read uncommitted)
- Submit to read (read committed)
- Repeatable (repeatable read)
- Serialization (serializable)
- EXEC Before the order is executed
- EXEC After the execution of the command
4.3 persistence
- No configuration RDB perhaps AOF , The durability of transactions cannot be guaranteed ;
- Used RDB Pattern , After a transaction is executed , Next time RDB Before the snapshot is executed , If an instance goes down , The persistence of transactions is also not guaranteed ;
- Used AOF Pattern ;AOF Three configuration options for mode no 、everysec There will be data loss .always It can ensure the persistence of transactions , But because of the poor performance , Generally, it is not recommended to use in production environment .
4.4 Uniformity
- Wikipedia
- perform EXEC Before the command , The operation command sent by the client is wrong , Transaction terminated , Data consistency ;
- perform EXEC After the command , The data types of the command and operation do not match , The wrong command will report an error , But the transaction will not be terminated by the wrong command , But will continue to carry out . The correct command is executed normally , The wrong command reports an error , From this point of view , Data can also be consistent ;
- In the course of executing a transaction ,Redis The service outage . Here we need to consider the persistence pattern of service configuration . No persistent memory mode : After the service is restarted , The database does not hold data , So the data is consistent ;RDB / AOF Pattern : After the service is restarted ,Redis adopt RDB / AOF File recovery data , The database will be restored to a consistent state .
- 《 Design data-intensive applications 》

- Guaranteed atomicity , Persistence and isolation , If none of these characteristics can be guaranteed , Then the consistency of transactions cannot be guaranteed ;
- The constraints of the database itself , For example, the string length cannot exceed the column limit or uniqueness constraint ;
- The business level also needs to be guaranteed .
4.5 summary
- Ensure isolation ;
- There is no guarantee of persistence ;
- With a certain degree of atomicity , But rollback is not supported ;
- There are differences in the concept of consistency , Suppose that the core of consistency is the semantics of constraints ,Redis The transaction can guarantee consistency .
5 Lua Script
5.1 brief introduction

- Reduce network overhead . Send multiple requests at a time in the form of scripts , Reduce network delay .
- Atomic manipulation .Redis The entire script is executed as a whole , The middle is not inserted by other commands .
- Reuse . The script sent by the client will be permanent Redis in , Other clients can reuse this script without having to use code to complete the same logic .
5.2 EVAL command
EVAL script numkeys key [key ...] arg [arg ...]
scriptIs the first parameter , by Lua 5.1 Script ;
- The second parameter
numkeysThere are several parameters for specifying subsequent parameters key;
key [key ...], It's the key to operate , You can specify multiple , stay Lua The script passesKEYS[1],KEYS[2]obtain ;
arg [arg ...], Parameters , stay Lua The script passesARGV[1],ARGV[2]obtain .
redis> eval "return ARGV[1]" 0 100
"100"
redis> eval "return {ARGV[1],ARGV[2]}" 0 100 101
1) "100"
2) "101"
redis> eval "return {KEYS[1],KEYS[2],ARGV[1]}" 2 key1 key2 first second
1) "key1"
2) "key2"
3) "first"
4) "second"
redis.call()redis> set mystring 'hello world'
OK
redis> get mystring
"hello world"
redis> EVAL "return redis.call('GET',KEYS[1])" 1 mystring
"hello world"
redis> EVAL "return redis.call('GET','mystring')" 0
"hello world"
5.3 EVALSHA command

redis> EVALSHA sha1 numkeys key [key ...] arg [arg ...]
redis> SCRIPT LOAD "return 'hello world'"
"5332031c6b470dc5a0dd9b4bf2030dea6d65de91"
redis> EVALSHA 5332031c6b470dc5a0dd9b4bf2030dea6d65de91 0
"hello world"
5.4 Business VS Lua Script
- for fear of Redis Blocking ,Lua Script business logic should not be too complex and time consuming ;
- Check and test carefully Lua Script , Because execution Lua Scripts have some atomicity , Rollback is not supported .
6 Actual combat preparation

// load Lua Script
String scriptLoad(String luaScript);
// perform Lua Script
Object eval(String shardingkey,
String luaScript,
ReturnType returnType,
List<Object> keys,
Object... values);
// adopt sha1 Summary execution Lua Script
Object evalSha(String shardingkey,
String shaDigest,
List<Object> keys,
Object... values);
public int calcSlot(String key) {
if (key == null) {
return 0;
}
int start = key.indexOf('{');
if (start != -1) {
int end = key.indexOf('}');
key = key.substring(start+1, end);
}
int result = CRC16.crc16(key.getBytes()) % MAX_SLOT;
log.debug("slot {} for {}", result, key);
return result;
}
7 Grab the red envelope script
- The user successfully grabbed the red envelope
{
"code":"0",
// Red envelope amount
"amount":"7.1",
// Red envelope number
"redPacketId":"162339217730846210"
}
- The user has received
{
"code":"1"
}
- The user failed to grab the red envelope
{
"code":"-1"
}
-- KEY[1]: User's anti weight claim record
local userHashKey = KEYS[1];
-- KEY[2]: Operation pre allocation red packet list
local redPacketOperatingKey = KEYS[2];
-- KEY[3]: User's red envelope receiving record
local userAmountKey = KEYS[3];
-- KEY[4]: The user id
local userId = KEYS[4];
local result = {};
-- Judge whether the user has received
if redis.call('hexists', userHashKey, userId) == 1 then
result['code'] = '1';
return cjson.encode(result);
else
-- Get red packet data from pre allocated red packets
local redPacket = redis.call('rpop', redPacketOperatingKey);
if redPacket
then
local data = cjson.decode(redPacket);
-- Join users ID Information
data['userId'] = userId;
-- Put the user number in the de duplicated hash ,value Set as red packet number
redis.call('hset', userHashKey, userId, data['redPacketId']);
-- Users and red packets are placed in the consumed queue
redis.call('lpush', userAmountKey, cjson.encode(data));
-- The return value of successful assembly
result['redPacketId'] = data['redPacketId'];
result['code'] = '0';
result['amount'] = data['amount'];
return cjson.encode(result);
else
-- Failed to grab the red envelope
result['code'] = '-1';
return cjson.encode(result);
end
end
- To write junit The test case ;
- from Redis 3.2 Start , Built in Lua debugger( abbreviation
LDB), have access to Lua debugger Yes Lua Script debugging .
8 Asynchronous task
- RedisMessageConsumer :Consumer class, Configure listening queue name , And the corresponding consumption listener
String groupName = "userGroup";
String queueName = "userAmountQueue";
RedisMessageQueueBuilder buidler =
redisClient.getRedisMessageQueueBuilder();
RedisMessageConsumer consumer =
new RedisMessageConsumer(groupName, buidler);
consumer.subscribe(queueName, userAmountMessageListener);
consumer.start();
- RedisMessageListener :Consumer monitor, Write business consumption code
public class UserAmountMessageListener implements RedisMessageListener {
@Override
public RedisConsumeAction onMessage(RedisMessage redisMessage) {
try {
String message = (String) redisMessage.getData();
// TODO Call the user balance system
// Return to consumption success
return RedisConsumeAction.CommitMessage;
}catch (Exception e) {
logger.error("userAmountService invoke error:", e);
// Consumption failure , Perform retry operation
return RedisConsumeAction.ReconsumeLater;
}
}
}
9 Wrote last

边栏推荐
- 实验笔记之——CARMEN (.log .clf)文件转换为rosbag
- 测试同学怎么参与codereview
- Oracle连接MySQL报错IM002
- 通俗易懂理解樸素貝葉斯分類的拉普拉斯平滑
- 在外企远程办公是什么体验? | 社区征文
- Learning notes - data set generation
- C语言学习-Day_04
- [200 opencv routines] 212 Draw a slanted rectangle
- Multi thread implementation rewrites run (), how to inject and use mapper file to operate database
- Your brain is learning automatically when you sleep! Here comes the first human experimental evidence: accelerate playback 1-4 times, and the effect of deep sleep stage is the best
猜你喜欢

Feedforward feedback control system design (process control course design matlab/simulink)

In the three-tier architecture, at which layer is the database design implemented, not at the data storage layer?

CPU design (single cycle and pipeline)

Une compréhension facile de la simplicité de la classification bayésienne du lissage laplacien

mysql数据库汉字模糊查询出现异常

Oracle trigger stored procedure writes at the same time

【TcaplusDB知识库】TcaplusDB Tmonitor模块架构介绍

三层架构中,数据库的设计在哪一层实现,不是在数据存储层吗?

leetcode:968. 监控二叉树【树状dp,维护每个节点子树的三个状态,非常难想权当学习,类比打家劫舍3】

Multi thread implementation rewrites run (), how to inject and use mapper file to operate database
随机推荐
2-4 installation of Nessus under Kali
C any() and aii() methods
Leetcode to do questions
TCP/IP 详解(第 2 版) 笔记 / 3 链路层 / 3.4 桥接器与交换机 / 3.4.1 生成树协议(Spanning Tree Protocol (STP))
软交换呼叫中心系统的支撑系统
audiotrack与audioflinger
Audiotrack and audiolinker
【TcaplusDB知识库】TcaplusDB机型管理介绍
R language uses econcharts package to create microeconomic or macro-economic charts, demand function to visualize demand curve, and customize the parameters of demand function to enrich the visualizat
Test how students participate in codereview
[200 opencv routines] 212 Draw a slanted rectangle
软件系统架构的演变
你睡觉时大脑真在自动学习!首个人体实验证据来了:加速1-4倍重放,深度睡眠阶段效果最好...
Only one confirmcallback is supported by each rabbittemplate
以后发现漏洞,禁止告诉中国!
On anchors in object detection
【TcaplusDB知识库】TcaplusDB新增机型介绍
Concepts of concurrency, parallelism, asynchronism, synchronization, multithreading and mutual exclusion
手机影像内卷几时休?
leetcode待做题目