• 数据库选型之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
      如果,您认为阅读这篇博客让您有些收获,不妨点击一下右下角的【推荐】。
      如果,您希望更容易地发现我的新博客,不妨点击一下左下角的【关注我】。
      如果,您对我的博客所讲述的内容有兴趣,请继续关注我的后续博客,我是【志青云集】。
      本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。


  • 相关阅读:
    PageObject小结
    python函数默认参数坑
    编译Android 8.0系统 并刷入pixel
    CF 289 F. Progress Monitoring DP计数
    EDU 61 F. Clear the String 区间dp
    Educational Codeforces Round 55 G 最小割
    Educational Codeforces Round 55 E 分治
    hdu 6430 bitset暴力
    AC自动机+DP codeforces86C
    CF895C dp/线性基
  • 原文地址:https://www.cnblogs.com/lyssym/p/4821788.html
Copyright © 2020-2023  润新知