Recently, I was engaged in a second kill activity, considering the performance and response speed, using redis. When writing, I paid special attention to the prevention of supersending. the cas (checkandset) optimistic lock based on redis theory should be able to prevent this problem, but it still appeared, i'm confused. please help me ,... recently, I was engaged in a second kill activity, considering the performance and response speed, using redis. When writing, I paid special attention to the prevention of supersending. the cas (check and set) optimistic lock based on redis theory should be able to prevent this problem, but it still appeared, I am confused. please help me. the specific code is roughly as follows:
Connect ('10. 10.10.119 ', 6379); $ mywatchkey = $ redis-> get ("mywatchkey"); $ rob_total = 100; // quantity of purchases if ($ mywatchkey <$ rob_total) {$ redis-> watch ("mywatchkey"); $ redis-> multi (); // sets the latency to facilitate testing. Sleep (5); // Insert the snapped up data $ redis-> hSet ("mywatchlist", "user_id _". mt_rand (1, 9999), time (); $ redis-> set ("mywatchkey", $ mywatchkey + 1); $ rob_result = $ redis-> exec (); if ($ rob_result) {$ mywatchlist = $ redis-> hGetAll ("mywatchlist"); echo "snapped up!
"; Echo" remaining quantity: ". ($ rob_total-$ mywatchkey-1 )."
"; Echo" user list:
"; Var_dump ($ mywatchlist);} else {echo" bad luck, buy again! "; Exit ;}}?>
Reply content:Recently, I was engaged in a second kill activity, considering the performance and response speed, using redis. When writing, I paid special attention to the prevention of supersending. the cas (check and set) optimistic lock based on redis theory should be able to prevent this problem, but it still appeared, I am confused. please help me. the specific code is roughly as follows:
Connect ('10. 10.10.119 ', 6379); $ mywatchkey = $ redis-> get ("mywatchkey"); $ rob_total = 100; // quantity of purchases if ($ mywatchkey <$ rob_total) {$ redis-> watch ("mywatchkey"); $ redis-> multi (); // sets the latency to facilitate testing. Sleep (5); // Insert the snapped up data $ redis-> hSet ("mywatchlist", "user_id _". mt_rand (1, 9999), time (); $ redis-> set ("mywatchkey", $ mywatchkey + 1); $ rob_result = $ redis-> exec (); if ($ rob_result) {$ mywatchlist = $ redis-> hGetAll ("mywatchlist"); echo "snapped up!
"; Echo" remaining quantity: ". ($ rob_total-$ mywatchkey-1 )."
"; Echo" user list:
"; Var_dump ($ mywatchlist);} else {echo" bad luck, buy again! "; Exit ;}}?>
I think this code will still be sold out in high concurrency. Assume that when there is only one prize, three people will execute the prize at the same time.$redis->watch("mywatchkey")
The data obtained is 99, so the sales volume is oversold.
Becauseredis
It is read by a single thread, so use the simplest queue.
Write the number of prizes into the lotteryredis
Queueaward:100
// List with a length of 100. The value is only used as whether to win the prize.
Concurrent lottery
$ Award = $ redis-> lpop ('award: 100'); // since the queue has only 100 values, make sure that only 100 people win the prize if (! $ Award) {echo "bad luck, buy again! "; Exit;} // The rest is about the winning operation.
Sleep (5 );
Isn't your company accepting people?
Consider this situation.
Mywatchkey = 99
User A requests mywatchkey to get 99,
User B requests mywatchkey to get 99,
What is the value of mywatchkey after A and B are completed .. 101, or 100?
This is a classic Check-then-Act error.
First, let's ask if the code's "superselling" result is $ mywatchkey> 100 (I don't think it will happen)
Or $ mywatchkey = 100 at the same time there are two pages that show "flash sale successful! "
I didn't test the code. I just wondered if it would be the following:
1. Session A: check mywatchkey. at this time, mywatchkey = 99
2. Session B: after mywatchkey is processed, mywatchkey = 100 does not affect subsequent operations of Session.
Add two more connections. let's take a look. There may be gains.
Transactions-and-watch-statement-in-redis
Redis-watch-multi-exec-by-one-client
If you want to solve this problem fundamentally, first learn:
1. lock.
2. traditional database transactions.
Then we will learn the difference between Redis and traditional databases.