利用Gearman进行Mysql到Redis的复制

redis与数据库结合,作为数据库数据的缓存提供给前端

一.实现数据库,php,nginx和redis的架构

server1提供nginx服务,使用php语言,server2提供redis缓存服务,server3提供后端数据库服务…
整体思想是:客户端通过nginx和php访问后端数据库时,先在redis这个数据库缓存中赵,查看是否含有想要的数据,如果没有就去后端数据库查找,将查找到数据返回给客户端一份,另外在redis中缓存一份….下次如果访问相同的数据就直接去redis,缩短时间同时也减轻数据库的查找压力

(一)在server1前端中
1.安装nginx和php

 yum install -y nginx-1.8.0-1.el6.ngx.x86_64.rpm php-*

2.在php的配置文件中修改时区为上海

 cd /etc/php.d/  
 vim /etc/php.ini
  timezone = “Asia/Shanghai”

3.因为php作为nginx的前端服务,我们将php网页代码也限制在nginx的用户空间中

 cd /etc/php-fpm.d/ 
  vim www.conf  修改用户为nginx

这里写图片描述
4.查看端口情况
netstat -antlp
5.修改nginx的配置文件

cd /etc/nginx/conf.d   
vim default.conf   
    location / {
        root   /usr/share/nginx/html;
        index  index.php index.html index.htm;      # 设置index.php为默认发布文件


    location ~ \.php$ {
        root           html;
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME /usr/share/nginx/html$fastcgi_script_name;
        include        fastcgi_params;
    }

6.将php测试页面的代码(该代码是查询数据库中数据)放在默认发布目录下

cd /usr/share/nginx/html/ 
cp test.php /usr/share/nginx/html/index.php
test.php代码如下(仅供参考):
  <?php
        $redis = new Redis();
        $redis->connect('127.0.0.1',6379) or die ("could net connect redis server");
  #      $query = "select * from test limit 9";
        $query = "select * from test";
        for ($key = 1; $key < 10; $key++)
        {
                if (!$redis->get($key))
                {
                        $connect = mysql_connect('127.0.0.1','redis','westos');  # 利用redis用户访问数据库
                        mysql_select_db(test);
                        $result = mysql_query($query);
                        #如果没有找到$key,就将该查询sql的结果缓存到redis
                        while ($row = mysql_fetch_assoc($result))
                        {
                                $redis->set($row['id'],$row['name']);
                        }
                        $myserver = 'mysql';
                        break;
                }
                else
                {
                        $myserver = "redis";
                        $data[$key] = $redis->get($key);
                }
        }
        echo $myserver;
        echo "<br>";
        for ($key = 1; $key < 10; $key++)
        {
                echo "number is <b><font color=#FF0000>$key</font></b>";

                echo "<br>";

                echo "name is <b><font color=#FF0000>$data[$key]</font></b>";

                echo "<br>";
        }
?>

7.源码编译php与redis的连接软件—phpredis-master.zip

yum install unzip      # 安装解压工具
unzip phpredis-master.zip 
cd phpredis-master   
phpize                 # 创建预编译环境
./configure     
make  
make install           # 源码编译安装

这里写图片描述
8.在php中动态加载redis模块

cd /etc/php.d   
cp mysql.ini redis.ini      # 拷贝数据库的模版
vim redis.ini
extension=redis.so          # 将redis模块加入php中

这里写图片描述
9.重新加载nginx,php和redis服务

/etc/init.d/php-fpm reload
nginx-s reload
/etc/init.d/redis stop 
/etc/init.d/redis start

10.在数据库中建数据库建表,对所有ip上的nginx用户授权(因为在php前端我们是利用nginx用户来访问数据库的)
这里写图片描述
11.在浏览器处输入提供nginx服务和php服务的主句ip,因为redis里边没有数据缓存,所以得去后端服务器拿数据,刷新页面,会看到第二次是去redis中拿数据,同时我们在提供redis的主机中利用redis-cli命令行也可以看到数据(说明数据是真的存在了redis缓存中)
数据库:
这里写图片描述
网页第二次去redis:
这里写图片描述
提供redis服务的主机:
这里写图片描述

可是做到这儿,我们可以发现问题,当在数据库中修改了数据之后,网页中的数据和 redis缓存处的数据均不改变,这样当然是不行的,所以我们解决这个问题…

二.利用Gearman进行Mysql到Redis的同步复制:
Gearman是一个开源的Map/Reduce分布式计算框架,具有丰富的client sdk,而且它支持MySQL UDF。
这里写图片描述

当有数据发生变化时,通过MySQL Trigger实时异步调用Gearman的UDF提交一个job给JobServer,当job执行的时候会去更新redis;从而保证redis与MySQL中的数据是同步的。

(一)在server1中:

1.安装Gearmand(服务端)及其很多很多的依赖项,之后打开gearmand服务

yum install  -y gearmand-1.1.8-2.el6.x86_64.rpm libgearman-* libevent-*
yum install php-devel-5.3.3-38.el6.x86_64.rpm  php-5.3.3-38.el6.x86_64.rpm

/etc/init.d/gearmand start
netstat -antlp   # 查看对应端口是否打开

2.scp gearman-mysql-udf-0.6.tar.gz server3:
scp lib_mysqludf_json-master.zip server3:
scp libgearman-* server3:
scp libevent-* server3:
3.在php中动态加入模块gearman

cp worker.php  /usr/local/   # work是中间搬运数据的“进程”,由php语言编写
ll gearman-1.1.2.tgz 
tar zxf gearman-1.1.2.tgz     # 在php中动态加入Gearman的模块,并进行源码编译
cd gearman-1.1.2  
phpize  
make make 
install


vim worker.php
<?php
$worker = new GearmanWorker();
$worker->addServer();
$worker->addFunction('syncToRedis', 'syncToRedis');

$redis = new Redis();
$redis->connect('172.25.1.2', 6379);

while($worker->work());
function syncToRedis($job)
{
        global $redis;
        $workString = $job->workload();
        $work = json_decode($workString);
        if(!isset($work->id)){
                return false;
        }
        $redis->set($work->id, $work->name);
        # 这条语句就是将 id 作 KEY 和name 作 VALUE 分开存储,需要和前面写的 php 测试代码的存取一致。
}
?>

4.将添加的动态模块加进php的模块目录中,当然也可选择直接写入配置文件中

cd /usr/lib64/php/modules/    # php的模块目录
ll gearman.so                 # 刚刚源码编译成功的gearman模块
cp redis.ini gearman.ini      # 利用redis的模版,编写gearman的模块配置文件
vim gearman.ini
  gearman.so

5.查看个gearman模块是否添加成功

/etc/init.d/php-fpm reload    # 重载服务
php -m | grep gearman         # 如果有则表明成功

6.启动worker进程并将其打入后台

nohup  php /usr/local/worker.php  &
ps ax

(二)在server3(后端数据库)中:
1.安装把mysql关系型数据转换成json格式的UDF工具—lib_mysqludf_json-master
(mysql里的数据格式转成json格式,通常使用php的json扩展实现。如果使用udf,会有更快的速度。)

unzip lib_mysqludf_json-master.zip     # 解压源码包
cd lib_mysqludf_json-master   
yum install gcc mysql-devel -y         # 安装依赖性
gcc $(mysql_config --cflags) -shared -fPIC -o lib_mysqludf_json.so lib_mysqludf_json.c
cd /usr/lib64/mysql/plugin/            # 存放数据库服务的所有插件位置
cd /root/lib_mysqludf_json-master
cp lib_mysqludf_json.so /usr/lib64/mysql/plugin/  # 拷贝 lib_mysqludf_json.so 模块到数据库的插件目录中

这里写图片描述
2.登陆mysql,注册 json_object函数:

show global variables like 'plugin_dir';     # 查看数据库服务存放插件的目录
CREATE FUNCTION json_object RETURNS STRING SONAME 'lib_mysqludf_json.so';  # 注册 UDF 函数 json_object(作用是利用该函数可以将数据库中的数据构造为json格式)

这里写图片描述

3.安装 gearman-mysql-udf,这个插件是用来管理调用 Gearman 的分布式的队列。

tar zxf gearman-mysql-udf-0.6.tar.gz
cd gearman-mysql-udf-0.6
yum install libgearman-* libevent-*    # 解决依赖性
./configure --libdir=/usr/lib64/mysql/plugin/     # 创建预编译环境,指定安装目录在默认数据库插件目录中
make     # 源码编译
make install

这里写图片描述
4.登陆mysql,再次注册函数

CREATE FUNCTION gman_do_background RETURNS STRING SONAME 'libgearman_mysql_udf.so';     # 用Gearman做队列来实现消息推送
CREATE FUNCTION gman_servers_set RETURNS STRING SONAME 'libgearman_mysql_udf.so';
select * from mysql.func;     # 查看数据库中注册的函数
SELECT gman_servers_set('172.25.1.1:4730');     # 指定 gearman 的服务信息

这里写图片描述
这里写图片描述
5.编辑触发器文件

什么是触发器: 触发器(trigger)是SQL server
提供给程序员和数据分析员来保证数据完整性的一种方法,它是与表事件相关的特殊的存储过程,它的执行不是由程序调用,也不是手工启动,而是由事件来触发,比如当对一个表进行操作(insert,delete, update)时就会激活它执行。触发器经常用于加强数据的完整性约束和业务规则等

vim test.sql   
use test;       # 取数据程序段
#CREATE TABLE `test` (`id` int(7) NOT NULL AUTO_INCREMENT, `name` char(8) DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;
#INSERT INTO `test` VALUES (1,'test1'),(2,'test2'),(3,'test3'),(4,'test4'),(5,'test5'),(6,'test6'),(7,'test7'),(8,'test8'),(9,'test9');

DELIMITER $$     # 触发器程序段
CREATE TRIGGER datatoredis AFTER UPDATE ON test FOR EACH ROW BEGIN
    SET @RECV=gman_do_background('syncToRedis', json_object(NEW.id as `id`, NEW.name as `name`));
  END$$
DELIMITER ;

将触发器程序导入数据库中:mysql < test.sql
登陆mysql:SHOW TRIGGERS FROM test; 查看触发器是否导入
这里写图片描述

测试:
在数据库中修改数据,在redis和网页中查看数据是否更新….
数据库中:
这里写图片描述
网页:
这里写图片描述
redis:
这里写图片描述
说明三处数据已经达到一致!!!

猜你喜欢

转载自blog.csdn.net/jay_youth/article/details/81632153
今日推荐