当前位置:网站首页>Design a red envelope grabbing system
Design a red envelope grabbing system
2022-07-06 23:34:00 【OoZzzy】
List of articles
- 1. Demand analysis
- 2. Table structure design
- 3. Implementation based on distributed lock
- 4. Implementation based on optimistic lock
- 5. Implementation based on pessimistic lock
- 6. Pre allocate red packets , Implementation based on optimistic lock
- 7. be based on Redis Implementation of queues
- 8. be based on Redis queue , Asynchronous storage
1. Demand analysis
Common red envelope systems , Amount specified by the user 、 The total number of red packets is used to complete the creation of red packets , Then the red packet is distributed to the target user through a certain portal , After the user sees the red envelope , Click red envelope , Get red packets randomly , Last , Users can view the red packets they have grabbed . The whole business process is not complicated , The difficulty lies in Grab a red envelope
This behavior may have High concurrency
. therefore , The optimization point of system design mainly focuses on Grab a red envelope
In this behavior .
- Hand out red envelopes : The user sets the total amount of red packets 、 Total quantity
- Grab a red envelope : The user gets a certain amount randomly from the total red packet
High availability must be ensured for red packets , Otherwise, users will be very angry . secondly , The consistency of system data must be ensured, and no over issuance is allowed , Otherwise, users who get red packets will not receive money , Users will be angry . And finally , The system may have high concurrency .
2. Table structure design
Red envelope activity table
CREATE TABLE `t_redpack_activity`
(
`id` bigint(20) NOT NULL COMMENT ' Primary key ',
`total_amount` decimal(10, 2) NOT NULL DEFAULT '0.00' COMMENT ' Total sum ',
`surplus_amount` decimal(10, 2) NOT NULL DEFAULT '0.00' COMMENT ' The remaining amount ',
`total` bigint(20) NOT NULL DEFAULT '0' COMMENT ' Total number of red packets ',
`surplus_total` bigint(20) NOT NULL DEFAULT '0' COMMENT ' Total remaining red packets ',
`user_id` bigint(20) NOT NULL DEFAULT '0' COMMENT ' The user id ',
`version` bigint(20) NOT NULL DEFAULT '0' COMMENT ' Version number ',
PRIMARY KEY (`id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8;
Red envelope table
CREATE TABLE `t_redpack`
(
`id` bigint(20) NOT NULL COMMENT ' Primary key ',
`activity_id` bigint(20) NOT NULL DEFAULT 0 COMMENT ' Red envelope activity ID',
`amount` decimal(10, 2) NOT NULL DEFAULT '0.00' COMMENT ' amount of money ',
`status` TINYINT(4) NOT NULL DEFAULT 0 COMMENT ' Red envelope status 1 You can use 2 Unavailable ',
`version` bigint(20) NOT NULL DEFAULT '0' COMMENT ' Version number ',
PRIMARY KEY (`id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8;
A detailed list
CREATE TABLE `t_redpack_detail`
(
`id` bigint(20) NOT NULL COMMENT ' Primary key ',
`amount` decimal(10, 2) NOT NULL DEFAULT '0.00' COMMENT ' amount of money ',
`user_id` bigint(20) NOT NULL DEFAULT '0' COMMENT ' The user id ',
`redpack_id` bigint(20) NOT NULL DEFAULT '0' COMMENT ' Red envelope number ',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT ' Creation time ',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT ' Update time ',
PRIMARY KEY (`id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8;
Activity list , Is how many red envelopes you sent , And the remaining amount needs to be maintained . The schedule is the red packet details that the user grabs . The red packet table is the information of each specific red packet . Why do you need three tables ? In fact, if there is no red envelope table, it is OK . However, our scheme needs to use a table to record the information of red packets in advance , That's why the table was designed .
3. Implementation based on distributed lock
The implementation based on distributed lock is the simplest and crudest , The whole red packet interface is used to activityId As key To lock , Ensure that the same batch of red packet robbing is executed serially . The implementation of distributed locks is implemented by spring-integration-redis The project provides , The core class is RedisLockRegistry. Lock through Redis Of lua Script implementation , And it realizes blocking local reentrant .
4. Implementation based on optimistic lock
The second way , Add optimistic lock version control to the red packet activity table , When multiple threads update the same activity table at the same time , only one clien You will be successful . Other failures client Cycle retry , Set a maximum number of cycles . This scheme can realize the processing in the case of concurrency , But the conflict is great . Because only one person will succeed at a time , other client Need to try again , Even if you try again, only one person can succeed at a time , therefore TPS Very low . When the set number of failed retries is less than the number of red packets issued , It may lead to someone not grabbing the red envelope in the end , In fact, there are still red envelopes left .
5. Implementation based on pessimistic lock
Due to the increase of red packet activity table, optimistic lock conflicts are very large , So consider using pessimistic locks :select * from t_redpack_activity where id = #{id} for update, Note that pessimistic locks must be used in transactions . here , All red packet grabbing becomes serial . In this case , Pessimistic locks are far more efficient than optimistic locks .
6. Pre allocate red packets , Implementation based on optimistic lock
You can see , If we add the dimension of Le Guan lock to the red packet details , Then the conflict will be reduced . Because the red packet details were created after the user grabbed them , Now you need to pre allocate red packets , That is, when you create a red packet activity, you will generate N Red envelopes , Control availability through status / Unavailable . such , When more than one client When you grab a red envelope , Get all available red packet details under this activity , Randomly return one of them and then update it , The successful update means that the user has grabbed the red packet , Failure is a sign of conflict , You can cycle through retry . such , Conflict is reduced .
7. be based on Redis Implementation of queues
Similar to the previous scheme , however , A corresponding number of red envelopes will be created when users issue red envelopes , And join in Redis In line . When grabbing a red envelope, it will pop up .Redis The queue fits our needs very well , There will be no duplicate elements in each pop-up , Destroy when used up . defects : When grabbing a red envelope, once it pops out of the queue , At this point the system crashes , After recovery, the details of red packets in this queue have been lost , Manual compensation is required .
8. be based on Redis queue , Asynchronous storage
In this scheme, you do not operate the database after you get the red packet , Instead, it saves persistent information to Redis in , Then return to success . Through another thread UserRedpackPersistConsumer, Pull the persistent information for warehousing . It should be noted that , In this case, if you use the normal pop There will still be crash point The problem of , So considering availability , Use here Redis Of BRPOPLPUSH operation , Pop up the element and add it to the backup queue , Ensure that the crash here can be automatically recovered through the backup queue . Crash recovery thread CrashRecoveryThread Pull backup information regularly , Go to DB Verify whether the persistence is successful , If successful, clear this element , Otherwise, compensate and clear this element . If an exception occurs during the operation of the database, the error log will be recorded redpack.persist.log, This log uses a separate file and format , Easy to compensate ( Generally not triggered ).
Redis High availability is required .
边栏推荐
- The programmer said, "I'm 36 years old, and I don't want to be rolled, let alone cut."
- 基于PaddlePaddle平台(EasyDL)设计的人脸识别课堂考勤系统
- 吴恩达2022机器学习课程评测来了!
- If the request URL contains jsessionid, the solution
- B 站弹幕 protobuf 协议还原分析
- 【系统分析师之路】第七章 复盘系统设计(面向服务开发方法)
- Implementation steps of mysql start log in docker
- Laravel8 uses passport authentication to log in and generate a token
- Why are some people still poor and living at the bottom of society even though they have been working hard?
- 自动更新Selenium驱动chromedriver
猜你喜欢
Isomorphism + cross end, knowing applet +kbone+finclip is enough!
How to implement Lua entry of API gateway
mysql连接vscode成功了,但是报这个错
Flutter life cycle
Koa2 addition, deletion, modification and query of JSON array
使用MitmProxy离线缓存360度全景网页
The problem of ASP reading Oracle Database
PDF批量拆分、合并、书签提取、书签写入小工具
koa2对Json数组增删改查
JDBC programming of MySQL database
随机推荐
AcWing 4299. Delete point
MySQL数据库之JDBC编程
Daily question brushing record (XV)
Graphite document: four countermeasures to solve the problem of enterprise document information security
(flutter2) as import old project error: inheritfromwidgetofexacttype
How much does the mlperf list weigh when AI is named?
The programmer refused the offer because of low salary, HR became angry and netizens exploded
士大夫哈哈哈
Win11怎么恢复传统右键菜单?Win11右键改回传统模式的方法
请问async i/o可以由udf算子实现然后用sql api调用吗?目前好像只看到Datastre
华为云GaussDB(for Redis)揭秘第21期:使用高斯Redis实现二级索引
Where does this "judge the operation type according to the op value and assemble SQL by yourself" mean? It means simply using Flink tab
Flutter life cycle
What can be done for traffic safety?
GPT-3当一作自己研究自己,已投稿,在线蹲一个同行评议
Leetcode problem solving - 889 Construct binary tree according to preorder and postorder traversal
Gradle知識概括
《数字经济全景白皮书》保险数字化篇 重磅发布
Summary of three methods for MySQL to view table structure
Résumé des connaissances de gradle