Redis 作 mysql 的缓存服务器
1.安装 lnmp 环境,安装以下软件包:
nginx php php-fpm php-cli php-common php-gd php-mbstring php-mysql
php-pdo php-devel mysql mysql-server
http://download.fedoraproject.org/pub/epel/6/
http://mirrors.163.com/centos/6/os/x86_64/
http://nginx.org/packages/centos/6/
2.安装php的redis扩展
https://github.com/owlient/phpredis
[root@server8 redis]# unzip phpredis-master.zip
[root@server8 redis]# cd phpredis-master
[root@server18phpredis-master]# phpize
Configuring for:PHP Api Version:
20090626Zend Module Api No:
20090626Zend Extension Api No:
220090626
[root@server1phpredis-master]#./configure--with-php-config=/usr/bin/php-config
[root@server8 phpredis-master]# make &&make install
[root@server8 phpredis-master]# vim /etc/php.ini
date.timezone = Asia/shanghai #设置时区
[root@server8 php.d]# cp mysql.ini redis.ini
[root@server8 php.d]# vim redis.ini
extension=redis.so #加载 redis 模块
[root@server8 php.d]# cd /etc/php-fpm.d/
[root@server8 php-fpm.d]# vim www.conf #将用户和组改为nginx
[root@server8 php-fpm.d]# /etc/init.d/php-fpm start
[root@server8 php-fpm.d]# vim /etc/nginx/conf.d/default.conf
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log /var/log/nginx/log/host.access.log main;
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;
}
[root@server8 php-fpm.d]# /etc/init.d/nginx start
[root@server8 php-fpm.d]# netstat -antlp ##查看80端口是否打开
![](https://i-blog.csdnimg.cn/blog_migrate/be75090c86fe6b1074a135c3e5c86f2e.png)
4.在server7上配置 mysql
yum install mysql-server -y
root@server7 utils]# /etc/init.d/mysqld restart #配置后直接启动
# service mysqld start
mysql> grant all on test.* to redis@localhost identified by 'westos'; #创建用户并授权
Query OK, 0 rows affected (0.00 sec)
mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)
5.创建 php 测试页面
[root@server8 html]# vim test.php
<?php
$redis = new Redis();
$redis->connect('172.25.27.6',6379) or die ("could net connect redis
server"); #ip 为主redis 的ip
$query = "select * from test limit 9";
for ($key = 1; $key < 10; $key++)
{
if (!$redis->get($key))
{
$connect = mysql_connect('172.25.27.7','redis','westos'); #用户和帐号为server7mysql 授权的用户和密码
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>";
}
?>
[root@server7 redis]# vim test.php
![](https://i-blog.csdnimg.cn/blog_migrate/a2a4e8f03e0fe66772a94272ed0f27df.png)
[root@server7 mnt]# mysql < test.sql
发现rides端信息并没同步过去
在将一删除后在重新查看发现已经发生改变,同时在浏览器查看数据也已发生变化,浏览器查看时,发现再访问一次mysql后,第二次访问的redis时,
数据已经变化
测试结果:到这里,我们已经实现了 redis 作为 mysql 的缓存服务器,但是如果更新了 mysql,redis中仍然会有对应的 KEY,数据就不会更新,此时就会出现
mysql 和 redis 数据不一致的情况。所以接下来就要通过 mysql 触发器将改变的数据同步到 redis 中。
配置 gearman 实现数据同步
Gearman 是一个支持分布式的任务分发框架:
Gearman Job Server: Gearman 核心程序,需要编译安装并以守护进程形式运行在后台。
Gearman Client:可以理解为任务的请求者。
Gearman Worker:任务的真正执行者,一般需要自己编写具体逻辑并通过守护进程方式运行,Gearman Worker 接收到 Gearman Client 传递的任务内容后,
会按顺序处理。
大致流程:下面要编写的 mysql 触发器,就相当于 Gearman 的客户端。修改表,插入表就相当于直接下发任务。然后通过 lib_mysqludf_json UDF 库函数
将关系数据映射为 JSON 格式,然后在通过 gearman-mysql-udf 插件将任务加入到 Gearman 的任务队列中,最后通过redis_worker.php,也就是 Gearman
的 worker 端来完成 redis 数据库的更新
1. 安装 gearman 软件包: (server7 mysql)
gearmand libgearman-devel libgearman libevent libevent-devel
libevent-doc libevent-headers tokyocabinet
# service gearmand start
#启动服务
# netstat -antlp |grep gearmand
tcp
0
0 0.0.0.0:4730
7304/gearmand
0.0.0.0:*
LISTEN
2. 安装 php 的 gearman 扩展 (server8 nginx)
https://pecl.php.net
yum install -y db*-devel
tar zxf gearman-1.1.2.tgz
cd gearman-1.1.2
./configure --with-php-config=/usr/bin/php-config
make && make install
# vim /etc/php.ini
extension=gearman.so
# service php-fpm reload
3. 安装 lib_mysqludf_json (server7 mysql)
lib_mysqludf_json UDF 库函数将关系数据映射为 JSON 格式。通常,数据库中的数据映
射为 JSON 格式,是通过程序来转换的。
https://github.com/mysqludf/lib_mysqludf_json
# yum install -y mysql-devel
# unzip lib_mysqludf_json-master.zip
# cd lib_mysqludf_json-master
# gcc $(mysql_config --cflags) -shared -fPIC -o lib_mysqludf_json.so
lib_mysqludf_json.c
查看 mysql 的模块目录:
mysql> show global variables like 'plugin_dir';
+---------------+-------------------------+
| Variable_name | Value
|
+---------------+-------------------------+
| plugin_dir
| /usr/lib64/mysql/plugin |
+---------------+-------------------------+
拷贝 lib_mysqludf_json.so 模块:
# cp lib_mysqludf_json.so /usr/lib64/mysql/plugin/
注册 UDF 函数
mysql> CREATE FUNCTION json_object RETURNS STRING SONAME
'lib_mysqludf_json.so';
查看函数
mysql> select * from mysql.func;
+--------------------+-----+-------------------------+----------+
| name
| ret | dl
| type
|
+--------------------+-----+-------------------------+----------+
| json_object
| 0 | lib_mysqludf_json.so | function |
+--------------------+-----+-------------------------+----------+
4. 安装 gearman-mysql-udf(server7)
这个插件是用来管理调用 Gearman 的分布式的队列。
https://launchpad.net/gearman-mysql-udf
# tar zxf gearman-mysql-udf-0.6.tar.gz
# cd gearman-mysql-udf-0.6
# ./configure --with-mysql=/usr/bin/mysql_config
--libdir=/usr/lib64/mysql/plugin/
# make# make install
注册 UDF 函数
mysql> CREATE FUNCTION gman_do_background RETURNS STRING SONAME
'libgearman_mysql_udf.so';
mysql> CREATE FUNCTION gman_servers_set RETURNS STRING SONAME
'libgearman_mysql_udf.so';
查看函数
mysql> select * from mysql.func;
+--------------------+-----+-------------------------+----------+
| name
| ret | dl
| type
|
+--------------------+-----+-------------------------+----------+
| json_object
|
0 | lib_mysqludf_json.so
| function |
| gman_do_background |
0 | libgearman_mysql_udf.so | function |
| gman_servers_set
|
0 | libgearman_mysql_udf.so | function |
+--------------------+-----+-------------------------+----------+
指定 gearman 的服务信息
mysql> SELECT gman_servers_set('127.0.0.1:4730');
+------------------------------------+
| gman_servers_set('127.0.0.1:4730') |
+------------------------------------+
| 127.0.0.1:4730
|
+------------------------------------+
5. 编写 mysql 触发器(根据实际情况编写)(server7 mysql)
# vim test.sql
use test;
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;+-------------+--------+-------+-------------------------------------------------
-------+----------------------+--------------------+
| datatoredis | UPDATE | test | BEGIN
SET @RECV=gman_do_background('syncToRedis', json_object(NEW.id as
`id`, NEW.name as `name`));
END | AFTER | NULL
|
| root@localhost | latin1
|
latin1_swedish_ci
| latin1_swedish_ci |
+-------------+--------+-------+------------------------------------------------------------------------
-------+----------------------+--------------------+
6. 编写 gearman 的 worker 端(server8)
# vim worker.php
<?php
$worker = new GearmanWorker();
$worker->addServer();
$worker->addFunction('syncToRedis', 'syncToRedis');
$redis = new Redis();
$redis->connect('127.0.0.1', 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 测试代码的存取一致。
}
?>
后台运行 worker
# nohup php worker.php &
7. 更新 mysql 中的数据
mysql> update test set name='hello' where id=1;查看 redis
# redis-cli
127.0.0.1:6379> get 1
"hello"
刷新测试页面数据同步
redis高可用
[root@server6 redis-4.0.1]# cp sentinel.conf /etc/redis/
[root@server6 redis-4.0.1]#vim /etc/redis/sentinel.conf
[root@server6 redis]# scp sentinel.conf root@172.25.27.7:/etc/redis
[root@server6 redis]# scp sentinel.conf root@172.25.27.8:/etc/redis
#为了防止三个环境不一致,直接将6上配置好的分发给server7 server8
/etc/init.d/redis_6379 restart #三台机子都重新启动redis程序
[root@server6 redis]# redis-server /etc/redis/sentinel.conf --sentinel #启动sentinel
[root@server7 redis]# redis-server /etc/redis/sentinel.conf --sentinel #server7 ,serevr8让他在后台运行
此时mymaster 在server6上,且serevr7,server8此时都为从机,且都正常工作中
[root@server8 utils]# redis-cli -h 172.25.27.6 -p 6379 shutdown
当执行命令让serevr6 端口关闭后,此时server7被选为新的mymaster
![](https://i-blog.csdnimg.cn/blog_migrate/5b2c0f0414ee6d6ee8deddfd2b171d5d.png)
[root@server6 redis]# /etc/init.d/redis_6379 start #重新启动serevr6
[root@server7 redis]# redis-cli -h 172.25.27.6 -p 6379 info Replication #查看server6此时的状态
![](https://i-blog.csdnimg.cn/blog_migrate/8c46421f570e64f76c9fc7406b26f0ce.png)
至此,redis的高可用已经实现