鍍金池/ 問答/PHP  數(shù)據(jù)庫/ mysql高并發(fā)時候投票問題 如何優(yōu)化

mysql高并發(fā)時候投票問題 如何優(yōu)化

比如一萬人給一個人投票
我的做法是先是讀取票數(shù)然后在票數(shù)+1
但是一萬人同時投票的話 獲取票數(shù)和更新肯定獲取的不對

代碼如下 用的是phpcms 請問大神該怎么優(yōu)化 代碼就這么點 結(jié)構(gòu)簡單的 就是投票人比較多

//根據(jù)ID獲取票數(shù)
$r = $db->get_one(array('id' => intval($_GET['id'])));
//票數(shù)累計并更新票數(shù)
$num = $r['num'] + 1;
$sql = array('num' => $num);
$db->update($sql, array('id' => intval($_GET['id'])));
回答
編輯回答
溫衫

針對于這個需求,我有兩步方案

1.將用戶點擊投票或者取消投票的總數(shù)放到緩存中,redis,memcache都可以,建議redis;

2.將某個用戶是否投票,放入緩存,同上;

3.用戶展示的以及判斷的數(shù)據(jù)邏輯,直接走緩存,然后再通過定時腳本同步數(shù)據(jù)到mysql服務器上;

4.如果為了保險起見可以在更新或者寫入的時候加鎖,保證數(shù)據(jù)的一致性,前提條件要根據(jù)邏輯來,不會出現(xiàn)死鎖。

2017年4月17日 15:11
編輯回答
尐飯團

只要不對表造成死鎖,控制好高并發(fā),基本上沒有問題,不用非得把表鎖死。做好異步處理

2018年6月26日 01:51
編輯回答
陌顏

如果只是保證數(shù)據(jù)正常, 那可以事務加排它鎖來搞.

按理說會先存到redis里面, 投票結(jié)束了才寫入數(shù)據(jù)庫

2018年4月28日 09:05
編輯回答
胭脂淚

看你的并發(fā)有多高、服務器性能有多好了。
簡單來講,有幾點可以處理你的問題。

  1. 使用redis列表記錄每個人的投票,異步去處理數(shù)據(jù)庫。
  2. 數(shù)據(jù)庫加鎖,不過在高并發(fā)(如只有一臺低檔服務器+一萬個人3s內(nèi)同時訪問)時能不能扛得住要看信仰。
  3. 優(yōu)化你的表設計,這張表盡量簡單一些,選擇適當?shù)氖聞崭綦x級別。
  4. 服務器物理機換成硬盤讀寫性能更優(yōu)的。
2018年3月7日 14:48
編輯回答
只愛你

簡單點就直接MySQL上鎖,但是這樣性能會低很多。
可以利用redis,讀也從redis讀,更新也是更新redis里(incr操作),
開個任務等到投票結(jié)束,把緩存中投票數(shù)寫入到MySQL中。

2017年3月11日 01:43
編輯回答
心夠野

誠邀。

如果你不想或者不愿意將redis引入到phpcms中。
我沒有對phpcms進行過二次開發(fā),但是你可以在sql中直接進行相加,并非使用代碼去實現(xiàn)相加

update student set score=score+1 where id = 1

這樣就避免了投票不準確
如果有時間可以使用redis或者隊列去實現(xiàn)這個功能。

2017年4月29日 15:10
編輯回答
不歸路

這個投票我建議你用redis投票 然后定時更新到mysql 因為update可能造成鎖表,你還要select讀取票數(shù),在并發(fā)量很大的情況下可能直接會因為sql阻塞導致mysql gone away

2017年8月8日 01:10
編輯回答
汐顏

這其實是涉及到隊列控制,鎖的一個應用。即,當一個用戶寫的時候,將其先鎖起來,不給其它人控制數(shù)據(jù),直到一個修改完成,然后才到下一個人進行修改。
可以對 數(shù)據(jù)鎖 或者 數(shù)據(jù)隊列 查找下相關(guān)文章進行了解。具體實現(xiàn)可以通過臨時表進行隊列排序,逐個處理。當然,如果處理高并發(fā)數(shù)據(jù),一般都會用牛刀諸如 redis 等數(shù)據(jù)庫進行主從數(shù)據(jù)處理會比較好。

2017年12月10日 15:14