背景
 
平台目前的分析任务主要以Hive为主,分析后的结果存储在HDFS,用户通过REST API或者Rsync的方式获取分析结果,这样的方式带来以下几个问题:
 
(1)任务执行结束时间未知,用户必须自行编写代码不断地通过REST API请求分析结果,直至获取到分析结果为止,其中还需要处理分析结果过大,转而通过Rsync方式获取;
 
(2)受限于Hive SQL的表达能力,用户的计算逻辑无法完全表述,获取分析结果后需要再计算,然后入库;
 
(3)基于(1)、(2)的原因,用户编写大量复杂且冗余的代码处理上述逻辑。
 
为了改善上述情况,平台设计的解决方案如下:
 
(1)使用Spark替换Hive(MapReduce)分析任务,结合Hive SQL和Spark API两种方式,使用户的计算逻辑可以得到很好的表述;
 
(2)用户无需使用“Pull”的方式获取结果,转而使用“Post”的方式将分析结果存入自己的MySQL数据库中;
 
(3)提供基于Python的MySQL通用批量写入工具方便用户使用。
 
方案
 
MySQL批量写入工具需要解决以下几个问题:
 
(1)通用:不受限于具体数据格式的束缚;
 
     用户需要将不同格式的数据写入不同的数据库/表,意味着数据库的主机名、端口、用户名、密码、数据库实例可以通过参数定制,不同的数据格式使用SQL语句表达,如“insert into students (c_number, c_name) values (%s, %s)”。
 
(2)多线程:使用多线程的方式,提高写入的吞吐量;
 
     典型的“生产者——消费者”问题,用户需要将数据首先写入一个线程安全的共享队列中;“消费者”线程不断的从这个共享队列中获取数据并缓存,待缓存数据达到一定数目时,将这批数据一次性写出;然后继续上述过程。
 
     除此之外,“消费者”线程需要能够“正常”结束。
 
(3)数据库连接控制:需要避免连接过多或者频繁连接带来的性能开销;
 
     “消费者”线程需要能够重复利用一定数目的数据库连接,数据库连接由专门的连接池提供,工作流程如下:
 
     a. 从连接池中获取数据库连接;
     b. 通过a中的连接将数据批量写出并commit;
     c. 将数据库连接归还给连接池。
 
(4)API:简单易用
 
我们将批量写入工具定义为一个“存储引擎”,考虑到MySQL的吞吐量可能在大数据量的写入下会成为一个瓶颈,后期会考虑扩展其它工具。因此定义一个基类表示抽象的“存储引擎”,并扩展出本文具体讨论的MySQL“存储引擎”:MySQLStorageEngine。
 
 
 
MySQLStorageEngine的初始化过程涉及以下六个方面:
 
(1)begin、end用于统计一次批量写入的耗时;
 
(2)接收用户定制的参数;
     host:数据库主机名;
     user:数据库登录用户名;
     passwd:数据库登录密码;
     db:数据库实例
     port:数据库端口
     charset:数据库字符编码
     sql:写入数据时使用的SQL语句,如“insert into students (c_number, c_name) values (%s, %s)”
     threads:写入线程数目;
     bufferSize:写入线程内部的缓存区大小,亦即每一次“batch”的大小;
     mincached:数据库连接池内部最小缓存连接数;
     maxcached:数据库连接池内部最大缓存连接数;
     maxconnections:数据库连接池所允许同时建立的最大连接数:目前与写入线程数目相同。
 
(3)构建共享队列queue;
 
(4)saveNum、storeNum用于统计用户写入总数及实际(成功)写入总数,考虑到多线程使用环境,分别构建相应的锁对象saveLock、storeLock;
 
(5)构建数据库连接池,这里使用的是DBUtils PooledDB;
 
(6)构建写入线程(多个)并启动。
 
至此,MySQLStorageEngine实例创建完毕,并且启动内部多个写入线程用于消费队列queue中数据。用户可通过实例方法save写入数据:
 
 
可见,save支持两种类型的数据,一种是Tuple,另一种是Tuple数组,它们都被保存至队列queue中,由写入线程负责处理。
 
用户写入完成之后,可以通过方法close关闭“存储引擎”,
 
 
需要注意的是,用户写入的数据实际是保存在队列queue中的,“用户写入完成”并不代表队列queue中的数据已全部被写入线程消费且完成入库,因此必须首先通知写入线程用户数据已全部写入完毕(requestStop),然后等待写入线程运行完毕(join),最后关闭数据库连接池。
 
写入线程由MySQLSaver实现,它的初始化过程特别简单:
 
(1)接收“存储引擎”实例engine;
(2)定义实例变量stop,初始值为False,用于表示用户尚有数据写入;True表示用户写入结束。
 
 
MySQLSaver的工作流程如下:
 
 
(1)初始化缓存区buffer,用于保存从队列queue消费而来的数据;
 
(2)循环从队列queue获取数据,如果没有获取到数据,则执行(3);如果获取到数据,则执行(4);
 
(3)如果用户写入结束(stop值为True)而且队列中已经没有剩余数据,将缓冲区buffer中的数据一次性写入(__save),结束线程(break);
 
(4)将(2)中获取到的数据存入缓存区,如果缓存区的大小达到数目限制,则将缓冲区buffer中的数据一次性写入(__save),继续(2)。
 
__save的工作流程如下:
 
 
(1)从连接池pool中获取数据库连接db并构建实例cursor;
(2)写入buffer中的数据(executemany)并提交(commit);
(3)清空buffer、关闭实例cursor、将数据库连接db“归还”给连接池(close)。
 
使用示例如下:
 

MySQL通用批量写入工具(Python)的更多相关文章

  1. 【Python之旅】第六篇(七):开发简易主机批量管理工具

    [Python之旅]第六篇(七):开发简易主机批量管理工具 python 软件开发 Paramiko模块 批量主机管理 摘要: 通过前面对Paramiko模块的学习与使用,以及Python中多线程与多 ...

  2. Sqlite表结构读取工具,word批量转html,在线云剪贴板,文件批量提取工具;

    工欲善其事必先利其器,本周为您推荐工具排行 Sqlite表结构读取工具,word批量转html,在线云剪贴板,文件批量提取工具:     本周我们又要发干货了,准备好接受了吗? 为什么是干货,就是因为 ...

  3. Python开发程序:简单主机批量管理工具

    题目:简单主机批量管理工具 需求: 主机分组 登录后显示主机分组,选择分组后查看主机列表 可批量执行命令.发送文件,结果实时返回 主机用户名密码可以不同 流程图: 说明: ### 作者介绍: * au ...

  4. mysql批量写入

    MySQL批量写入语法是: INSERT INTO table (field1,field2,field3) VALUES (“a”,”b”,”c”), (“a1”,”b1”,”c1”),(“a2”, ...

  5. 【Python】JBOSS-JMX-EJB-InvokerServlet批量检测工具

    一.说明 在JBoss服务器上部署web应用程序,有很多不同的方式,诸如:JMX Console.Remote Method Invocation(RMI).JMXInvokerServlet.Htt ...

  6. php从memcache读取数据再批量写入mysql的方法

    这篇文章主要介绍了php从memcache读取数据再批量写入mysql的方法,可利用memcache缓解服务器读写压力,并实现数据库数据的写入操作,非常具有实用价值,需要的朋友可以参考下. 用 Mem ...

  7. Python简单主机批量管理工具

    一.程序介绍 需求: 简单主机批量管理工具 需求: 1.主机分组 2.主机信息使用配置文件 3.可批量执行命令.发送文件,结果实时返回 4.主机用户名密码.端口可以不同 5.执行远程命令使用param ...

  8. 批量插入数据, 将DataTable里的数据批量写入数据库的方法

    大量数据导入操作, 也就是直接将DataTable里的内容写入到数据库 通用方法: 拼接Insert语句, 好土鳖 1. MS Sql Server:   使用SqlBulkCopy 2. MySql ...

  9. 部署MySQL自动化运维工具inception+archer

    ***************************************************************************部署MySQL自动化运维工具inception+a ...

随机推荐

  1. android ContentProvider学习

    1.ContentProvider提供位存储或获取数据提供了统一的接口. 2.使用ContentProvider可以在不同的应用程序之间共享数据. 3.Android为常见的一些数据提供了Conten ...

  2. ListView嵌套ListView优化

    在做业务时候,一个ListView显示多种数据类型,我们想到的方法是ListView在嵌套一个ListView,对于子ListView 占父ListView的一行,就攻克了问题,可是这种逻辑是不是有点 ...

  3. Web站点架构设计考虑的因素

    转自http://blog.csdn.net/moshengtan/article/details/8990052 1    Web负载均衡 1.1 - 使用商业硬件实现 最经常使用的F5 与citr ...

  4. React Native 从入门到原理

    React Native 是最近非常火的一个话题,介绍如何利用 React Native 进行开发的文章和书籍多如牛毛,但面向入门水平并介绍它工作原理的文章却寥寥无几. 本文分为两个部分:上半部分用通 ...

  5. dispatch的几种队列

    dispatch的几种队列   dispatch队列的生成可以有这几种方式: 1. dispatch_queue_t queue = dispatch_queue_create("com.d ...

  6. POJ 1584 A Round Peg in a Ground Hole 判断凸多边形,判断点在凸多边形内

    A Round Peg in a Ground Hole Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 5456   Acc ...

  7. Objective-C基础知识点总结

    一.#import 和 #include 的区别,@class代表什么?@class 和 #import 的区别?#import<> 和 #import""的区别 答: ...

  8. SVN的使用(转发)

    http://my.oschina.net/joanfen/blog/194491?fromerr=LM5QY3YF

  9. centos yum

    1.介绍 yum(全 称为 Yellow dog Updater, Modified)是一个在Fedora和RedHat以及SUSE中的Shell前端软件包管理器.基於RPM包管理,能够从指定的服务器 ...

  10. Java数据库连接池的几种配置方法(以MySQL数据库为例)

    Java数据库连接池的几种配置方法(以MySQL数据库为例) 一.Tomcat配置数据源: 前提:需要将连接MySQL数据库驱动jar包放进Tomcat安装目录中common文件夹下的lib目录中 1 ...