The demand analysis of the red envelope robbery
The scene of the robbery is a bit like a second kill, but more simple than the second kill.
Because the second kill is usually related to inventory. And Rob Red envelopes can allow some red envelopes have not been robbed, because the people who send red envelopes will not have to lose, not to rob the money back to send a red envelope people can.
In addition, such as Millet to buy more simple than Taobao, but also because such as Millet is a company, if a small number did not Rob, the next time to rob, manual repair of the data is very simple. And like Taobao so many goods, if each has the risk of repairing data, then if the fault is very troublesome.
The scheme of red envelopes based on Redis
Here is a scheme based on Redis to rob red envelopes.
The original red envelopes are called Big Red envelopes, and the red envelopes after the split are called small red envelopes.
1. Small red envelopes are generated beforehand, inserted into the database, the red envelopes corresponding to the user ID is null. Build algorithm See another article: http://www.jb51.net/article/98620.htm
2. Each big red envelope corresponds to two redis queues, one is the unpaid red envelope queue, the other is the red envelope. At the beginning, put all the little red envelopes that were not robbed into a queue of unpaid red envelopes.
The unused red envelopes are JSON strings, such as {userId: ' 789 ', Money: ' 300 '}.
3. Use a map in the Redis to filter the users who have robbed the red envelopes.
4. Rob Red Envelopes, the first judge whether the user robbed red envelopes, if not, then never a red envelope to take out a small red envelope, and then push to another consumption queue, and finally put the user ID into the heavy map.
5. Use a single thread batch to take out the red envelopes in the consumption queue, and then batch update the user ID of the red envelopes into the database.
The above process is very clear, but in the 4th step, if the user quickly ordered two times, or opened two browser to rob Red envelopes, will it be possible for users to grab two red envelopes?
To solve this problem, the Lua script was adopted, allowing the entire process of step 4th to be executed atomically.
The following is a LUA script executed on the Redis:
--function: Try to get a red envelope, if successful, return the JSON string, if unsuccessful, return null
--parameter: Red envelope queue name, consumed queue name, go to heavy map name, user ID
--return value: Nil or JSON string, Contains user Id:userid, red envelope id:id, red envelope amount: Money
-If the user has robbed a red envelope, return nil if
rediscall (' hexists ', keys[3], keys[4]) ~= 0 Then
return nil
Else
--First take out a small red envelope local
Hongbao = Rediscall (' Rpop ', keys[1]);
If Hongbao then local
x = Cjsondecode (Hongbao);
--Adding User ID information
x[' userId ' = keys[4];
local re = Cjsonencode (x);
--Put the user ID in the heavy set
rediscall (' Hset ', keys[3], keys[4], keys[4);
--Put the red envelopes in the consumption queue
rediscall (' Lpush ', keys[2], re);
return re;
End End
Here is the test code:
public class Testeval {static String host = ' localhost ';
static int honbaocount = 1_0_0000;
static int threadcount = 20;
static String hongbaolist = "Hongbaolist";
static String hongbaoconsumedlist = "Hongbaoconsumedlist";
static String Hongbaoconsumedmap = "Hongbaoconsumedmap";
static Random Random = new Random (); --function: Try to get a red envelope, if successful, returns the JSON string, if unsuccessful, returns the null//--parameter: Red envelope queue name, consumed queue name, go to heavy map name, User ID//-return value: Nil or JSON string containing user Id:userid, red Packet Id:id, red envelope amount: money static String Trygethongbaoscript =//"Local bconsumed = Rediscall (' hexists ', keys[3], keys[4]
\ n "//+" print (' bconsumed: ', bconsumed); \ n "" If Rediscall (' hexists ', keys[3], keys[4]) ~= 0 then\n " + "return nil\n" + "else\n" + "local Hongbao = Rediscall (' Rpop ', keys[1]) \ n"//+ "print (' Hongbao: ', h
Ongbao); \ n "+" if Hongbao then\n "+" local x = Cjsondecode (hongbao); \ n "+" x[' userId '] = keys[4];\n " + "Local re = Cjsonencode (x); \ n "+" Rediscall (' Hset ', keys[3], keys[4], keys[4]) \ n "+" Rediscall (' Lpush ', keys[2], re); \ n "+"
return re;\n "+" end\n "+" end\n "+" return nil ";
Static Stopwatch watch = new stopwatch ();
public static void Main (string[] args) throws Interruptedexception {//Testeval ();
Generatetestdata ();
Testtrygethongbao ();
The static public void Generatetestdata () throws interruptedexception {Jedis Jedis = new Jedis (host);
Jedisflushall ();
Final Countdownlatch latch = new Countdownlatch (threadcount);
for (int i = 0; i < ThreadCount ++i) {Final int temp = i;
Thread thread = new Thread () {public void run () {Jedis Jedis = new Jedis (host);
int per = Honbaocount/threadcount;
Jsonobject object = new Jsonobject ();
for (int j = Temp */J < (temp+1) * per; J + +) {objectput ("id", j); Objectput ("Money", j);
Jedislpush (Hongbaolist, objecttojsonstring ());
} latchcountdown ();
}
};
ThreadStart ();
} latchawait (); static public void Testtrygethongbao () throws interruptedexception {final Countdownlatch latch = new COUNTD
Ownlatch (ThreadCount);
Systemerrprintln ("Start:" + Systemcurrenttimemillis ()/1000);
Watchstart ();
for (int i = 0; i < ThreadCount ++i) {Final int temp = i;
Thread thread = new Thread () {public void run () {Jedis Jedis = new Jedis (host);
String sha = Jedisscriptload (Trygethongbaoscript);
Int j = Honbaocount/threadcount * TEMP; while (true) {object = Jediseval (Trygethongbaoscript, 4, Hongbaolist, Hongbaoconsumedlist, hongbaocons
Umedmap, "" + j);
j + +;
if (object!= null) {//Systemoutprintln ("Get Hongbao:" + object); }else {//has finished the IF (Jedisllen (hongbaolist) = = 0) break;
} latchcountdown ();
}
};
ThreadStart ();
} latchawait ();
Watchstop ();
Systemerrprintln ("Time:" + watchgettotaltimeseconds ());
Systemerrprintln ("Speed:" + honbaocount/watchgettotaltimeseconds ());
Systemerrprintln ("End:" + Systemcurrenttimemillis ()/1000);
}
}
Test results of 20 threads, can rob 25,000 per second, enough to deal with most of the red envelopes scene.
If it is really unable to cope, split into a few redis clusters, or to bulk rob red envelopes, but also enough to deal with.
Summarize:
Redis's scheme, although in extreme cases (that is, Redis hang out) will lose a second of data, but it is a strong enough to cope with the high concurrent Robbery scheme.
The above is the entire content of this article, I hope to help you learn, but also hope that we support the cloud habitat community.