PHP e-commerce orders automatically confirm receipt redis queue, e-commerce redis
I. Scenarios
On the previous e-commerce platform, most users do not take the initiative to click confirm the receipt after receiving the goods, resulting in various complaints from sellers when the seller settles the payment, so as to meet the needs, make an order to automatically confirm receipt x days after delivery. An update statement is executed at a specific time to change the order status.
Ii. Ideas
The most cumbersome method is to query qualified orders through scheduled tasks in the linux background, and then update them. Ideally, if there is an order to be updated every minute, this method would also work. However, the platform is too small, and the seller's delivery time is mostly intensive and will not be distributed within 24 hours per minute. Therefore, it is not suitable to query too many scheduled tasks. Here, we can store the order information that will be automatically confirmed and received to other media, such as redis, memcache, and rabbitmq, and then execute the script to obtain the order information from the previous media for determination, this greatly reduces the query pressure on the database.
Redis queue producer
In this regard, we choose to query the information about the order to be confirmed and received through the linux scheduled task at every day, and then store it on redis and the queue we selected on redis, queue processing is characterized by first-in-first-out. The previous data is sorted by the delivery time when querying the order. Therefore, the first-out queue must be the order closest to the specified automatic receipt time. The Code is as follows:
$ SuccessCount = 0; $ failCount = 0; $ screen_time = 3600*24*9; // set the number of days for filtering $ data = array (); $ now_time = time (); // query the data that meets the requirements $ SQL = "select id, send_time as deliver_time from 'order' where is_send = 1 and is_del = 0 and is_cancel = 0 and is_token = 0 and send_time> 0 and send_time + {$ screen_time} <$ now_time order by send_time asc "; $ res = $ con-> query ($ SQL); // records and clears while ($ redis-> LLEN ('Auto _ recevice_order ') when the queue has data ')) {$ txt = 'execution time :'. date ('Y-m-d H: I: s '). ', information :'. $ redis-> RPOP ('Auto _ recevice_order '); file_put_contents ('. /autoToken/fail_log.txt ', $ txt. "\ r \ n ". PHP_EOL, FILE_APPEND); $ failCount ++;} // refill the data in the queue while ($ row = $ res-> fetch_assoc () {$ successCount ++; $ redis-> LPUSH ('Auto _ recevice_order ', json_encode ($ row1);} $ con-> close (); $ success = date ('Y-m-d H: I: s '). ': [pushed successfully]: data pushed successfully this time :'. $ successCount. 'entries; record the data failed to be processed :'. $ failCount. "\ r \ n"; file_put_contents ('. /success_log.txt ', $ success. "\ r \ n ". PHP_EOL, FILE_APPEND );
Redis queue consumer
The queue consumers do not use linux scheduled tasks. They use linux screen + php cli mode to execute php scripts. Consumers only need to constantly read order information from the queue, then, judge the delivery time in the order information. If the automatic receipt requirement is met, execute the update statement. At the same time, if the receipt time is not reached, and the receipt time interval is relatively large, you can let the php script sleep for a certain amount of time, this number of time self-adjusted design, the obtained order that does not meet the time requirement needs to be pushed to the redis queue again, and it is still at the top of the queue. To be retrieved next time. The Code is as follows:
$ Set_time = 3600*24*10; // set Automatic receipt several days later while (true) {if ($ I % 30 = 0) {usleep (10 ); // prevent high CPU usage due to the while LOOP} if ($ redis-> LLEN ('Auto _ recevice_order ')) {$ data = json_decode ($ redis-> RPOP ('Auto _ recevice_order '); $ id = (int) $ data-> id; // convert data to integer $ deliver_time = (int) $ data-> deliver_time; // convert data to integer $ res1 = $ res2 = false; $ now_time = time (); if ($ deliver_time + $ set_time) <$ now_time) {$ sql1 = "update 'order' set 'is _ token' = '1 ', 'token _ time' = $ now_time where id = $ id and is_send = 1 and is_del = 0 and is_cancel = 0 and is_token = 0 and send_time + {$ set_time} <$ now_time"; $ res1 = $ con-> query ($ sql1); // update data $ rows = mysqli_affected_rows ($ con); if ($ rows) {$ ip = $ this-> getIp (); $ sql2 = "insert into 'order _ log' ('order _ id', 'Log _ msg ', 'Log _ ip', 'Log _ role', 'Log _ user', 'Log _ order_state ', 'Log _ Time') VALUES ($ id, 'automatic system shipping ',' $ ip', 'system', 'server', 'shipping ', $ now_time )"; // write Order Log $ res2 = $ con-> query ($ sql2); // Add log data} if ($ res1 = false) {// re-insert data that does not meet the conditions into the queue $ redis-> RPUSH ('Auto _ recevice_order ', json_encode (array ('id' => $ id, 'delimiter_time' => $ deliver_time) ;}}$ I ++ ;}
Run the php script here, and use the linux screen or supervisor or nohup daemon. For specific usage, you can use Baidu. It is best to have necessary log records in the same script.
Iii. Thinking
As the business grows, there are multiple orders to be processed in the same second in the queue. However, when only one order information can be retrieved from the queue at a time, one producer can be used for multiple consumers. In this case, the lock mechanism can be used to ensure that a message can only reach one consumer. When the amount of redis data reaches a certain level, you can also adjust the execution frequency and corresponding conditions of the producer.
For more original blogs, see personal independent blog: Portal