数据库选型之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:

图-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作为缓存来缓解访问系统访问压力的解决方案,本文作者是不赞成这种该方案的,希望对有类似业务需求的朋友有所帮助。
附录:
测试部分程序源代码:
import java.sql.Date;
import java.math.BigDecimal; public class Transaction {
private Date tradedate;
private String symbol;
private String symbolName;
private String trdmintime;
private BigDecimal startprice;
private BigDecimal highprice;
private BigDecimal lowprice;
private BigDecimal endprice;
private BigDecimal change;
private BigDecimal changeratio;
private BigDecimal minvolume;
private BigDecimal minamout;
private long unix;
private String market; public Transaction(Date tradedate,
String symbol,
String symbolName,
String trdmintime,
BigDecimal startprice,
BigDecimal highprice,
BigDecimal lowprice,
BigDecimal endprice,
BigDecimal change,
BigDecimal changeratio,
BigDecimal minvolume,
BigDecimal minamout,
long unix,
String market)
{
this.symbol = symbol;
this.symbolName = symbolName;
this.trdmintime = trdmintime;
this.startprice = startprice;
this.highprice = highprice;
this.lowprice = lowprice;
this.endprice = endprice;
this.change = change;
this.changeratio = changeratio;
this.minvolume = minvolume;
this.minamout = minamout;
this.unix = unix;
this.market = market;
} public void setTradedate(Date tradedate) {
this.tradedate = tradedate;
} public void setSymbol(String symbol) {
this.symbol = symbol;
} public void setSymbolName(String symbolName) {
this.symbolName = symbolName;
} public void setTrdmintime(String trdmintime) {
this.trdmintime = trdmintime;
} public void setStartprice(BigDecimal startprice) {
this.startprice = startprice;
} public void setHighprice(BigDecimal highprice) {
this.highprice = highprice;
} public void setLowprice(BigDecimal lowprice) {
this.lowprice = lowprice;
} public void setEndprice(BigDecimal endprice) {
this.endprice = endprice;
} public void setChange(BigDecimal change) {
this.change = change;
} public void setChangeratio(BigDecimal changeratio) {
this.changeratio = changeratio;
} public void setMinvolume(BigDecimal minvolume) {
this.minvolume = minvolume;
} public void setMinamout(BigDecimal minamout) {
this.minamout = minamout;
} public void setUnix(long unix) {
this.unix = unix;
} public void setMarket(String market) {
this.market = market;
} public Date getTradedate() {
return tradedate;
} public String getSymbol() {
return symbol;
} public String getSymbolName() {
return symbolName;
} public String getTrdmintime() {
return trdmintime;
} public BigDecimal getStartprice() {
return startprice;
} public BigDecimal getHighprice() {
return highprice;
} public BigDecimal getLowprice() {
return lowprice;
} public BigDecimal getEndprice() {
return endprice;
} public BigDecimal getChange() {
return change;
} public BigDecimal getChangeratio() {
return changeratio;
} public BigDecimal getMinvolume() {
return minvolume;
} public BigDecimal getMinamout() {
return minamout;
} public long getUnix() {
return unix;
} public String getMarket() {
return market;
} }
Class Transaction
import java.sql.Date;
import com.gta.mysql.Transaction;
import com.gta.mysql.Test; public class RunThread extends Thread {
private Transaction ts;
private int symbolData;
private Test test; public RunThread(Transaction ts, int symbolData, Test test) {
this.ts = ts;
this.symbolData = symbolData;
this.test = test;
} public void run()
{
long start = getRunTime();
for(int i = 0; i < ThreadTest.NUM*1000; i++) {
ts.setTradedate(new Date(System.currentTimeMillis()));
ts.setSymbol(Integer.toString(symbolData));
symbolData++;
ts.setSymbolName("中国银行");
ts.setUnix(ts.getUnix()+1);
test.insertData(ts);
}
long end = getRunTime(); System.out.println(ThreadTest.NUM*1000*1000/(end-start));
} public long getRunTime()
{
return System.currentTimeMillis();
} }
Class RunThread
import java.math.BigDecimal;
import java.math.RoundingMode;
import com.gta.mysql.Test;
import com.gta.mysql.Transaction; public class ThreadTest {
public static int MAX = 10;
public static int NUM = Test.FIX/MAX; public static void main(String[] args) { Transaction [] ts = new Transaction[ThreadTest.MAX];
Test []test = new Test[ThreadTest.MAX];
int symbol = 100000;
for (int i = 0; i < ts.length; i++) {
ts[i] = new Transaction(null,
"",
"",
"010000",
new BigDecimal(15.857).setScale(3, RoundingMode.HALF_UP),
new BigDecimal(18.550).setScale(3, RoundingMode.HALF_UP),
new BigDecimal(13.147).setScale(3, RoundingMode.HALF_UP),
new BigDecimal(16.383).setScale(3, RoundingMode.HALF_UP),
new BigDecimal(0.151).setScale(3, RoundingMode.HALF_UP),
new BigDecimal(1.550).setScale(3, RoundingMode.HALF_UP),
new BigDecimal(5000000).setScale(3, RoundingMode.HALF_UP),
new BigDecimal(500000000).setScale(3, RoundingMode.HALF_UP),
System.currentTimeMillis(),
"SSE");
test[i] = new Test(); } RunThread[] thread = new RunThread[ThreadTest.MAX];
for (int i = 0; i < thread.length; i++) {
test[i].initMySQL();
thread[i] = new RunThread(ts[i], symbol, test[i]);
symbol += ThreadTest.NUM*1000;
} for (int i = 0; i < thread.length; i++)
thread[i].start(); while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
test[0].down();
}
} } }
ThreadTest
作者:志青云集
出处:http://www.cnblogs.com/lyssym
如果,您认为阅读这篇博客让您有些收获,不妨点击一下右下角的【推荐】。
如果,您希望更容易地发现我的新博客,不妨点击一下左下角的【关注我】。
如果,您对我的博客所讲述的内容有兴趣,请继续关注我的后续博客,我是【志青云集】。
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。
数据库选型之MySQL(多线程并发)的更多相关文章
- 数据库选型之MySQL(固态硬盘)
刘勇 Email: lyssym@sina.com 本博客记录作者在工作与研究中所经历的点滴,一方面给自己的工作与生活留下印记,另一方面若是能对大家有所帮助,则幸甚至哉矣! 简介 鉴于高频中心库 ...
- 数据库选型之MySQL(普通硬盘)
刘勇 Email:lyssym@sina.com 本博客记录作者在工作与研究中所经历的点滴,一方面给自己的工作与生活留下印记,另一方面若是能对大家有所帮助,则幸甚至哉矣! 简介 鉴于高频中心库ta ...
- 数据库选型之亿级数据量并发访问(MySQL集群)
刘 勇 Email:lyssym@sina.com 简介 针对实际应用中并发访问MySQL的场景,本文采用多线程对MySQL进行并发读取访问,其中以返回用户所需的数据并显示在终端为测试结束节点,即将 ...
- nosql数据库选型
http://blogread.cn/it/article/6654 今天在书店里翻完了一遍<七天七数据库>.这本书简单介绍了postgreSQL,riak,mongodb,HBase,r ...
- MySQL Innodb 并发涉及参数
1 参数作用 MySQL的各个插件式引擎中,都会对事务及线程做一定的处理和优化.在Innodb引擎中,总是尝试保持 innodb内 操作系统的线程数(暂命名为innodb_thread) 应该小于或等 ...
- 从其他数据库迁移到MySQL及MySQL特点
从其他数据库迁移到MySQL Oracle,SQL Server迁移到MySQL 一些变化 不再使用存储过程.视图.定时作业 表结构变更,如采用自增id做主键,以及其他语法变更 业务SQL改造,不使用 ...
- Java多线程并发编程/锁的理解
一.前言 最近项目遇到多线程并发的情景(并发抢单&恢复库存并行),代码在正常情况下运行没有什么问题,在高并发压测下会出现:库存超发/总库存与sku库存对不上等各种问题. 在运用了 限流/加锁等 ...
- [数据库系列之MySQL] Mysql整体架构浅析一
一.引言 平时我们在做Java系统时,一般情况下都会连接到一个MySQL数据库上去,执行各种增删改查的语句.大部分的Java工程师对MySQL的了解和掌握程度,大致就停留在这么一个阶段:对MySQL可 ...
- 多线程并发同一个表问题(li)
现有数据库开发过程中对事务的控制.事务锁.行锁.表锁的发现缺乏必要的方法和手段,通过以下手段可以丰富我们处理开发过程中处理锁问题的方法.For Update和For Update of使用户能够锁定指 ...
随机推荐
- 9.3n+1问题
时间限制: 1 s 空间限制: 32000 KB 题目等级 : 白银 Silver 题解 查看运行结果 题目描述 Description 3n+1问题是一个简单有趣而又没有解决的数学问题.这个问题是由 ...
- php-streams扩展学习
一. streams是干嘛的: 用于统一文件.网络.数据压缩等类文件操作方式,并为这些类文件操作提供一组通用的函数接口. 二. stream是具有流式行为的资源对象,这个对象有一个包装类 例如: pr ...
- ngxin error日志
日志模块ngx_errlog_module对于支持可变参数平台提供的三个接口 #define ngx_log_error(level, log, ...) \ if ((log)->log_le ...
- IndiaHacks 2016 - Online Edition (Div. 1 + Div. 2) E. Bear and Forgotten Tree 2 bfs set 反图的生成树
E. Bear and Forgotten Tree 2 题目连接: http://www.codeforces.com/contest/653/problem/E Description A tre ...
- LNMP包环境下使用TP5框架通过ODBC连接MSSQL方案
本文主要介绍了如何在linux下使用php语言的thinkphp5框架通过pdo_odbc的方式连接MSSQL的方案步骤: 1.下载微软官方发布的ODBC驱动包 Red Hat 5/6:https:/ ...
- Registering DLL and ActiveX controls from code
http://delphi.about.com/od/windowsshellapi/l/aa040803a.htm How to register (and unregister) OLE cont ...
- C# 读取EXCEL文件出现数据丢失问题,数据不完整
将EXCEL数据导出的时候如果同一列数据中既有文字,又有数字!读取时一列中要么文字丢失只剩下数字,要么数字丢失,只剩下文字,这是由第一行的数据类型决定的.出现这种问题是由于数据类型不统一造成的. 原来 ...
- GOOGLE定位
GOOGLE定位 /// <author>cxg 2018-3-27</author> unit umap; interface uses System.SysUtils, S ...
- The maximum number of processes for the user account running is currently , which can cause performance issues. We recommend increasing this to at least 4096.
[root@localhost ~]# vi /etc/security/limits.conf # /etc/security/limits.conf # #Each line describes ...
- 8个超有用的Java測试工具和框架
Java入门 假设你才刚開始接触Java世界,那么要做的第一件事情是,安装JDK--Java Development Kit(Java开发工具包),它自带有Java Runtime Environme ...