Redis——基于lamp架构做mysql的缓存服务器和配置gearman实现数据同步

news/2024/12/23 3:48:19

一.前言

对一个关系型数据库进行调优以获得高查询性能可能会比较困难。如果对数据模型优化和对查询调优不起作用,DBA就可以使用缓存系统,比如Redis,它是一个可以提供内存和永久数据存储的键值数据存储系统。

由于Redis能够将数据快速读写至数据存储系统,比起关系型数据库它更具性能优势。但是键值数据存储比较简单,它们没有类似SQL那样的查询语言或是结构化数据模型。取而代之的是,它们包含用键作为标识符并与值相关联的一个简单字典或是哈希模型。DBA可以通过这些键来存储和检索值。

键值存储简单而又快速,这使得它们可以很好地匹配关系型数据库丰富的数据模型和查询功能。有时使用键值和关系型数据库的组合是更好的选择。另外,还有大量支持商业化的键值数据库,包括Redis,Riak和Areospike。

要运行Redis缓存来优化常用查询的性能,首先要对你想要缓存的查询结果进行识别。将注意力集中在那些最频繁使用和耗时的查询上,然后从你要缓存的查询中识别数据。简言之,就是缓存一个查询返回的所有字段值。

流程图如下所示:

client——>app——>redis——>mysql——>redis——>client

二.基于lamp架构mysql的缓存服务器

实验环境:

主机服务
server1httpd,php等
server2redis服务器
server3mysql数据库

前提:

因为这之前是做过redis 高可用的。所以要将之前打开的redis-server的进程杀掉或者关闭

在这里插入图片描述
server2关闭主要是为了让它从slave变为master
在这里插入图片描述
server3也关闭
在这里插入图片描述

实验步骤如下所示:

第一步:配置server1和server2

  • server1:

server1上面安装相应的软件
在这里插入图片描述

编辑server1httpd的发布文件(我这里有已经写好的,上传到httpd的默认发布目录下,改改就好了)

在这里插入图片描述

test.php文件的内容如下
在这里插入图片描述在这里插入图片描述

<?php
        $redis = new Redis();
        $redis->connect('127.0.0.1',6379) or die ("could net connect redis server");
  #      $query = "select * from test limit 9";
        $query = "select * from test";
        for ($key = 1; $key < 10; $key++)
        {
                if (!$redis->get($key))
                {
                        $connect = mysql_connect('127.0.0.1','redis','westos');
                        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>";
        }
?>

修改test.php文件

在这里插入图片描述

在这里插入图片描述

开启httpd服务

[root@server1 ~]# systemctl start httpd

在这里插入图片描述

  • server2

因为server2之前是slave,所以我们需要将以下内容恢复,让其恢复为master

[root@server2 ~]# vim /etc/redis/6379.conf   
bind 0.0.0.0           #第70行的监听所有端口的内容不用动
#replicaof 172.25.27.1 6379
#min-replicas-to-write 1    #注释458和459行
#min-replicas-max-lag 10
[root@server2 ~]# /etc/init.d/redis_6379 start
[root@server2 ~]# redis-cli  info

在这里插入图片描述

在这里插入图片描述

第二步:配置server3

[root@server3 ~]# yum install mariadb-server -y
[root@server3 ~]# systemctl start mariadb 
[root@server3 ~]# mysql   #查看是否有test这个库,没有的话,创建

在这里插入图片描述
在这里插入图片描述

编写test数据库的测试文件(test.sql),并将其导入到test数据库中

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  < test.sql
[root@server3 ~]# mysql     #进去查看是否导入成功

在这里插入图片描述

在这里插入图片描述
添加授权用户:

[root@server3 ~]# mysql 
MariaDB [(none)]> grant all on test.* to 'redis'@'%' identified by 'westos';

在这里插入图片描述

第三步:server1添加redis模块

  • server1

此时的php只有mysql的模块,没有redis的模块,这样就无法将其联系起来 ,如下图所示:

在这里插入图片描述
此时去浏览器访问,是空白的

在这里插入图片描述

所以我们需要编译php的redis模块,首先将所需的安装包发送给server1

在这里插入图片描述

解压:
在这里插入图片描述

安装devel库

在这里插入图片描述

预编译:我们可以用./configure --help查看帮助

在这里插入图片描述

我们进行以下操作来将redis模板加入进去:

./configure --enable-redis
make
make install
cd /usr/lib64/php/modules
vim /etc/php.ini   #修改时区

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

cp mysql.ini  redis.ini
vim redis.ini
extension=redis.so    #加载 redis 模块(这个也可以在/etc/php.ini里面添加)
systemctl restart httpd
php -m | grep redis       #此时有了redis模板

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

第四步:测试

在浏览器输入172.25.27.1/test.php

在这里插入图片描述

也可以使用redis进行测试(要客户端先去访问,redis拿到数据之后在测试):

在这里插入图片描述

结论:看到了test数据库中的内容,宣告实验成功

但是此时有一个问题,我们修改了数据库里面的内容,redis已经缓存,所以客户端取到的还是原本旧的内容,redis并没有同步更新,只有将redis的缓存删掉,让其重新去数据库取数据,客户端才能得到更新的数据。

如下图所示:

修改数据库内容
在这里插入图片描述

在这里插入图片描述

此时客户端去访问,还是原本的数据

在这里插入图片描述
因为redis的数据没更新:

在这里插入图片描述

将redis缓存删除,在让客户端访问,此时数据就更新了

在这里插入图片描述
此时是redis去取数据:
在这里插入图片描述
在这里插入图片描述
因为此时redis重新去取了数据:
在这里插入图片描述

总结:到这里,我们已经实现了 redis 作为 mysql 的缓存服务器,但是如果更新了 mysql,redis中仍然会有对应的 KEY,数据就不会更新,此时就会出现 mysql 和 redis 数据不一致的情况。所以接下来就要通过 mysql 触发器将改变的数据同步到 redis 中。

因为我们总不能每次更新数据就手动删除redis里面的数据,那也忒麻烦了,为了解决这个问题,我们配置gearman实现数据同步(也就是mysql的触发器)

三.配置gearman实现数据同步

前言:

Gearman+PHP+MySQL UDF的组合异步实现MySQL到Redis的数据复制。

用redis作为Mysql数据库的缓存,在查找的时候,首先查找redis缓存,如果找到则返回结果;如果在redis中没有找到,那么查找Mysql数据库,找到的花则返回结果并且更新redis;如果没有找到则返回空。对于写入的情况,直接写入mysql数据库,mysql数据库通过触发器及UDF机制自动把变更的内容更新到redis中。采用MySQL作为数据存储引擎,Redis则作为Cache。

mysql读写数据都需要从磁盘读取。磁盘的容量,带宽的大小就影响了网站的访问速度,读取的方式,也就是sql语句,次数和效率也会影响读取效率。

redis和mc都是缓存,并且都是驻留在内存中运行的,这大大提升了高数据量web访问的访问速度。然而mc只是提供了简单的数据结构,比如
string存储;redis却提供了大量的数据结构,比如string、list、set、hashset、sorted set这些,这使得用户方便了好多,毕竟封装了一层实用的功能,同时实现了同样的效果,当然用redis而慢慢舍弃mc。

这个实验的实现需要使用新的工具gearmand

Gearman是一套用来把程式需求委派给机器,提供通用的程序框架来将任务分发在机器运算。它同时具备并行工作的能力、负载均衡处理的能力,以及在不同程序语言之间沟通的能力。

运行过程:

一个Gearman请求的处理过程涉及三个角色:Client -> Job -> Worker。

Client:请求的发起者,可以是 C,PHP,Perl,MySQL UDF 等等。

Job:请求的调度者,用来负责协调把 Client 发出的请求转发给合适的 Worker。

Worker:请求的处理者,可以是 C,PHP,Perl 等等。

因为 Client,Worker 并不限制用一样的语言,所以有利于多语言多系统之间的集成。

甚至我们通过增加更多的 Worker,可以很方便的实现应用程序的分布式负载均衡架构。

大致流程:

下面要编写的 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)

实验过程如下所示:

第一步:server3安装插件

将test.mysql文件不用的部分注释,将触发器部分的注释取消(这一步也可以放到后面做):

在这里插入图片描述
此时导入数据库是失败的,因为缺少模块,如下图:

在这里插入图片描述

我们需要编译数据库添加插件,使用lib_mysqludf_json的原因是因为Gearman只接受字符串作为入口参数,可以通过lib_mysqludf_jsonUDF 库函数将关系数据映射为 JSON 格式(MySQL中的数据编码为JSON字符串,起到统一标准的作用)。编译数据库需要mariadb-devel和gcc。

[root@server3 ~]# yum install unzip -y
[root@server3 ~]# unzip lib_mysqludf_json-master.zip 
[root@server3 ~]# cd lib_mysqludf_json-master
[root@server3 ~]# yum install gcc -y
[root@server3 ~]# yum install mariadb-devel -y   
 [root@server3 lib_mysqludf_json-master]# gcc $(mysql_config --cflags) -shared -fPIC -o lib_mysqludf_json.so lib_mysqludf_json.c

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
查看 :

[root@server3 lib_mysqludf_json-master]# mysql -uroot -proot
 MariaDB [(none)]> show global variables like 'plugin_dir';

在这里插入图片描述
拷贝 lib_mysqludf_json.so 模块到mysql的插件目录

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

在这里插入图片描述
数据库里注册 UDF 函数并查看

[root@server3 lib_mysqludf_json-master]# mysql -uroot -proot
MariaDB [(none)]> CREATE FUNCTION json_object RETURNS STRING SONAME 'lib_mysqludf_json.so;
MariaDB [(none)]> select * from mysql.func;

在这里插入图片描述

第二步:安装与配置 gearman

安装gearmand-1.1.12-18并且其对应的依赖包:

  • libgearman-1.1.12-18.el7.x86_64.rpm
  • libgearman-devel-1.1.12-18.el7.x86_64.rpm
  • ibevent-devel-2.0.21-4.el7.x86_64.rpm

将这下载好的这几个包上传给虚拟机:
在这里插入图片描述

[root@server3 ~]# yum install  gearmand-*  libevent-devel-2.0.21-4.el7.x86_64.rpm libgearman-*   -y   
[root@server3 ~]#systemctl start gearmand
[root@server3 ~]#netstat -antlp |grep gearmand

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

编译 gearman-mysql-udf

这个插件是用来管理调用 Gearman 的分布式的队列。

下载gearman-mysql-udf对应的软件包:

  • gearman-mysql-udf-0.6.tar.gz

步骤如下:

[root@server3 ~]# tar zxf gearman-mysql-udf-0.6.tar.gz 
[root@server3 ~]# cd gearman-mysql-udf-0.6
[root@server3 gearman-mysql-udf-0.6]# ls
[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 #编译与安装

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

注册 UDF 函数并查看

[root@server3 ~]# mysql -uroot -proot
#注册 UDF 函数:
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';
#查看函数:
MariaDB [(none)]> select * from mysql.func;

在这里插入图片描述
指定 gearman 的服务信息(这一步可以在上一步数据库里一起做)

在这里插入图片描述

root@server3 ~]# mysql
MariaDB [(none)]> SELECT gman_servers_set('172.25.27.1:4730');

在这里插入图片描述编写 mysql 触发器test.mysql(我们前面已经做过),将其导入数据库:

[root@server3 ~]# mysql  < test.sql  
[root@server3 ~]# mysql
MariaDB [(none)]> SHOW TRIGGERS FROM test;     

在这里插入图片描述

在这里插入图片描述

第三步:配置server1

安装 gearman(与server3过程一样,这里就粗略展示)

在这里插入图片描述在这里插入图片描述

在这里插入图片描述

安装php的gearman 扩展

此时php没有gearman模块
在这里插入图片描述
进行以下操作添加:

tar zxf gearman-1.1.2.tgz
cd gearman-1.1.2
phpize
./configure 
make && make install

在这里插入图片描述
在这里插入图片描述

编译完成界面:
在这里插入图片描述

cd /usr/lib64/php/modules    #查看是否有gearman模块
cd /etc/php.d
cp redis.ini  gearman.ini
vim gearman.ini
在里面写入:
extension=gearman.so

systemctl restart httpd
php -m | grep gearman

在这里插入图片描述

编写 gearman 的 worker 端——worker.php文件

worker.php文件内容如下:

<?php
$worker = new GearmanWorker();
$worker->addServer();
$worker->addFunction('syncToRedis', 'syncToRedis');
 
$redis = new Redis();
$redis->connect('172.25.27.2', 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);
}
?>

在这里插入图片描述
在这里插入图片描述

将修改好的worker.php放到/usr/local下,并后台运行

mv worker.php  /usr/local
nohup php /usr/local/worker.php &

在这里插入图片描述
查看服务进程:
在这里插入图片描述

查看服务端口:
在这里插入图片描述

第四步:测试

更新数据库里面的数据

[root@server3 ~]# mysql -uroot -proot 
MariaDB [(none)]> use test;
MariaDB [test]> update test set name='redhat' where id=2;

在这里插入图片描述

在这里插入图片描述

 MariaDB [test]> update test set name='hanghang' where id=3;

在这里插入图片描述
在这里插入图片描述

再次更新:
在这里插入图片描述在这里插入图片描述

大量更新:

在这里插入图片描述在这里插入图片描述

redis里面的数据也改变了

在这里插入图片描述


http://www.niftyadmin.cn/n/2864061.html

相关文章

hibernate学习之第十一篇(1)

hibernate的继承映射 《一》一张表映射一棵继承树 使用discriminator&#xff08;鉴别标志&#xff09; 类Worker和Farmer都继承自Person 类Person的源代码如下&#xff1a; package hibernate.extend; public class Person { private int id; private String name; private…

Redis——redis集群方案之codis集群的搭建部署

一.什么是codis集群 codis集群简介 Codis是一个分布式的Redis解决方案&#xff0c;对于上层的应用来说&#xff0c;连接Codis Proxy和连接原生的Redis Server没有明显的区别&#xff08;不支持的命令列表&#xff09;&#xff0c;上层应用可以像使用单机的Redis一样使用&#…

hibernate学习之第十一篇(2)

《二》每个子类映射到一张表&#xff08;joined-subclass&#xff09; 配置文件修改为&#xff1a; <?xml version"1.0" encoding"UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" &qu…

MFS——分布式文件系统的安装与部署

一.什么是MFS MFS简介 分布式文件系统是指文件系统管理的物理存储资源通过计算机网络与各节点相连。简单讲&#xff0c;就是把一些分散的共享文件夹&#xff0c;集合到一个文件夹内。对于用户来说&#xff0c;只需要打开该虚拟文件夹&#xff0c;就可以使用这些分散的文件夹进…

hibernate学习之第十二篇

《三》混合使用“一个类继承体系一张表”和“每个子类一张表” 比如上面的例子&#xff0c;worker类可能属性很少&#xff0c;而farmer属性却很多&#xff0c;把两者都与person放在同一张表中&#xff0c;则显得表的 结构不是很合理&#xff0c;会有很多字段是null。所以我们可…

MFS——如何恢复挂掉的mfsmaster服务

需要了解的知识&#xff1a; 在正常关闭的时候&#xff0c;/var/lib/mfs目录中会产生metadata.mfs这个文件&#xff0c;这个文件是开启mfsmaster服务时必备的文件。如果没有该文件,那么mfsmaster服务也就起不来。在正常开启的时候&#xff0c;/var/lib/mfs目录中就会产生metad…

hibernate学习之第十二篇(续)

《四》每个具体类映射一张独立的表&#xff08;union-subclass&#xff09;&#xff0c;即表与子类之间的独立一对一关系 所有的子类的表中的信息都是完整的&#xff0c;不需要对表进行关联了。 person.hbm.xml的配置如下&#xff1a; <?xml version"1.0" enco…

MFS ——利用pacemaker+corosync+pcs实现mfsmaster的高可用

一.什么是mfsmaster的高可用 我们知道mfsmaster是调度器&#xff0c;是mfs最核心的地方&#xff0c;如果mfsmaster挂了&#xff0c;整个mfs架构会挂掉&#xff0c;对此我们要对mfsmaster进行高可用冗余操作。 MFS文件系统中&#xff0c;master负责各个数据存储服务器的管理&am…