实验主机3台:
server11:redis缓存服务器
server12:mysql服务器:client
serever13:ngnx+php-fpm,gearmand server,worker
server11:
首先安装redis服务器
server13:
rpm包安装nginx+php-fpm
vim /etc/php.ini
946 date.timezone = Asia/Shanghai
vim /etc/php-fpm.d/www.conf
#修改用户和组为nginx,原因是查看/etc/nginx/nginx.conf文件中记录了nginx默认以nginx用户身份启动
39 user = nginx
40 ; RPM: Keep a group allowed to write in log dir.
41 group = nginx
vim /etc/nginx/conf.d/default.conf
8 location / {
9 root /usr/share/nginx/html; 10 index index.php index.html index.htm; #添加php首页
11 }
30 location ~ \.php$ {
31 root html;
32 fastcgi_pass 127.0.0.1:9000;
33 fastcgi_index index.php;
34 fastcgi_param SCRIPT_FILENAME /usr/share/nginx/html$fastcgi_script _name;
35 include fastcgi_params;
36 }
yum install -y unzip
unzip phpredis-master.zip
cd phpredis-master
yum install -y gcc
phpize
./configure
make & make install
#此时可以生成redis.so,即redis动态连接库
cd /usr/lib64/php/modules/ #默认在此目录下
cd /usr/share/nginx/html/
vim test.php
<?php
$redis = new Redis();
$redis->connect('172.25.92.11',6379) or die ("could net connect redis server"); #指定redis服务器
# $query = "select * from test limit 9";
$query = "select * from test";
for ($key = 1; $key < 10; $key++)
{
if (!$redis->get($key))
{
$connect = mysql_connect('172.25.92.12','redis','westos'); #设定登陆后端mysql服务器的用户和密码
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);
}
}
cd /etc/php.d/
cp mysql.ini redis.ini
vim redis.ini
extension=redis.so #添加redis缓存库,php默认会读取/etc/php.d/下的所有.ini结尾的文件
/etc/init.d/nginx start
/etc/init.d/php-fpm start
server12:
yum install -y mysql-sesrver
/etc/init.d/mysqld start
mysql_secure_installation
mysql -phello
mysql> create database test;
Query OK, 1 row affected (0.00 sec)
mysql> grant all on test.* to redis@'%' identified by 'westos'; #根据test.php文件内容授权用户
Query OK, 0 rows affected (0.00 sec)
mysql < test.sql -phello
#test.sql文件内容
[root@server12 ~]# cat 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> use test;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> select * from test;
+----+-------+
| id | name |
+----+-------+
| 1 | test1 |
| 2 | test2 |
| 3 | test3 |
| 4 | test4 |
| 5 | test5 |
| 6 | test6 |
| 7 | test7 |
| 8 | test8 |
| 9 | test9 |
+----+-------+
测试:手动更新redis
浏览器:
172.25.92.13/test.php
会显示test库中的内容。
在server12上手动做数据库更新:
mysql> update test set name='westos' where id=1;
Query OK, 1 row affected (0.10 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select * from test; +----+--------+
| id | name | +----+--------+
| 1 | westos |
| 2 | test2 |
| 3 | test3 |
| 4 | test4 |
| 5 | test5 |
| 6 | test6 |
| 7 | test7 |
| 8 | test8 |
| 9 | test9 | +----+--------+
在浏览器再次访问时发现没有变化,原因是因为redis缓存的存在。
server11上:删除id1的缓存:
[root@server11 ~]# redis-cli
127.0.0.1:6379> get 1
"test1"
127.0.0.1:6379> get 2
"test2"
127.0.0.1:6379> del 1
(integer) 1
127.0.0.1:6379> get 1
(nil)
再次在浏览器*问:
利用gearmand实现redis自动更新:
原理:msyql作为gearemand的客户端(client),geaemand自身为server,php端为worker。
当mysql(client)由数据更新时,会触发trigger,trigger会调用UDF(三个函数),将mysql更新的数据json化,并发给gearmand(保证4370端口开启)。gearmand会将数据发送个php服务端,同时php端会发送给redis(worker.php文件中记录了此行为)。php端要安装gearmand(gearman-1.1.2.tgz)来生成gearmand.so,然后扩展到php中,建立php和gearmand的关联。然后将worker.php程序运行在后端,一旦数据库端由数据更新,gearmand会发送给redis,同时会发送给php端。每次数据库更新都会及时的更新到php端,不会因为redis缓存导致客户端访问的数据不变的情况,既有缓存的功能,也有实时更新的效果。
server13上:
yum install gearmand-1.1.8-2.el6.x86_64.rpm libgearman-1.1.8-2.el6.x86_64.rpm
/etc/init.d/gearmand start
netstat -antlp #查看gearmand开启的端口4730
tcp 0 0 0.0.0.0:4730 0.0.0.0:* LISTEN 3601/gearmand
server12:
yum install mysql-devel #安装mysql的开发包
yum install -y unzip
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 #编译生成lib_mysqludf_json.so,可以使用ls查看 cp lib_mysqludf_json.so /usr/lib64/mysql/plugin/
cd /usr/lib64/mysql/plugin/
mysql -phello
mysql> CREATE FUNCTION json_object RETURNS STRING SONAME 'lib_mysqludf_json.so'; #由mysqludf_json.so生成json_object这个UDF函数,此函数用于将mysql数据映射为json格式 tar zxf gearman-mysql-udf-0.6.tar.gz
cd gearman-mysql-udf-0.6
yum install -y libgearman-* libevent-*
./configure --libdir=/usr/lib64/mysql/plugin/
make
make install
cd /usr/lib64/mysql/plugin/
ls #可以看到生成libgearman_mysql_udf.so.0.0.0这个动态库,用于创建另外两个函数。
mysql -phello
mysql> CREATE FUNCTION gman_do_background RETURNS STRING SONAME 'libgearman_mysql_udf.so'; #生成gman_do_background这个函数,此函数用于将json数据发送给gearmand
mysql> CREATE FUNCTION gman_servers_set RETURNS STRING SONAME 'libgearman_mysql_udf.so'; #生成gman_servers函数,此函数用于指定gearmand的ip和端口 Query OK, 0 rows affected (0.00 sec) mysql> select * from mysql.func; #查看关于没有mysql的函数 +--------------------+-----+-------------------------+----------+
| 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 | +--------------------+-----+-------------------------+----------+ 3 rows in set (0.00 sec) mysql> SELECT gman_servers_set('172.25.92.13:4730'); #查看gearmand +---------------------------------------+
| gman_servers_set('172.25.92.13:4730') | +---------------------------------------+
| 172.25.92.13:4730 | +---------------------------------------+
#重新导入数据库,启动触发条件,即mysql何时将数据发送给gearmnd
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 -phello
mysql -phello
mysql> SHOW TRIGGERS FROM test; #查看触发条件
server13上:
vim worker.php #此程序用于指出gearmand和redis的关联,用php语言写成
<?php
$worker = new GearmanWorker();
$worker->addServer();
$worker->addFunction('syncToRedis', 'syncToRedis');
$redis = new Redis();
$redis->connect('172.25.92.11', 6379); #指出redis的位置
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);
}
?>
tar zxf gearman-1.1.2.tgz
cd gearman-1.1.2
phpize
yum install -y libgearman-devel-1.1.8-2.el6.x86_64.rpm libevent-1.4.13-4.el6.x86_64.rpm libevent-devel-1.4.13-4.el6.x86_64.rpm libevent-doc-1.4.13-4.el6.noarch.rpm libevent-headers-1.4.13-4.el6.noarch.rpm re2c-0.13.5-1.el6.x86_64.rpm
cd gearman-1.1.2
./configure
make
make install
cd /etc/php.d/
cp redis.ini gearman.ini
vim gearman.ini #指定gearmand扩展的ini文件
cd /usr/lib64/php/modules/ #次目录下可以看见gearman.so
vim gearman.ini
extension=gearman.so
/etc/init.d/php-fpm reload
cp worker.php /usr/local/ #将第三方程序放在/usr/local下
cd /usr/local/
nohup php worker.php & #后台运行worker
ps ax #查看进程
测试:此时在数据库再次更新数据时,在redis以及浏览器*问都可以直接变更。