PHP使用SWOOLE扩展实现定时同步 MySQL 数据

南宁公司和几个分公司之间都使用了呼叫系统,然后现在需要做一个呼叫通话数据分析,由于分公司的呼叫服务器是在内网,通过技术手段映射出来,分公司到南宁之间的网络不稳定,所以需要把分公司的通话数据同步到南宁。

本身最简单的方法就是直接配置MySQL的主从同步就可以同步数据到南宁来了。但是销售呼叫系统那边的公司不给MySQL权限我们。 所以这个方法只能放弃了。

于是我们干脆的想,使用PHP来实现定时一个简易的PHP定时同步工具,然后PHP进程常驻后台运行,所以首先就先到了一个PHP组件:SWOOLE,经过讨论,分公司的每天半天生成的数据量最大在5000条左右,所以这个方案是可行,就这样干。

我们使用PHP SWOOLE 做一个异步的定时任务系统。

本身MySQL数据库的主从同步是通过解析Master库中的binary-log来进行同步数据到从库的。然而我们使用PHP来同步数据的时候,那么只能从master库分批查询数据,然后插入到南宁的slave库来了。

这里我们使用的框架是 ThinkPHP 3.2 .

首先安装PHP扩展: SWOOLE,因为没有使用到特别的功能,所以这里我们使用pecl来快速安装:

?

1

pecl install swoole

安装完成后在 php.ini 里面加入 extension="swoole.so" 安装完成后,我们使用 phpinfo() 来检查是否成功了.

安装成功了,我们就来写业务.

服务端

1、首先启动一个后台的服务端,监听端口9501

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

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、接收和投递任务

?

1

2

3

4

5

6

7

8

9

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数据库

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

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、任务完成时候调用

?

1

2

3

4

public function onFinish($serv, $task_id, $task_data)

{

 echo "AsyncTask[$task_id] Finish: $task_data".PHP_EOL;

}

客户端推送任务

到此基本完成,剩下来我们来写客户端任务推送

?

1

2

3

4

5

6

7

8

9

10

11

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

?

1

2

3

4

5

6

#!/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定时任务,我们把脚本加入定时任务

?

1

2

3

4

#设置每天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: 最好推荐在里面加入写日志操作,这样好知道是任务推送、执行是否成功。

至此基本完成,程序有待优化~~~,各位看客有更好的方法欢迎提出。

参考文献:

https://www.jb51.net/article/110702.htm

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值