node.js - 抽獎(jiǎng)碼設(shè)計(jì)問(wèn)題
問(wèn)題描述
程序的邏輯:
程序事先生成了抽獎(jiǎng)碼存在mysql中,然后有用戶(hù)來(lái)的以后,找到一個(gè)沒(méi)有用過(guò)的抽獎(jiǎng)碼給他,然后把這個(gè)抽獎(jiǎng)碼設(shè)置成為已經(jīng)使用過(guò)了
問(wèn)題:當(dāng)大量用戶(hù)同時(shí)并發(fā)請(qǐng)求的時(shí)候,大部分用戶(hù)返回同一個(gè)抽獎(jiǎng)碼
原因大概是這樣子的
select codeid,codevalue from tb_code where isused=0 Limit 1
通過(guò)上面的sql找到一個(gè)沒(méi)有使用過(guò)的抽獎(jiǎng)碼
update tb_code set isused=1 where codeid=codeid
然后上面的sql語(yǔ)句是更新為已經(jīng)使用
當(dāng)大量用過(guò)過(guò)來(lái)的時(shí)候,比如A先取到一個(gè)碼XYBV,但是還沒(méi)有更新,B用戶(hù)也過(guò)來(lái)了的時(shí)候找到的也是這個(gè)碼值了。
code的返回都是在執(zhí)行完update以后返回
后來(lái)修改了下更新語(yǔ)句
update tb_code set isused=1 where isused=0 and codeid=codeid
根據(jù)affectedRows來(lái)判斷是不是更新成功了,如果成功的話,則返回code,否返回一個(gè)null
這樣雖然不會(huì)返回重復(fù)的值,但是會(huì)有一部分收不到碼值
再后來(lái)的搜了下,使用直接更新查找到碼值,最后再通過(guò)ranomno來(lái)查找剛才更新的碼值,如下面所示的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)’;
剛開(kāi)始本地測(cè)試的時(shí)候,沒(méi)有問(wèn)題,想著解決了。后來(lái)上線,檢測(cè)日志的時(shí)候,發(fā)現(xiàn)很多請(qǐng)求長(zhǎng)時(shí)間沒(méi)有響應(yīng),應(yīng)該是上面的sql語(yǔ)句執(zhí)行的效率太低了。
最后換了一種方法使用redis緩存code
先從庫(kù)里面取1000個(gè)code使用Lpush放去redis里面去,然后當(dāng)用戶(hù)有請(qǐng)求過(guò)來(lái),直接從redis里面取Rpop
然后做一個(gè)定時(shí)任務(wù),檢測(cè)redis里面的code數(shù)量,如果少于設(shè)定的數(shù)量,就從庫(kù)里面取1000個(gè)Lpush到redis里面去
現(xiàn)在項(xiàng)目跑了幾個(gè)小時(shí),暫時(shí)沒(méi)有發(fā)現(xiàn)請(qǐng)求超時(shí)的問(wèn)題和碼值重復(fù)的問(wèn)題。
但是感覺(jué)這種方式湊合能用,但不是最好的
想請(qǐng)問(wèn)大家,對(duì)于類(lèi)似的問(wèn)題有沒(méi)有最佳實(shí)踐,比如在數(shù)據(jù)庫(kù)設(shè)計(jì)和程序結(jié)構(gòu)上
問(wèn)題解答
回答1:你可以事先生成所有的code,放redis里,這樣不用一千一千的再去弄了。
你也可以用mongodb,查詢(xún)修改數(shù)據(jù)庫(kù)并發(fā)性能也挺強(qiáng)的;
回答2:可以試試mysql 的事務(wù)呢?http://dwz.cn/3SrgGk
回答3:抽獎(jiǎng)碼即時(shí)根據(jù)uid算一個(gè) 加一點(diǎn)隨機(jī)字符串
相關(guān)文章:
1. ios - vue-cli開(kāi)發(fā)項(xiàng)目webstrom會(huì)在stylus樣式報(bào)錯(cuò),飆紅,請(qǐng)大神幫忙2. css - 移動(dòng)端 oppo 手機(jī)之 Border-radius3. javascript - vue提示語(yǔ)法錯(cuò)誤,請(qǐng)問(wèn)錯(cuò)誤在哪?4. 淺談vue生命周期共有幾個(gè)階段?分別是什么?5. index.php錯(cuò)誤,求指點(diǎn)6. angular.js - angularjs中添加高德地圖API,地圖顯示不正常,控制臺(tái)報(bào)錯(cuò),何解?7. javascript - 為什么我的animation-fill-mode 設(shè)置不生效8. html - JavaScript的Dom操作如何改變子元素的文本內(nèi)容9. javascript - vue.js如何遞歸渲染組件.10. python - 抓包只抓到j(luò)son,真實(shí)的地址卻找不到
