这里有新鲜出炉的Mysql教程,程序狗速度看过来!
MySQL是一个开放源码的小型关联式数据库管理系统,开发者为瑞典MySQL AB公司。MySQL被广泛地应用在Internet上的中小型网站中。由于其体积小、速度快、总体拥有成本低,尤其是开放源码这一特点,许多中小型网站为了降低网站总体拥有成本而选择了MySQL作为网站数据库。
本文给大家介绍的是一次比较特殊的任务,我们使用PHP SWOOLE 做一个异步的定时任务系统,具体如何来实现的呢,接下来来我们好好看下吧
南宁公司和几个分公司之间都使用了呼叫系统,然后现在需要做一个呼叫通话数据分析,由于分公司的呼叫服务器是在内网,通过技术手段映射出来,分公司到南宁之间的网络不稳定,所以需要把分公司的通话数据同步到南宁。
本身最简单的方法就是直接配置MySQL的主从同步就可以同步数据到南宁来了。但是销售呼叫系统那边的公司不给MySQL权限我们。 所以这个方法只能放弃了。
于是我们干脆的想,使用PHP来实现定时一个简易的PHP定时同步工具,然后PHP进程常驻后台运行,所以首先就先到了一个PHP组件:SWOOLE,经过讨论,分公司的每天半天生成的数据量最大在5000条左右,所以这个方案是可行,就这样干。
我们使用PHP SWOOLE 做一个异步的定时任务系统。
本身MySQL数据库的主从同步是通过解析Master库中的binary-log来进行同步数据到从库的。然而我们使用PHP来同步数据的时候,那么只能从master库分批查询数据,然后插入到南宁的slave库来了。
这里我们使用的框架是
.
- ThinkPHP 3.2
首先安装PHP扩展: SWOOLE,因为没有使用到特别的功能,所以这里我们使用pecl来快速安装:
- pecl install swoole
安装完成后在
里面加入
- php.ini
安装完成后,我们使用
- extension="swoole.so"
来检查是否成功了.
- phpinfo()
安装成功了,我们就来写业务.
服务端
1、首先启动一个后台的服务端,监听端口9501
- public
- function index() {
- $serv = new\swoole_server("0.0.0.0", 9501);
- $serv - >set(['worker_num' = >1, //一般设置为服务器CPU数的1-4倍
- 'task_worker_num' = >8, //task进程的数量
- 'daemonize' = >1, //以守护进程执行
- 'max_request' = >10000, //最大请求数量
- "task_ipc_mode " = >2 //使用消息队列通信,并设置为争抢模式
- ]);
- $serv - >on('Receive', [$this, 'onReceive']); //接收任务,并投递
- $serv - >on('Task', [$this, 'onTask']); //可以在这个方法里面处理任务
- $serv - >on('Finish', [$this, 'onFinish']); //任务完成时候调用
- $serv - >start();
- }
2、接收和投递任务
- public
- function onReceive($serv, $fd, $from_id, $data) {
- //使用json_decode 解析任务数据
- $areas = json_decode($data, true);
- foreach($areas as $area) {
- //投递异步任务
- $serv - >task($area);
- }
- }
3、任务执行,数据从master库查询和写入到slave数据库
- public
- function onTask($serv, $task_id, $from_id, $task_data) {
- $area = $task_data; //参数是地区编号
- $rows = 50; //每页多少条
- //主库地址,根据参数地区($area)编号切换master数据库连接
- //从库MySQL实例,根据参数地区($area)编号切换slave数据库连接
- //由于程序是常驻内存的,所以MySQL连接可以使用长连接,然后重复利用。要使用设计模式的,可以使用对象池模式
- Code......
- //master 库为分公司的数据库,slave库为数据同步到南宁后的从库
- Code......
- //使用$sql获取从库中最大的自增: SELECT MAX(id) AS maxid FROM ss_cdr_cdr_info limit 1
- $slaveMaxIncrementId = ...;
- //使用$sql获取主库中最大的自增: SELECT MAX(id) AS maxid FROM ss_cdr_cdr_info limit 1
- $masterMaxIncrementId = ...;
- //如果相等的就不同步了
- if ($slaveMaxIncrementId >= $masterMaxIncrementId) {
- return false;
- }
- //根据条数计算页数
- $dataNumber = ceil($masterMaxIncrementId - $slaveMaxIncrementId);
- $eachNumber = ceil($dataNumber / $rows);
- $left = 0;
- //根据页数来进行分批循环进行写入,要记得及时清理内存
- for ($i = 0; $i < $eachNumber; $i++) {
- $left = $i == 0 ? $slaveMaxIncrementId: $left + $rows;
- $right = $left + $rows;
- //生成分批查询条件
- //$where = "id > $left AND <= $right";
- $masterData = ...; //从主库查询数据
- $slaveLastInsertId = ...; //插入到从库
- unset($masterData, $slaveLastInsertId);
- }
- echo "New AsyncTask[id=$task_id]".PHP_EOL;
- $serv - >finish("$area -> OK");
- }
4、任务完成时候调用
- public
- function onFinish($serv, $task_id, $task_data) {
- echo "AsyncTask[$task_id] Finish: $task_data".PHP_EOL;
- }
客户端推送任务
到此基本完成,剩下来我们来写客户端任务推送
- public
- function index() {
- $client = new\swoole_client(SWOOLE_SOCK_TCP);
- if (!$client - >connect('127.0.0.1', 9501, 1)) {
- throw new Exception('链接SWOOLE服务错误');
- }
- $areas = json_encode(['liuzhou', 'yulin', 'beihai', 'guilin']);
- //开始遍历检查
- $client - >send($areas);
- echo "任务发送成功".PHP_EOL;
- }
至此基本完成了,剩下的我们来写一个shell脚本定时执行:/home/wwwroot/sync_db/crontab/send.sh
- #!/bin/bash
- PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
- export PATH
- # 定时推送异步的数据同步任务
- /usr/bin/php /home/wwwroot/sync_db/server.php home/index/index
使用crontab定时任务,我们把脚本加入定时任务
- #设置每天12:30执行数据同步任务
- 30 12 * * * root /home/wwwroot/sync_db/crontab/send.sh
- #设置每天19:00执行数据同步任务
- 0 19 * * * root /home/wwwroot/sync_db/crontab/send.sh
Tips: 最好推荐在里面加入写日志操作,这样好知道是任务推送、执行是否成功。
至此基本完成,程序有待优化~~~,各位看客有更好的方法欢迎提出。
来源: http://www.phperz.com/article/17/0830/340219.html