node.js - 抽獎(jiǎng)碼設(shè)計(jì)問題
問題描述
程序的邏輯:
程序事先生成了抽獎(jiǎng)碼存在mysql中,然后有用戶來的以后,找到一個(gè)沒有用過的抽獎(jiǎng)碼給他,然后把這個(gè)抽獎(jiǎng)碼設(shè)置成為已經(jīng)使用過了
問題:當(dāng)大量用戶同時(shí)并發(fā)請(qǐng)求的時(shí)候,大部分用戶返回同一個(gè)抽獎(jiǎng)碼
原因大概是這樣子的
select codeid,codevalue from tb_code where isused=0 Limit 1
通過上面的sql找到一個(gè)沒有使用過的抽獎(jiǎng)碼
update tb_code set isused=1 where codeid=codeid
然后上面的sql語句是更新為已經(jīng)使用
當(dāng)大量用過過來的時(shí)候,比如A先取到一個(gè)碼XYBV,但是還沒有更新,B用戶也過來了的時(shí)候找到的也是這個(gè)碼值了。
code的返回都是在執(zhí)行完update以后返回
后來修改了下更新語句
update tb_code set isused=1 where isused=0 and codeid=codeid
根據(jù)affectedRows來判斷是不是更新成功了,如果成功的話,則返回code,否返回一個(gè)null
這樣雖然不會(huì)返回重復(fù)的值,但是會(huì)有一部分收不到碼值
再后來的搜了下,使用直接更新查找到碼值,最后再通過ranomno來查找剛才更新的碼值,如下面所示的sql
update tb_code set isused=1,randomno=’+randomno+’ where codeid in ( select codeid from (select codeid from tb_code where isused=0 Limit 1) as arbitraryTableName)’;
剛開始本地測試的時(shí)候,沒有問題,想著解決了。后來上線,檢測日志的時(shí)候,發(fā)現(xiàn)很多請(qǐng)求長時(shí)間沒有響應(yīng),應(yīng)該是上面的sql語句執(zhí)行的效率太低了。
最后換了一種方法使用redis緩存code
先從庫里面取1000個(gè)code使用Lpush放去redis里面去,然后當(dāng)用戶有請(qǐng)求過來,直接從redis里面取Rpop
然后做一個(gè)定時(shí)任務(wù),檢測redis里面的code數(shù)量,如果少于設(shè)定的數(shù)量,就從庫里面取1000個(gè)Lpush到redis里面去
現(xiàn)在項(xiàng)目跑了幾個(gè)小時(shí),暫時(shí)沒有發(fā)現(xiàn)請(qǐng)求超時(shí)的問題和碼值重復(fù)的問題。
但是感覺這種方式湊合能用,但不是最好的
想請(qǐng)問大家,對(duì)于類似的問題有沒有最佳實(shí)踐,比如在數(shù)據(jù)庫設(shè)計(jì)和程序結(jié)構(gòu)上
問題解答
回答1:你可以事先生成所有的code,放redis里,這樣不用一千一千的再去弄了。
你也可以用mongodb,查詢修改數(shù)據(jù)庫并發(fā)性能也挺強(qiáng)的;
回答2:可以試試mysql 的事務(wù)呢?http://dwz.cn/3SrgGk
回答3:抽獎(jiǎng)碼即時(shí)根據(jù)uid算一個(gè) 加一點(diǎn)隨機(jī)字符串
相關(guān)文章:
1. docker - 如何修改運(yùn)行中容器的配置2. 關(guān)docker hub上有些鏡像的tag被標(biāo)記““This image has vulnerabilities””3. Docker for Mac 創(chuàng)建的dnsmasq容器連不上/不工作的問題4. docker鏡像push報(bào)錯(cuò)5. html - css氣泡,實(shí)現(xiàn)“倒三角(不知道算不算三角了)”可透明的。6. javascript - 請(qǐng)指條明路,angular的$event,在select中卻是undefined?7. docker 下面創(chuàng)建的IMAGE 他們的 ID 一樣?這個(gè)是怎么回事????8. 我何時(shí)應(yīng)該在Java中使用JFrame.add(component)和JFrame.getContentPane()。add(component)9. java - 如何點(diǎn)擊按鈕,重新運(yùn)行(我是初學(xué)者)?10. 利用IPMI遠(yuǎn)程安裝centos報(bào)錯(cuò)!

網(wǎng)公網(wǎng)安備