redis做缓存手动更新,redis和gearmand实现自动更新,redis高可用配置

时间:2021-05-31 06:02:03

实验主机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)

再次在浏览器*问:
redis做缓存手动更新,redis和gearmand实现自动更新,redis高可用配置

利用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以及浏览器*问都可以直接变更。