Redis做mysql的前端缓存

简介

项目中,MySQL数据库服务器有时会位于另外一台主机,需要通过网络来访问数据库;即使应用程序与MySQL数据库在同一个主机中,访问MySQL也涉及到磁盘IO操作(MySQL也有一些数据预读技术,能够减少磁盘IO读写,此部分后续继续研究),总之,直接从MySQL中读取数据不如直接从内存中读取数据来的效率高。为了提高数据库访问效率,人们采用了各种各样的方法,其中方法之一就是使用一个给予内存的缓存系统放置在数据库和应用程序之间。在查找数据的时候,首先从内存中查找,如果找到则使用,如果没有找到,那么再真正访问数据库。这种方法在一些场景下(例如:频繁查找相同数据)能够提高系统的整体效率。
在这里插入图片描述
读取步骤:

  1. client读取redis,如果命中返回结果,如果没有命中转到2.
  2. client读取数据库,在数据库中没有查到,返回空;在数据库中查到了,返回查到的结果并更新Redis。
    写入步骤:
  3. client修改/删除或者新增数据到MySQL。
  4. MySQL的触发器调用用户自定义的UDF。
  5. UDF把修改/删除或者新增的数据更新到redis中。

实验环境

主机 ip 服务
server1 172.25.62.1 nginx
server2 172.25.62.2 redis
server3 172.25.62.3 mysql

搭建步骤:

在server1

1.安装nginx
因为要进行缓存的测试,所以要用一台主机作为服务器的前端提供访问。

[root@server1 ~]# tar zxf nginx-1.16.0.tar.gz 
[root@server1 nginx-1.16.0]# ./configure --prefix=/usr/local/nginx

在这里插入图片描述

[root@server1 nginx-1.16.0]# make && make install

进入目录进行编译安装。
2.修改配置

[root@server1 ~]# vim /usr/local/nginx/conf/nginx.conf
 35     server {
 36         listen       80;
 37         server_name  localhost;
 38         location / {
 39             root   html;
 40             index  index.php index.html index.htm;
 41         }   
 42         error_page   500 502 503 504  /50x.html;
 43         location = /50x.html {
 44             root   html;
 45         }   
 46 
 47         location ~ \.php$ {
 48             root           html;
 49             fastcgi_pass   127.0.0.1:9000;
 50             fastcgi_index  index.php;
 51             #fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
 52             include        fastcgi.conf;
 53         } 

修改nginx主配置文件,使浏览器默认访问php页面。

[root@server1 ~]#/usr/local/nginx/sbin/nginx -t
[root@server1 ~]#/usr/local/nginx/sbin/nginx	

启动nginx。
3.编写php默认发布页

[root@server1 ~]# vim /usr/locacl/nginx/html/index.html
1 <?php
  2         $redis = new Redis();
  3         $redis->connect('172.25.62.2',6379) or die ("could net connect redis server");	##安装redis的ip
  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.62.3','redis','redhat');		##安装mysql的ip
 11                         mysql_select_db(test);
 12                         $result = mysql_query($query);
 13                         //如果没有找到$key,就将该查询sql的结果缓存到redis
 14                         while ($row = mysql_fetch_assoc($result))
 15                         {
 16                                 $redis->set($row['id'],$row['name']);
 17                         }
 18                         $myserver = 'mysql';
 19                         break;
 20                 }
 21                 else
 22                 {
 23                         $myserver = "redis";
 24                         $data[$key] = $redis->get($key);
 25                 }
 26         }
 27 
 28         echo $myserver;
 29         echo "<br>";
 30         for ($key = 1; $key < 10; $key++)
 31         {
 32                 echo "number is <b><font color=#FF0000>$key</font></b>";
 33 
 34                 echo "<br>";
 35 
 36                 echo "name is <b><font color=#FF0000>$data[$key]</font></b>";
 37 
 38                 echo "<br>";
 39         }
 40 ?>                                                                                                                           

4.安装php以及相关软件

[root@server1 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@server1 rhel7]# yum install -y *

安装上面所有软件。

[root@server1 rhel7]# systemctl start php-fpm

开启php。

在server2

1.安装redis
详见Redis的主从复制和高可用性中redis的安装部分。
安装后的redis不能作为主从复制的从节点,必须本身为master节点,如果设置了要修改文件。

[root@server2 ~]# vim /etc/redis/6379.conf

将主从复制的内容删除就可以了。
2.开启redis

[root@server2 ~]# redis-cli

在这里插入图片描述
开启redis,测试功能是否正常。

在server3

1.安装mariadb,进行安全初始化

[root@server3 ~]# yum install -y mariadb-server
[root@server3 ~]# systemctl start mariadb

安装并开启mysql。

[root@server3 ~]# mysql_secure_installation

在这里插入图片描述

安全初始化。
2.对数据库进行授权

[root@server3 ~]# mysql -p
MariaDB [(none)]> create database test;
MariaDB [(none)]> grant all on test.* to redis@'%' identified by 'redhat';
MariaDB [(none)]> flush privileges;

创建test库,对用户和test库进行授权。
3.将数据导入数据库

[root@server3 ~]# vim test.sql
  1 use test;
  2 CREATE TABLE `test` (`id` int(7) NOT NULL AUTO_INCREMENT, `name` char(8) D    EFAULT NULL, PRIMARY KEY (`id`))     ENGINE=InnoDB DEFAULT CHARSET=utf8;
  3 INSERT INTO `test` VALUES (1,'test1'),(2,'test2'),(3,'test3'),(4,'test4'),    (5,'test5'),(6,'test6'),(7,'test    7'),(8,'test8'),(9,'test9');
  4 
  5 #DELIMITER $$
  6 #CREATE TRIGGER datatoredis AFTER UPDATE ON test FOR EACH ROW BEGIN
  7 #    SET @RECV=gman_do_background('syncToRedis', json_object(NEW.id as `id    `, NEW.name as `name`));
  8 #  END$$
  9 #DELIMITER ;

编写库文件。

[root@server3 ~]#  mysql -predhat < test.sql

将数据导入数据库,下面是导入的内容。
在这里插入图片描述
这样就完成基本配置了。

测试:

输入做前端的server1的ip进行测试。
在这里插入图片描述
首先我们看到的是mysql中的数据,访问到mysql的数据之后,这些数据回被缓存到redis里,第二此访问就不再访问mysql,而是从redis缓存中取数据。
在这里插入图片描述
第二次访问的是redis中的数据。

redis和mysql的数据同步更新

虽然redis可以作为mysql的缓存,但是当mysql中的数据更新时,访问到的redis中的内容是没有更新的,所以要设置两个库的同步更新。
在这里插入图片描述
如图,将test表中的test1改为redhat,之后进行访问。
在这里插入图片描述
可以看到数据没有更新。

在server3

1.安装相关软件

[root@server3 ~]# yum install mariadb-devel -y

安装mariadb-devel。
在这里插入图片描述

[root@server3 ~]# unzip lib_mysqludf_json-master.zip

获取lib_mysqludf包并解压。

[root@server3 lib_mysqludf_json-master]# gcc $(mysql_config --cflags) \
-shared -fPIC -o lib_mysqludf_json.so lib_mysqludf_json.c

在这里插入图片描述
进入目录进行编译。

[root@server3 ~]# cp lib_mysqludf_json-master/lib_mysqludf_json.so /usr/lib64/mysql/plugin/

将编译出的模块放到mysql插件目录。

MariaDB [(none)]> show global variables like 'plugin_dir';

在这里插入图片描述
在数据库中查看插件是否加入。

[root@server3 ~]# tar zxf gearman-mysql-udf-0.6.tar.gz
[root@server3 gearman-mysql-udf-0.6]# pwd
/root/gearman-mysql-udf-0.6
[root@server3 gearman-mysql-udf-0.6]# ./configure --libdir=/usr/lib64/mysql/plugin/ --with-mysql
[root@server3 gearman-mysql-udf-0.6]# make && make install

在这里插入图片描述
编译安装gearman插件。
在这里插入图片描述

[root@server3 rhel7]# yum install -y libevent-devel-2.0.21-4.el7.x86_64.rpm libgearman-*

安装libevent-devel,libgearman,libgearman-devel。

2.在数据库内进行操作

MariaDB [(none)]> CREATE FUNCTION json_object RETURNS STRING SONAME 'lib_mysqludf_json.so';
MariaDB [(none)]> CREATE FUNCTION gman_do_background RETURNS STRING SONAME 'libgearman_mysql_udf.so';
MariaDB [(none)]> CREATE FUNCTION gman_servers_set RETURNS STRING SONAME 'libgearman_mysql_udf.so';

注册udf函数。

MariaDB [(none)]> select * from mysql.func;

查看函数,指定german服务信息。

MariaDB [(none)]> SELECT gman_servers_set('172.25.62.1:4730');

在这里插入图片描述
3.编写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 -uroot -predhat

导入数据。

MariaDB [(none)]> show triggers from test;

在这里插入图片描述
查看状态,这样,在mysql端的操作就完成了。

在server1

1.安装gearmand

[root@server3 ~]# gearmand-1.1.12-18.el7.x86_64.rpm

获取gearmand-1.1.12-18.el7.x86_64.rpm包进行安装。

[root@server1 rhel7]# systemctl start gearmand

开启服务。
2.编写worker.php

[root@server1 local]# pwd
/usr/local
[root@server1 local]# vim 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.62.2', 6379);		##修改ip为redis端的ip
  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@server1 ~]# nohup php /usr/local/worker.php &> /dev/null &

开启worker.php进程。

测试:

在server3修改test表内容

MariaDB [test]> update test set name='Linux' where id=2;

在这里插入图片描述
在浏览器查看。
在这里插入图片描述
可以看到,test2的内容随着数据库更新了,由于test1是在设定之前就修改了,所以没有更新。

猜你喜欢

转载自blog.csdn.net/qq_41961805/article/details/90212799