1. 程式人生 > >如何處理高併發情況下的DB插入

如何處理高併發情況下的DB插入

插入資料庫,在大家開發過程中是很經常的事情,假設我們有這麼一個需求:

1、我們需要接收一個外部的訂單,而這個訂單號是不允許重複的

2、資料庫對外部訂單號沒有做唯一性約束

3、外部經常插入相同的訂單,對於已經存在的訂單則拒絕處理

對於這個需求,很簡單我們會用下面的程式碼進行處理(思路:先查詢資料庫,如果資料庫存在則直接退出,否則插入)

package com.yhj.test;

import com.yhj.dao.OrderDao;

import com.yhj.pojo.Order;

/**

 * @Description:併發測試用例

 * @Author YHJ  create at 2011

-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-上午08:43:15

     * @throws

 Exception

     */

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

先去訪問DB,查詢沒有,開始插入,這時候執行緒2又來查詢DB,而此時執行緒1插入的事務還沒有提交,執行緒2沒有查到該資料,也進行插入,於是,問題出現了,插入了2條一樣訂單。

對於這種情況,好像如果不用資料庫做唯一性約束又不借助外部其他的一些工具,是沒有辦法實現的。那怎麼做呢?

引入快取,我們看下面的程式碼

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-上午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-上午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寫快取

執行緒

相關推薦

如何處理併發情況DB插入

插入資料庫,在大家開發過程中是很經常的事情,假設我們有這麼一個需求: 1、我們需要接收一個外部的訂單,而這個訂單號是不允許重複的 2、資料庫對外部訂單號沒有做唯一性約束 3、外部經常插入相同的訂單,對於已經存在的訂單則拒絕處理 對於這個需求,很簡單我們會用下面的

測試Nginx 和 Tomcat 併發情況處理靜態頁面的效能

以下是 ab 壓力測試的結果(為了得到比較科學的資料可以進行多次的測試,一般至少10次) ab 可執行檔案的位置 /usr/local/web/apache/bin 測試命令:ab -n1000

併發情況 如何支撐大量的請求

儘量使用快取,包括使用者快取,資訊快取等,多花點記憶體來做快取,可以大量減少與資料庫的互動,提高效能。用jprofiler等工具找出效能瓶頸,減少額外的開銷。優化資料庫查詢語句,減少直接使用hibernate等工具的直接生成語句(僅耗時較長的查詢做優化)。優化資料庫結構,多做索引,提高查詢效率。統計的功能儘量

java中如何處理併發情況

1.背景描述 併發就是可以使用多個執行緒同時處理不同的操作。 高併發的時候就是有很多使用者訪問,導致系統資料不正確。對於大型網站,比如入口網站。在面對大量使用者訪問,高併發請求方面,基本的解決方案集中在這樣幾個環節,使用高效能的伺服器,高效能的程式語言,還有高效能的web容

Java多執行緒:解決併發環境資料插入重複問題

1.背景描述 應用框架:Spring + SpringMVC + Hibernate  資料庫:Oracle11g 一家文學網站向我係統推多執行緒低併發推送資料,我這邊觀察日誌和資料庫,發現有

併發情況如何保證訊息的順序

      在知乎上看到一位大牛總結了一些保證訊息順序的方案,在此記錄下來學習一下。      在多佇列訊息處理的場景中,怎樣保持多個訊息之間的時間順序,是一個很經典的問題。解決方法當然是有的。        為了討論這個問題,讓我們做一些簡化問題的假設:有若干個訊息佇列A、

併發情況Redis 的可用性測試與分析及部署架構說明

1、讀取Redis的timeout異常 建立執行緒數在50以下時程式可以正常執行,當執行緒數設定為100以上時,某些執行緒執行出現異常: java.net.SocketTimeoutException: Read timed out 造成這種異常可能有以下兩個原因: 原因一:在連線Redis的Jedis的預設

Mysql在併發情況,防止庫存超賣而小於0的解決方案

背景: 本人上次做申領campaign的PHP後臺時,因為專案上線後某些時段同時申領的人過多,導致一些專櫃的存貨為負數(<0),還好併發量不是特別大,只存在於小部分專櫃而且一般都是-1的狀況,沒有造成特別特別嚴重的後果,但還是要反思了自己的過錯。   這次又有新的申

提高MySQL在併發情況的負載

(只作為日後參考的記錄,沒有實際測試過) TCMalloc(Thread-Caching Malloc)是google開發的開源工具──“google-perftools”中的成員。與標準的glibc庫的malloc相比,TCMalloc在記憶體的分配上效率和速度要高得多

Redis鎖機制處理併發

文章正文   這裡我們主要利用Redis的setnx的命令來處理高併發。 setnx 有兩個引數。第一個引數表示鍵。第二個引數表示值。如果當前鍵不存在,那麼會插入當前鍵,將第二個引數做為值。返回 1。如果當前鍵存在,那麼會返回0。 建立庫存表 CREATE T

過年了,又要處理併發

涉及搶購、秒殺、抽獎、搶票等活動時,為了避免超賣,那麼庫存數量是有限的,但是如果同時下單人數超過了庫存數量,就會導致商品超賣問題。 sql1:秒殺 if(庫存數量 > 0) {   //生成訂單...  //sql2  //庫存-1 } 當

併發情況引發的血案

首先澄清一下,最近更博比較少,最近在研究新的東西的同時還有大量的任務在做,這個月會繼續的更新,把rabbitmq的系列更新完成,同時把我研究的新的東西的完整的系列也整理髮布出來,大家一起學習進步。 一、問題描述: 很多時候面試都會被問到併發的問題,那個時候我們總覺的遇不到這種

PHP 利用檔案鎖處理併發

利用 flock()函式對檔案進行加鎖(排它鎖),實現併發按序進行。 flock(file,lock,block)有三個引數。 file : 已經開啟的檔案 lock : 鎖的型別 LOCK_SH : 共享鎖定(讀鎖) LOCK_EX : 獨佔鎖定(排它鎖,寫鎖

訊息佇列處理併發

用mq來將耗時比較長或者耗費資源的請求排隊,非同步處理,減輕伺服器壓力增加穩定性。如果是高併發的實時請求,我個人覺得不適用這個方案。如果是為了高併發,我覺得應該朝解決高併發的方向考慮。叢集、分散式、動靜分離、資料庫讀寫分離之類的。web的話,只能客戶端頁面輪訓處理結果。因為,據我個人瞭解啊,現

如何解決jquery.jsonp請求在併發情況容易發生異常的bug

知道現在使用jsonp的公司越來越少了,似乎有比jsonp更好的跨域方案。但是我發現騰訊視屏、愛奇藝視訊、優酷土豆等大型網際網路公司還在使用它時,我決定寫一篇文章徹底解決jsonp在併發條件下報錯的問題。畢竟jsonp有最好的相容性。 先附上原始碼連線 Github

Java處理併發量訪問的處理總結

結合之前做的一個網站,專案中分了幾個子專案,主要用到Redis,service(server)層和control層分離,有做了快取,頁面也是進行靜態化(htm和freemarker),仔細想想,整個專案基本吻合高併發,負載均衡的處理。在網上找了些資料,基本和專案的特點吻合,特別紀念一下,但是後面的一

併發場景的快取有哪些常見的問題?

一、快取一致性問題 當資料時效性要求很高時,需要保證快取中的資料與資料庫中的保持一致,而且需要保證快取節點和副本中的資料也保持一致,不能出現差異現象。 這就比較依賴快取的過期和更新策略。一般會在資料發生更改的時,主動更新快取中的資料或者移除對應的快取。 二、快取併發

java處理併發問題的解決發案

      隨著網際網路業務的不斷豐富,網站相關的技術經過這些年的發展,已經細分到很細的方方面面,尤其對於大型網站來說,所採用的技術更是涉及面非常廣,從硬體到軟體、程式語言、資料庫、WebServer、防火牆等各個領域都有了很高的要求,已經不是原來簡單的html靜態網站所能比

快取在併發場景的常見問題 侵立刪

快取一致性問題 當資料時效性要求很高時,需要保證快取中的資料與資料庫中的保持一致,而且需要保證快取節點和副本中的資料也保持一致,不能出現差異現象。這就比較依賴快取的過期和更新策略。一般會在資料發生更改的時,主動更新快取中的資料或者移除對應的快取。

Java-15-tomcat7在大併發情況報錯、閃退解決辦法

最近執行1年多的實時公交查詢系統,突然一天掛掉兩次,懵逼了。 大併發量下,tomcat7.0.54報錯:org.apache.tomcat.util.net.AprEndpoint$Poller run Poller failed with error [610,038]