如何處理高併發情況下的DB插入
插入資料庫,在大家開發過程中是很經常的事情,假設我們有這麼一個需求:
1、我們需要接收一個外部的訂單,而這個訂單號是不允許重複的
2、資料庫對外部訂單號沒有做唯一性約束
3、外部經常插入相同的訂單,對於已經存在的訂單則拒絕處理
對於這個需求,很簡單我們會用下面的程式碼進行處理(思路:先查詢資料庫,如果資料庫存在則直接退出,否則插入)
package com.yhj.test;
import com.yhj.dao.OrderDao;
import com.yhj.pojo.Order;
/**
* @Description:併發測試用例
* @Author YHJ create at 2011
* @FileName com.yhj.test.TestCase.java
*/
publicclass TestCase {
/**
* data access object class for deal order
*/
private OrderDao orderDao;
/**
* @Description:插入測試
* @param object 要插入的object例項
* @author YHJ create at 2011-7-7 上午08:43:15
* @throws
*/
publicvoid doTestForInsert(Order order) throws Exception {
Order orderInDB = orderDao.findByName(order.getOrderNo());
if(null != orderInDB)
thrownew Exception("the order has been exist!");
orderDao.save(order);
}
}
這樣很顯然,在單執行緒下是沒問題的,但是多執行緒情況下就會出現一個問題,執行緒1
對於這種情況,好像如果不用資料庫做唯一性約束又不借助外部其他的一些工具,是沒有辦法實現的。那怎麼做呢?
引入快取,我們看下面的程式碼
package com.yhj.test;
import com.yhj.dao.OrderDao;
import com.yhj.pojo.Order;
import com.yhj.util.MemcacheUtil;
import com.yhj.util.MemcacheUtil.UNIT;
/**
* @Description:併發測試用例
* @Author YHJ create at 2011-7-7 上午08:41:44
* @FileName com.yhj.test.TestCase.java
*/
publicclass TestCase {
/**
* data access object class for deal order
*/
private OrderDao orderDao;
/**
* @Description:插入測試
* @param object 要插入的object例項
* @author YHJ create at 2011-7-7 上午08:43:15
* @throws Exception
*/
publicvoid doTestForInsert(Order order){
String key=null;
try{
Order orderInDB = orderDao.findByName(order.getOrderNo());
//查DB,如果資料庫已經有則丟擲異常
if(null != orderInDB)
thrownew Exception("the order has been exist!");
key=order.getOrderNo();
//插快取,原子性操作,插入失敗表明已經存在
if(!MemcacheUtil.add(key, order, MemcacheUtil.getExpiry(UNIT.MINUTE, 1)))
thrownew Exception("the order has been exist!");
//插DB
orderDao.save(order);
}catch (Exception e) {
e.printStackTrace();
}finally{
MemcacheUtil.del(key);
}
}
}
執行步驟如下:
1、查詢資料庫,如果資料庫已經存在則丟擲異常
2、插入快取,如果插入失敗則表明快取中已經存在,丟擲異常
3、如果上述2步都沒有丟擲異常,則執行插入資料庫的操作
4、刪除快取
在併發的情況下,執行緒1先查詢資料庫,發現沒有,繼續執行,寫快取,這時候執行緒2開始查詢資料庫,發現沒有,則寫快取,結果快取中已經存在,寫快取失敗,丟擲異常,返回已存在。執行緒1執行插入資料庫成功,刪除快取。以後再來的執行緒發現數據庫已經存在了,則不在向下執行,直接返回.。
機器異常情況下,不能執行finally語句,但是放在memcache中的資料會在1分鐘後超時。
貌似沒有問題。使用LodeRunner測試100個併發的操作,發現仍然有重複的訂單插入,這個是為什麼呢?我們再來看這段程式碼!
publicvoid doTestForInsert(Order order){
String key=null;
try{
Order orderInDB = orderDao.findByName(order.getOrderNo());
//查DB,如果資料庫已經有則丟擲異常
if(null != orderInDB)
thrownew Exception("the order has been exist!");
key=order.getOrderNo();
//插快取,原子性操作,插入失敗表明已經存在
if(!MemcacheUtil.add(key, order, MemcacheUtil.getExpiry(UNIT.MINUTE, 1)))
thrownew Exception("the order has been exist!");
//插DB
orderDao.save(order);
}catch (Exception e) {
e.printStackTrace();
}finally{
MemcacheUtil.del(key);
}
}
我們所預料的是2個執行緒同時操作,假設有更多的併發執行緒呢?
時刻1:
執行緒1到達,查資料庫,發現沒有
時刻2
執行緒1寫快取
執行緒
插入資料庫,在大家開發過程中是很經常的事情,假設我們有這麼一個需求:
1、我們需要接收一個外部的訂單,而這個訂單號是不允許重複的
2、資料庫對外部訂單號沒有做唯一性約束
3、外部經常插入相同的訂單,對於已經存在的訂單則拒絕處理
對於這個需求,很簡單我們會用下面的
以下是 ab 壓力測試的結果(為了得到比較科學的資料可以進行多次的測試,一般至少10次)
ab 可執行檔案的位置 /usr/local/web/apache/bin
測試命令:ab -n1000 儘量使用快取,包括使用者快取,資訊快取等,多花點記憶體來做快取,可以大量減少與資料庫的互動,提高效能。用jprofiler等工具找出效能瓶頸,減少額外的開銷。優化資料庫查詢語句,減少直接使用hibernate等工具的直接生成語句(僅耗時較長的查詢做優化)。優化資料庫結構,多做索引,提高查詢效率。統計的功能儘量
1.背景描述
併發就是可以使用多個執行緒同時處理不同的操作。
高併發的時候就是有很多使用者訪問,導致系統資料不正確。對於大型網站,比如入口網站。在面對大量使用者訪問,高併發請求方面,基本的解決方案集中在這樣幾個環節,使用高效能的伺服器,高效能的程式語言,還有高效能的web容
1.背景描述
應用框架:Spring + SpringMVC + Hibernate
資料庫:Oracle11g
一家文學網站向我係統推多執行緒低併發推送資料,我這邊觀察日誌和資料庫,發現有
在知乎上看到一位大牛總結了一些保證訊息順序的方案,在此記錄下來學習一下。 在多佇列訊息處理的場景中,怎樣保持多個訊息之間的時間順序,是一個很經典的問題。解決方法當然是有的。 為了討論這個問題,讓我們做一些簡化問題的假設:有若干個訊息佇列A、 1、讀取Redis的timeout異常
建立執行緒數在50以下時程式可以正常執行,當執行緒數設定為100以上時,某些執行緒執行出現異常:
java.net.SocketTimeoutException: Read timed out
造成這種異常可能有以下兩個原因:
原因一:在連線Redis的Jedis的預設
背景:
本人上次做申領campaign的PHP後臺時,因為專案上線後某些時段同時申領的人過多,導致一些專櫃的存貨為負數(<0),還好併發量不是特別大,只存在於小部分專櫃而且一般都是-1的狀況,沒有造成特別特別嚴重的後果,但還是要反思了自己的過錯。
這次又有新的申
(只作為日後參考的記錄,沒有實際測試過)
TCMalloc(Thread-Caching Malloc)是google開發的開源工具──“google-perftools”中的成員。與標準的glibc庫的malloc相比,TCMalloc在記憶體的分配上效率和速度要高得多
文章正文
這裡我們主要利用Redis的setnx的命令來處理高併發。
setnx 有兩個引數。第一個引數表示鍵。第二個引數表示值。如果當前鍵不存在,那麼會插入當前鍵,將第二個引數做為值。返回 1。如果當前鍵存在,那麼會返回0。
建立庫存表
CREATE T
涉及搶購、秒殺、抽獎、搶票等活動時,為了避免超賣,那麼庫存數量是有限的,但是如果同時下單人數超過了庫存數量,就會導致商品超賣問題。
sql1:秒殺 if(庫存數量 > 0) { //生成訂單...
//sql2 //庫存-1 }
當
首先澄清一下,最近更博比較少,最近在研究新的東西的同時還有大量的任務在做,這個月會繼續的更新,把rabbitmq的系列更新完成,同時把我研究的新的東西的完整的系列也整理髮布出來,大家一起學習進步。
一、問題描述:
很多時候面試都會被問到併發的問題,那個時候我們總覺的遇不到這種
利用
flock()函式對檔案進行加鎖(排它鎖),實現併發按序進行。
flock(file,lock,block)有三個引數。
file : 已經開啟的檔案
lock : 鎖的型別
LOCK_SH : 共享鎖定(讀鎖)
LOCK_EX : 獨佔鎖定(排它鎖,寫鎖
用mq來將耗時比較長或者耗費資源的請求排隊,非同步處理,減輕伺服器壓力增加穩定性。如果是高併發的實時請求,我個人覺得不適用這個方案。如果是為了高併發,我覺得應該朝解決高併發的方向考慮。叢集、分散式、動靜分離、資料庫讀寫分離之類的。web的話,只能客戶端頁面輪訓處理結果。因為,據我個人瞭解啊,現
知道現在使用jsonp的公司越來越少了,似乎有比jsonp更好的跨域方案。但是我發現騰訊視屏、愛奇藝視訊、優酷土豆等大型網際網路公司還在使用它時,我決定寫一篇文章徹底解決jsonp在併發條件下報錯的問題。畢竟jsonp有最好的相容性。
先附上原始碼連線 Github
結合之前做的一個網站,專案中分了幾個子專案,主要用到Redis,service(server)層和control層分離,有做了快取,頁面也是進行靜態化(htm和freemarker),仔細想想,整個專案基本吻合高併發,負載均衡的處理。在網上找了些資料,基本和專案的特點吻合,特別紀念一下,但是後面的一
一、快取一致性問題
當資料時效性要求很高時,需要保證快取中的資料與資料庫中的保持一致,而且需要保證快取節點和副本中的資料也保持一致,不能出現差異現象。
這就比較依賴快取的過期和更新策略。一般會在資料發生更改的時,主動更新快取中的資料或者移除對應的快取。
二、快取併發
隨著網際網路業務的不斷豐富,網站相關的技術經過這些年的發展,已經細分到很細的方方面面,尤其對於大型網站來說,所採用的技術更是涉及面非常廣,從硬體到軟體、程式語言、資料庫、WebServer、防火牆等各個領域都有了很高的要求,已經不是原來簡單的html靜態網站所能比
快取一致性問題
當資料時效性要求很高時,需要保證快取中的資料與資料庫中的保持一致,而且需要保證快取節點和副本中的資料也保持一致,不能出現差異現象。這就比較依賴快取的過期和更新策略。一般會在資料發生更改的時,主動更新快取中的資料或者移除對應的快取。
最近執行1年多的實時公交查詢系統,突然一天掛掉兩次,懵逼了。
大併發量下,tomcat7.0.54報錯:org.apache.tomcat.util.net.AprEndpoint$Poller run Poller failed with error [610,038] 相關推薦
如何處理高併發情況下的DB插入
測試Nginx 和 Tomcat 高併發情況下處理靜態頁面的效能
高併發情況下 如何支撐大量的請求
java中如何處理高併發情況
Java多執行緒:解決高併發環境下資料插入重複問題
高併發情況下如何保證訊息的順序
高併發情況下Redis 的可用性測試與分析及部署架構說明
Mysql在高併發情況下,防止庫存超賣而小於0的解決方案
提高MySQL在高併發情況下的負載
Redis鎖機制處理高併發
過年了,又要處理高併發了
併發情況下引發的血案
PHP 利用檔案鎖處理高併發
訊息佇列處理高併發
如何解決jquery.jsonp請求在併發情況下容易發生異常的bug
Java處理高併發量訪問的處理總結
高併發場景下的快取有哪些常見的問題?
java處理高併發問題的解決發案
快取在高併發場景下的常見問題 侵立刪
Java-15-tomcat7在大併發情況下報錯、閃退解決辦法