1. Login module
The login module first verifies the user name and password. What I use here is email login. The email login code uses the public code of online csdn, and then uses my own QQ SMTP permission to obtain the authorization code to complete the email login requirements.
Because the user's password cannot be saved in plain text to the database, I use salt encryption here to ensure that the user's information will not be leaked. Because the back-end login verification is successful, a token must first be generated, and the token content stores the user's ID information. Then use redis for caching, use the user's logged-in username as the key, and then use the generated token as the value to save it to redis. This enables single sign-on.
If the visitor adds the item to the shopping cart but is not logged in, when he clicks to buy, he needs to log in and the information will be synchronized to the logged-in user's shopping cart. When the visitor adds the item to the shopping cart, the shopping cart data can be saved in the server session. middle. The session identifier can be sent to the user's browser in a response, in a cookie, so that the user's subsequent requests can carry the session identifier. When a user clicks to purchase and needs to log in, the user's browser sends the session identifier to the server. The server finds the corresponding session data based on the session identifier and associates it with the user's identity information.
Of course, there is also the case of repeated login. Using redis+JWT can solve the problem of repeated login.
Then use different permissions for different users. This permission mainly lies in the background management system. Mainly divided into ordinary users and administrative users. Usage permissions are mainly implemented based on SpringSecurity.
2. Gateway module
When the user logs in, he or she can access it. The gateway is used here as the request forwarding. When the user logs in successfully, if he accesses other interfaces, he will access them from the gateway.
3. Course modules
Course modules involve the addition, deletion, modification and review of content. Because this module has a lot of read operations, course information is often stored in the redis cache to reduce the access pressure on the database.
Two situations, cache penetration and cache avalanche, are taken into consideration here. The first case uses logical expiration. When the data is saved in redis, the expiration time is added to its field, and then the expiration time is output. When later accessing expired data, first obtain the course information from redis at the business layer, and then obtain the time and current time from the expiration time field to judge. If it has expired, use the thread pool to create a new thread to reset cache. The current thread directly returns the expiration time to ensure the user experience. When the child thread accesses the database to reset the cache and expiration time, the latest data can be returned to the user. Although there are data inconsistency issues, the user experience has been greatly improved. The second situation is a cache avalanche. Because a lot of course information is cached, a large number of redis cache failures may suddenly occur. The solution here is to add a random TTL to the expiration time of each cached data to avoid a large amount of data expiring at the same time. A large number of database accesses cause downtime.
There are other situations where course module data is inconsistent. For example, after the course information is modified, the old data is still stored in the cache, which leads to data inconsistency. Double delete can be used here to solve the inconsistency between database and cache data. First delete the cache, then go to the database to modify the data, and then delete the cache, avoiding data inconsistency problems caused by concurrent deletion operations.
4. Order module
This module uses RabbitMQ and Alipay third-party payment. Alipay third-party payment is completed in the Alipay sandbox environment because the individual does not have a business license.
For the use of RabbitMQ, after the user places an order, the order information will first be saved to the order table of the database, and then the order information will be sent to RabbitMQ. Generally, there is a 30-minute payment time after placing an order. If payment is not made during this time, the order will be canceled and the information in the order form will be deleted. Therefore, the delay queue function is used for this function, but since RabbitMQ does not have a delay queue, the delay queue can be implemented according to the characteristics of RabbitMQ, and the dead letter queue + TTL can be used to solve this problem.
Then when 30 minutes are up and there is no inventory purchased, the system will get the message from the delay queue and check whether the order table has been paid. If not, the order table will be deleted. If the user pays within 30 minutes, the paid field will be modified in the order form. The process is the same as above.
Of course, it is also possible that message loss occurs due to server downtime, causing RabbitMQ to have sent the message to the inventory system, but the inventory system is down and does not receive the message, and message loss may occur. There are three steps to deal with message loss: the producer uses the confirm mechanism, MQ uses persistence, and the consumer uses the ACK confirmation mechanism.
For producers, consumers can send an ack receipt to MQ after processing the message, and MQ will delete the message after receiving the ack receipt. This project adopts the manual ACK mode. If there is an exception, a resend message will be sent, and if it ends normally, a signature will be sent.
For MQ, persistence is used. In this project, switch persistence, queue persistence, and message persistence are used.
For consumers using the ACK confirmation mode, the message can be deleted only after receiving the consumer's confirmation message. Otherwise, the message will be left in the queue and wait for the retry mechanism to get the message from the queue. Manual mode is used for abnormal situations. Only after the inventory system has successfully processed it, the receipt will be manually signed. If there is an abnormality, the message will be automatically resent.
In order to solve the oversold situation, the distributed lock redisson is used to solve this problem. Because strong consistency needs to be ensured here, redisson is used to implement this function. When placing orders concurrently, use distributed locks to avoid oversold conditions.
Of course, if there are too many requests but the consumer cannot consume them, and messages accumulate in the queue, the solution is to either open the thread pool, increase the consumer's consumption capacity within the range allowed by the CPU, or expand the queue capacity. , increase the accumulation limit.