利用Gearman使redis做mysql 的缓存服务器(lnmp架构)

mac2024-12-19  9

秒杀系统,先存储在内存中,等高峰过去之后,在将数据存入数据库中

实验环境

server3(172.25.34.4)安装nginx PHPserver4(172.25.34.5)安装Redisserver5(172.25.34.6)安装mariadb

redis结合lnmp架构做mysql 的缓存服务器

server3:

上篇实验中的集群节点服务都关掉

[root@server3 nginx-1.17.4]# killall redis-server

安装nginx:

[root@server3 ~]# tar zxf nginx-1.17.4.tar.gz [root@server3 ~]# cd nginx-1.17.4 [root@server3 nginx-1.17.4]# ls auto CHANGES.ru configure html man src CHANGES conf contrib LICENSE README [root@server3 nginx-1.17.4]# vi auto/cc/gcc # debug #CFLAGS="$CFLAGS -g" [root@server3 nginx-1.17.4]# yum install pcre-devel zlib-devel -y [root@server3 nginx-1.17.4]# ./configure --prefix=/usr/local/nginx [root@server3 rhel7]# make && make install

安装php

[root@server3 ~]# cd rhel7 [root@server3 rhel7]# ls gearmand-1.1.12-18.el7.x86_64.rpm libevent-devel-2.0.21-4.el7.x86_64.rpm libgearman-1.1.12-18.el7.x86_64.rpm libgearman-devel-1.1.12-18.el7.x86_64.rpm libzip-0.10.1-8.el7.x86_64.rpm openssl-1.0.2k-16.el7.x86_64.rpm openssl-libs-1.0.2k-16.el7.x86_64.rpm php-cli-5.4.16-46.el7.x86_64.rpm php-common-5.4.16-46.el7.x86_64.rpm php-fpm-5.4.16-46.el7.x86_64.rpm php-mysql-5.4.16-46.el7.x86_64.rpm php-pdo-5.4.16-46.el7.x86_64.rpm php-pecl-gearman-1.1.2-1.el7.x86_64.rpm php-pecl-igbinary-1.2.1-1.el7.x86_64.rpm php-pecl-redis-2.2.8-1.el7.x86_64.rpm php-process-5.4.16-46.el7.x86_64.rpm php-xml-5.4.16-46.el7.x86_64.rpm [root@server3 rhel7]# yum install * -y

编辑nginx的配置文件

root@server3 rhel7]# cd [root@server3 ~]# cd nginx-1.17.4/conf [root@server3 conf]# vi nginx.conf 2 user nginx nginx; 43 location / { 44 root html; 45 index index.php index.html index.htm; 46 } 65 location ~ \.php$ { 66 root html; 67 fastcgi_pass 127.0.0.1:9000; 68 fastcgi_index index.php; 69 # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; 70 include fastcgi.conf; 71 } [root@server1 conf]# /usr/local/nginx/sbin/nginx -t [root@server3 conf]# useradd nginx

开启nginx php 查看端口

[root@server3 conf]# /usr/local/nginx/sbin/nginx [root@server3 conf]# systemctl start php-fpm [root@server3 conf]# netstat -antuple Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address Foreign Address State User Inode PID/Program name tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 0 31086 7842/nginx: master tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 0 14167 629/sshd tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 0 15356 874/master tcp 0 0 127.0.0.1:9000 0.0.0.0:* LISTEN 0 31245 7850/php-fpm: maste [root@server3 ~]# ls gearman-mysql-udf-0.6.tar.gz nginx-1.17.4 redis-5.0.3.tar.gz test.php lib_mysqludf_json-master.zip nginx-1.17.4.tar.gz rhel6 Redis.pdf test.sql mysql redis-5.0.3 rhel7 worker.php [root@server3 ~]# mv test.php /usr/local/nginx/html/ [root@server3 ~]# cd /usr/local/nginx/html/ [root@server3 html]# ls 50x.html index.html test.php [root@server3 html]# mv test.php index.php [root@server3 html]# vi index.php 1 <?php 2 $redis = new Redis(); 3 $redis->connect('172.25.34.5',6379) or die ("could net connect redis server"); ##指向redis 4 # $query = "select * from test limit 9"; 5 $query = "select * from test"; 6 for ($key = 1; $key < 10; $key++) 7 { 8 if (!$redis->get($key)) 9 { 10 $connect = mysql_connect('172.25.34.6','redis','west os'); ##指向数据库

server4:

安装redis

下载安装包,并解压 [root@server4 ~]# ls redis-5.0.3.tar.gz [root@server4 ~]# tar zxf redis-5.0.3.tar.gz 安装依赖包,并编译安装 [root@server4 ~]# cd redis-5.0.3 [root@server4 redis-5.0.3]# yum install gcc -y [root@server4 redis-5.0.3]# make && make install 执行redis安装脚本 [root@server2 redis-5.0.3]# cd utils/ [root@server2 utils]# ./install_server.sh 此时netstat -antlp会出现6379端口 编辑配置文件 [root@server2 utils]# vim /etc/redis/6379.conf 70 bind 0.0.0.0 [root@server2 utils]# /etc/init.d/redis_6379 start

server5:

配置mysql端

安装rhel7.3自带数据库即可

如果之前安装过mysql数据库,先卸载数据库 [root@server5 ~]# rpm -aq | grep mysql mysql-community-common-5.7.24-1.el7.x86_64 mysql-community-client-5.7.24-1.el7.x86_64 mysql-community-server-5.7.24-1.el7.x86_64 mha4mysql-node-0.58-0.el7.centos.noarch mysql-community-libs-5.7.24-1.el7.x86_64 mysql-community-libs-compat-5.7.24-1.el7.x86_64 [root@server5 ~]# rpm -e `rpm -aq | grep mysql` --nodeps ##清除mysql数据库 warning: /etc/my.cnf saved as /etc/my.cnf.rpmsave 安装mariadb [root@server5 utils]# yum install mariadb-server -y [root@server5 mysql]# systemctl start mariadb [root@server5 mysql]# mysql_secure_installation MariaDB [(none)]> create database test; Query OK, 1 row affected (0.00 sec) MariaDB [(none)]> grant all on test.* to redis@'%' identified by 'westos'; Query OK, 0 rows affected (0.00 sec) MariaDB [test]> flush privileges; Query OK, 0 rows affected (0.00 sec) [root@server5 ~]# cd redis [root@server5 redis]# ls gearman-mysql-udf-0.6.tar.gz redis-5.0.3.tar.gz rhel7 test.sql lib_mysqludf_json-master.zip rhel6 Redis.pdf test.php worker.php [root@server5 redis]# 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 ; [root@server5 redis]# mysql -pwestos < test.sql 导入测试库 [root@server5 ~]# mysql -p MariaDB [(none)]> grant all on test.* to redis@'%' identified by 'westos'; ##授权用户 MariaDB [(none)]> flush privileges; Query OK, 0 rows affected (0.00 sec) MariaDB [(none)]> 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 MariaDB [test]> select * from test; +----+-------+ | id | name | +----+-------+ | 1 | test1 | | 2 | test2 | | 3 | test3 | | 4 | test4 | | 5 | test5 | | 6 | test6 | | 7 | test7 | | 8 | test8 | | 9 | test9 | +----+-------+

测试

浏览器访问

刷新 第一次访问到的是数据库mariadb中的数据,然后刷新后是redis

server4:

[root@server4 ~]# redis-cli 127.0.0.1:6379> get 1 "test1"

如何同步数据修改

server5:

MariaDB [(none)]> 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 MariaDB [test]> update test set name='westos' where id=1; #修改数据 Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 MariaDB [test]> select * from test; +----+--------+ | id | name | +----+--------+ | 1 | westos | | 2 | test2 | | 3 | test3 | | 4 | test4 | | 5 | test5 | | 6 | test6 | | 7 | test7 | | 8 | test8 | | 9 | test9 | +----+--------+ 9 rows in set (0.00 sec)

server4:

查看Redis数据库上存储的数据发现并未改变

[root@server4 ~]# redis-cli 127.0.0.1:6379> get 1 "test1"

在mysql端修改的数据没有进行同步,说明数据是在redis端取得

到这里,我们已经实现了 redis 作为 mysql 的缓存服务器,但是如果更新了 mysql,redis中仍然会有对应的 KEY,数据就不会更新,此时就会出现 mysql 和 redis 数据不一致的情况。 那么我们该如何实现将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 数据库的更新。

配置过程:

mysql (client) -> gearmand:4730(job server) -> worker(php/python/java)

server5:

安装 lib_mysqludf_json

[root@server5 redis]# ls gearman-mysql-udf-0.6.tar.gz redis-5.0.3.tar.gz rhel7 test.sql lib_mysqludf_json-master.zip rhel6 Redis.pdf test.php worker.php [root@server5 redis]# unzip lib_mysqludf_json-master.zip Archive: lib_mysqludf_json-master.zip 37f851c808c4161beb4d5e535771dc0c59c82de6 creating: lib_mysqludf_json-master/ inflating: lib_mysqludf_json-master/README.md inflating: lib_mysqludf_json-master/lib_mysqludf_json.c inflating: lib_mysqludf_json-master/lib_mysqludf_json.html inflating: lib_mysqludf_json-master/lib_mysqludf_json.so inflating: lib_mysqludf_json-master/lib_mysqludf_json.sql [root@server5 redis]# cd lib_mysqludf_json-master [root@server5 lib_mysqludf_json-master]# ls lib_mysqludf_json.c lib_mysqludf_json.so README.md lib_mysqludf_json.html lib_mysqludf_json.sql [root@server5 lib_mysqludf_json-master]# gcc $(mysql_config --cflags) -shared -fPIC -o lib_mysqludf_json.so lib_mysqludf_json.c [root@server5 lib_mysqludf_json-master]# cp lib_mysqludf_json.so /usr/lib64/mysql/plugin/

安装 gearman 软件包,并.安装 php 的 gearman 扩展

[root@server5 lib_mysqludf_json-master]# cd .. [root@server5 redis]# ls gearman-mysql-udf-0.6.tar.gz redis-5.0.3.tar.gz test.php lib_mysqludf_json-master rhel6 Redis.pdf test.sql lib_mysqludf_json-master.zip rhel7 worker.php [root@server5 redis]# tar zxf gearman-mysql-udf-0.6.tar.gz [root@server5 redis]# cd gearman-mysql-udf-0.6 [root@server5 rhel7]# ls gearmand-1.1.12-18.el7.x86_64.rpm libevent-devel-2.0.21-4.el7.x86_64.rpm libgearman-1.1.12-18.el7.x86_64.rpm libgearman-devel-1.1.12-18.el7.x86_64.rpm libzip-0.10.1-8.el7.x86_64.rpm openssl-1.0.2k-16.el7.x86_64.rpm openssl-libs-1.0.2k-16.el7.x86_64.rpm php-cli-5.4.16-46.el7.x86_64.rpm php-common-5.4.16-46.el7.x86_64.rpm php-fpm-5.4.16-46.el7.x86_64.rpm php-mysql-5.4.16-46.el7.x86_64.rpm php-pdo-5.4.16-46.el7.x86_64.rpm php-pecl-gearman-1.1.2-1.el7.x86_64.rpm php-pecl-igbinary-1.2.1-1.el7.x86_64.rpm php-pecl-redis-2.2.8-1.el7.x86_64.rpm php-process-5.4.16-46.el7.x86_64.rpm php-xml-5.4.16-46.el7.x86_64.rpm [root@server5 rhel7]# yum install libevent-devel-2.0.21-4.el7.x86_64.rpm libgearman-* [root@server5 redis]# cd ../gearman-mysql-udf-0.6 [root@server5 gearman-mysql-udf-0.6]# ./configure --libdir=/usr/lib64/mysql/plugin/ --with-mysql [root@server5 gearman-mysql-udf-0.6]# make && make install [root@server3 ~]# mysql -p MariaDB [(none)]> CREATE FUNCTION gman_do_background RETURNS STRING SONAME -> 'libgearman_mysql_udf.so'; Query OK, 0 rows affected (0.01 sec) MariaDB [(none)]> CREATE FUNCTION gman_servers_set RETURNS STRING SONAME -> 'libgearman_mysql_udf.so'; Query OK, 0 rows affected (0.00 sec) ##查看函数 MariaDB [(none)]> 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 | +--------------------+-----+-------------------------+----------+ 3 rows in set (0.00 sec) ##指定 gearman 的服务信息 MariaDB [(none)]> SELECT gman_servers_set('172.25.19.1:4730'); +--------------------------------------+ | gman_servers_set('172.25.19.1:4730') | +--------------------------------------+ | 172.25.19.1:4730 | +--------------------------------------+ 1 row in set (0.02 sec)

编写 mysql 触发器(根据实际情况编写)

[root@server3 ~]# 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 ; [root@server3 ~]# mysql -pwestos < test.sql

查看触发器

MariaDB [(none)]> SHOW TRIGGERS FROM test;

server3:

[root@server3 ~]# ls gearman-mysql-udf-0.6.tar.gz nginx-1.17.4.tar.gz rhel7 lib_mysqludf_json-master.zip redis-5.0.3 test.sql mysql redis-5.0.3.tar.gz worker.php nginx-1.17.4 rhel6 Redis.pdf [root@server3 ~]# cp worker.php /usr/local/ [root@server3 ~]# cd /usr/local [root@server3 local]# ls bin games lib libexec rediscluster share worker.php etc include lib64 nginx sbin src [root@server3 local]# vi worker.php 1 <?php 2 $worker = new GearmanWorker(); 3 $worker->addServer(); 4 $worker->addFunction('syncToRedis', 'syncToRedis'); 5 6 $redis = new Redis(); 7 $redis->connect('172.25.34.5', 6379); ##改 8 9 while($worker->work()); 10 function syncToRedis($job) 11 { 12 global $redis; 13 $workString = $job->workload(); 14 $work = json_decode($workString); 15 if(!isset($work->id)){ 16 return false; 17 } 18 $redis->set($work->id, $work->name); 19 } 20 ?> [root@server3 local]# nohup php /usr/local/worker.php &> /dev/null & [1] 7929 [root@server3 local]# systemctl start gearmand ##打开gearmand [1]+ Exit 255 nohup php /usr/local/worker.php &>/dev/null [root@server3 local]# netstat -antuple Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address Foreign Address State User Inode PID/Program name tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 0 31086 7842/nginx: master tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 0 14167 629/sshd tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 0 15356 874/master tcp 0 0 0.0.0.0:4730 0.0.0.0:* ##4370gearman的端口 LISTEN 99

测试:

server5:

更新数据库信息

MariaDB [test]> update test set name='sm' where id=1; Query OK, 1 row affected (0.01 sec) Rows matched: 1 Changed: 1 Warnings: 0 MariaDB [test]> select * from test; +----+--------+ | id | name | +----+--------+ | 1 | sm | | 2 | test2 | | 3 | test3 | | 4 | test4 | | 5 | test5 | | 6 | test6 | | 7 | test7 | | 8 | test8 | | 9 | test9 | +----+--------+ 9 rows in set (0.00 sec)

server4:

127.0.0.1:6379> get 1 "sm" 127.0.0.1:6379>
最新回复(0)