數據庫選型之MySQL(多線程並發)


劉勇    Email: lyssym@sina.com

       本博客記錄作者在工作與研究中所經歷的點滴,一方面給自己的工作與生活留下印記,另一方面若是能對大家有所幫助,則幸甚至哉矣!

簡介

        鑒於高頻中心庫task部分占用機器較多,為節省成本,調研數據庫或緩存。在數據庫選型之MySQL(二)中,在固態硬盤本地訪問MySQL可以滿足其10000次/s操作的需求,由於實際環境中存在多個品種(多進程、多線程訪問數據庫)的業務需求,因此,本文采用多線程在固態硬盤本地訪問MySQL展開測試,以期對高頻中心庫后期架構調整提供實踐參考。需要指出,本文作者對該種節省成本的解決方案是不贊成的。

測試環境

        硬件環境

        10.1.120.34:Intel Core I5-4590, 主頻:3.30G,  內存:16G, 有固態硬盤

        軟件環境:

        10.1.120.34: Cent OS 6.5,  MySQL 5.6.26 (社區版)

性能測試

        針對高頻生產的應用需求,本文構造高頻中心庫系統的數據結構,采用多線程模擬業務需求對本地節點MySQL進行寫入操作,分別存儲數據總量為60K、100K、600K條數據,對其速率進行測試。需要指出,由於常見I/O訪問的瓶頸主要受限於寫入測試,本文只針對寫入操作進行測試,暫不考慮讀取操作或者混合讀寫方式,若寫入操作不滿足要求,其它操作無需測試。

        因為10.1.120.34上采用固態硬盤作為存儲介質,其安裝有MySQL,根據應用場景,分別從10、20、30個線程並發訪問MySQL 展開測試。

        測試整個結果見圖-1:

QQ截圖20150919163126

圖-1 完整測試結果

        10個線程

        從10個線程執行事務處理,需要指出,事務處理數據量固定為1000,以下多線程情況與之類同,不再贅述,10個線程的平均速率見表-1。

表-1  10個線程下每個線程平均訪問MySQL測試結果

節點

數據庫IP

數據量(K)

平均寫入速率(條/s)
本地節點 10.1.120.34 60 4085
本地節點 10.1.120.34 100 4607
本地節點 10.1.120.34 600 3021

         20個線程

         從20個線程執行事務處理,20個線程的平均速率見表-2。

表-2  20個線程下每個線程平均訪問MySQL測試結果

節點

數據庫IP

數據量(K)

平均寫入速率(條/s)
本地節點 10.1.120.34 60 1945
本地節點 10.1.120.34 100 2149
本地節點 10.1.120.34 600 1525

        30個線程

        從30個線程執行事務處理,30個線程的平均速率見表-3。

表-3  30個線程下每個線程平均訪問MySQL測試結果

節點

數據庫IP

數據量(K)

平均寫入速率(條/s)
本地節點 10.1.120.34 60 1266
本地節點 10.1.120.34 100 1461
本地節點 10.1.120.34 600 879

小結

        從表1-3可知:1)隨着線程數目增加,線程平均寫入速率會減小,而且還很明顯;2)隨着訪問的數據量的增加,以10萬條至60萬條為例,每個線程平均訪問其速率下降也很明顯。

        本文測試結果對高頻中心庫后續架構調整提供有一些實踐參考,若以平均速率乘以線程個數來衡量,則該高頻生產情形是滿足需求的,但是若出現不平衡狀況,則為節省成本采用將數據在固態硬盤本地入庫落地來生產,然后輔以redis作為緩存來緩解訪問系統訪問壓力的解決方案,本文作者是不贊成這種該方案的,希望對有類似業務需求的朋友有所幫助。

 

附錄:

測試部分程序源代碼:

  1 import java.sql.Date;
  2 import java.math.BigDecimal;
  3 
  4 public class Transaction {
  5     private Date tradedate; 
  6     private String symbol;
  7     private String symbolName;
  8     private String trdmintime;
  9     private BigDecimal startprice;
 10     private BigDecimal highprice;
 11     private BigDecimal lowprice;
 12     private BigDecimal endprice;
 13     private BigDecimal change;
 14     private BigDecimal changeratio;
 15     private BigDecimal minvolume;
 16     private BigDecimal minamout;
 17     private long unix;
 18     private String market;
 19     
 20     public Transaction(Date tradedate,
 21                         String symbol,
 22                         String symbolName,
 23                         String trdmintime,
 24                         BigDecimal startprice,
 25                         BigDecimal highprice,
 26                         BigDecimal lowprice,
 27                         BigDecimal endprice,
 28                         BigDecimal change,
 29                         BigDecimal changeratio,
 30                         BigDecimal minvolume,
 31                         BigDecimal minamout,
 32                         long unix,
 33                         String market)
 34     {
 35         this.symbol = symbol;
 36         this.symbolName = symbolName;
 37         this.trdmintime = trdmintime;
 38         this.startprice = startprice;
 39         this.highprice = highprice;
 40         this.lowprice = lowprice;
 41         this.endprice = endprice;
 42         this.change = change;
 43         this.changeratio = changeratio;
 44         this.minvolume = minvolume;
 45         this.minamout = minamout;
 46         this.unix = unix;
 47         this.market = market;
 48     }
 49 
 50     public void setTradedate(Date tradedate) {
 51         this.tradedate = tradedate;
 52     }
 53 
 54     public void setSymbol(String symbol) {
 55         this.symbol = symbol;
 56     }
 57 
 58     public void setSymbolName(String symbolName) {
 59         this.symbolName = symbolName;
 60     }
 61 
 62     public void setTrdmintime(String trdmintime) {
 63         this.trdmintime = trdmintime;
 64     }
 65 
 66     public void setStartprice(BigDecimal startprice) {
 67         this.startprice = startprice;
 68     }
 69 
 70     public void setHighprice(BigDecimal highprice) {
 71         this.highprice = highprice;
 72     }
 73 
 74     public void setLowprice(BigDecimal lowprice) {
 75         this.lowprice = lowprice;
 76     }
 77 
 78     public void setEndprice(BigDecimal endprice) {
 79         this.endprice = endprice;
 80     }
 81 
 82     public void setChange(BigDecimal change) {
 83         this.change = change;
 84     }
 85 
 86     public void setChangeratio(BigDecimal changeratio) {
 87         this.changeratio = changeratio;
 88     }
 89 
 90     public void setMinvolume(BigDecimal minvolume) {
 91         this.minvolume = minvolume;
 92     }
 93 
 94     public void setMinamout(BigDecimal minamout) {
 95         this.minamout = minamout;
 96     }
 97 
 98     public void setUnix(long unix) {
 99         this.unix = unix;
100     }
101 
102     public void setMarket(String market) {
103         this.market = market;
104     }
105 
106     public Date getTradedate() {
107         return tradedate;
108     }
109 
110     public String getSymbol() {
111         return symbol;
112     }
113 
114     public String getSymbolName() {
115         return symbolName;
116     }
117 
118     public String getTrdmintime() {
119         return trdmintime;
120     }
121 
122     public BigDecimal getStartprice() {
123         return startprice;
124     }
125 
126     public BigDecimal getHighprice() {
127         return highprice;
128     }
129 
130     public BigDecimal getLowprice() {
131         return lowprice;
132     }
133 
134     public BigDecimal getEndprice() {
135         return endprice;
136     }
137 
138     public BigDecimal getChange() {
139         return change;
140     }
141 
142     public BigDecimal getChangeratio() {
143         return changeratio;
144     }
145 
146     public BigDecimal getMinvolume() {
147         return minvolume;
148     }
149 
150     public BigDecimal getMinamout() {
151         return minamout;
152     }
153 
154     public long getUnix() {
155         return unix;
156     }
157 
158     public String getMarket() {
159         return market;
160     }
161 
162 }
Class Transaction
 1 import java.sql.Date;
 2 import com.gta.mysql.Transaction;
 3 import com.gta.mysql.Test;
 4 
 5 public class RunThread extends Thread {
 6     private Transaction ts;
 7     private int symbolData;
 8     private Test test;
 9     
10     public RunThread(Transaction ts, int symbolData, Test test) {
11         this.ts = ts;
12         this.symbolData = symbolData;
13         this.test = test;
14     }
15     
16         
17     public void run() 
18     {
19         long start = getRunTime();
20         for(int i = 0; i < ThreadTest.NUM*1000; i++) {
21             ts.setTradedate(new Date(System.currentTimeMillis()));
22             ts.setSymbol(Integer.toString(symbolData));
23             symbolData++;
24             ts.setSymbolName("中國銀行");
25             ts.setUnix(ts.getUnix()+1);
26             test.insertData(ts);
27         }
28         long end = getRunTime();
29         
30         System.out.println(ThreadTest.NUM*1000*1000/(end-start));
31     }
32 
33 
34     public long getRunTime()
35     {
36         return System.currentTimeMillis();
37     }
38 
39 }
Class RunThread
 1 import java.math.BigDecimal;
 2 import java.math.RoundingMode;
 3 import com.gta.mysql.Test;
 4 import com.gta.mysql.Transaction;
 5 
 6 public class ThreadTest {
 7     public static int MAX = 10;
 8     public static int NUM = Test.FIX/MAX;
 9     
10     
11     public static void main(String[] args) {
12         
13         Transaction [] ts = new Transaction[ThreadTest.MAX];
14         Test []test = new Test[ThreadTest.MAX];
15         int symbol = 100000;
16         for (int i = 0; i < ts.length; i++) {
17             ts[i] = new Transaction(null,
18                     "",
19                     "",
20                     "010000",
21                     new BigDecimal(15.857).setScale(3, RoundingMode.HALF_UP),
22                     new BigDecimal(18.550).setScale(3, RoundingMode.HALF_UP),
23                     new BigDecimal(13.147).setScale(3, RoundingMode.HALF_UP),
24                     new BigDecimal(16.383).setScale(3, RoundingMode.HALF_UP),
25                     new BigDecimal(0.151).setScale(3, RoundingMode.HALF_UP),
26                     new BigDecimal(1.550).setScale(3, RoundingMode.HALF_UP),
27                     new BigDecimal(5000000).setScale(3, RoundingMode.HALF_UP),
28                     new BigDecimal(500000000).setScale(3, RoundingMode.HALF_UP),
29                     System.currentTimeMillis(),
30                     "SSE");
31             test[i] = new Test();
32             
33         }
34 
35         
36         RunThread[] thread = new RunThread[ThreadTest.MAX]; 
37         for (int i = 0; i < thread.length; i++) {
38             test[i].initMySQL();
39             thread[i] = new RunThread(ts[i], symbol, test[i]);
40             symbol += ThreadTest.NUM*1000;
41         }
42         
43         for (int i = 0; i < thread.length; i++)
44             thread[i].start();
45         
46         while (true) {
47             try {
48                 Thread.sleep(1000);
49             } catch (InterruptedException e) {
50                 e.printStackTrace();
51                 test[0].down();
52             }
53         }
54         
55     }
56 
57 }
ThreadTest

 


  作者:志青雲集
  出處:http://www.cnblogs.com/lyssym
  如果,您認為閱讀這篇博客讓您有些收獲,不妨點擊一下右下角的【推薦】。
  如果,您希望更容易地發現我的新博客,不妨點擊一下左下角的【關注我】。
  如果,您對我的博客所講述的內容有興趣,請繼續關注我的后續博客,我是【志青雲集】。
  本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接。


 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM