一.基于redis缓存数据库的lnmp架构的部署
1.数据流向
client–>app–>redis–>mysql–>redis—>client
当客户端访问数据时通过前端页面nginx取取数据,如果发现数据没在redis缓存中,然后直接去数据库中取数据,并且将数据写道redis中,然后将取得的数据通过前端界面返回给用户。
2.部署实现
- 实验环境:
1.主机环境
主机名(IP) | 服务 |
---|---|
server1(172.25.254.1) | nginx,php |
server2(172.25.254.2) | redis |
server3(172.25.254.3) | mysql |
2.实验环境清理
-
如果在server1上部署了redis的集群cluster应进行如下操作:
下载支持killall软件
杀掉与rediscluster相关的进程 -
如果安装了mysql,需要将mysql卸载掉,server1上只做nginx前端页面,操作如下:
注意:如果在server1上之前安装了nginx的openssl模块,因为在做数据缓存的同步更新的时候用到的gearman中需要openssl模块,会与nginx的openssl模块冲突,所以建议删掉虚拟机重新建立快照再进行实验操作。 -
原码编译安装nginx(server1)
a.官网下载nginx的压缩包并进行解压
b.官网下载依赖软件
c.进入解压目录下进行编译,并且安装,且在auto/cc/gcc文件中注释掉debug日志信息
[root@server1 nginx-1.16.0]# pwd
/root/nginx-1.16.0
[root@server1 nginx-1.16.0]# ./configure --prefix=/usr/local/nginx
[root@server1 nginx-1.16.0]# make && make install
编译安装完成之后:
注释debug日志信息:
d.nginx配置文件中打开php的配置
文件编辑内容如下:
在location资源中添加php的默认识别页面:
e.坚持nginx配置文件并且开启nginx
f.添加测试页在其默认发布目录
测试页index.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>";
}
?>
测试文件中修改连接的redis及数据库的相应信息内容如下:
- php的安装
a.官网下载php安装包及其依赖包并且安装
因为在后续实验中需要解决redis与mysql的数据同步更新问题,所以将gearman及其相关依赖包一并安装。
b.开启php-fpm服务并且查看端口
- 部署redis(server2)
由于之前实验已经部署好了redis,这里直接打开redis即可
注:如果之前做了redis的主从复制的部署,建议将redis的配置文件中的slaveof添加的内容注释掉
如果在redis中添加了数据将数据删掉,方便后续的实验效果:
- myslq的部署(server3)
a.如果安装了mysql卸载,并且删除数据库上缓存的数据
b.安装mariadb
c.开启数据库并且进行数据库的初始化
d.创建测试库并且对其该建立的数据库进行redis授权
e.导入测试数据库
测试文件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 ;
查看:
-
测试:
在浏览器页面输入:
http://172.25.254.1/
可以看到第一次是在数据库中,但当重新刷新页面的时候显示是在redis缓存中。
思考问题:
-
当在server3(mysql)上更新test数据库时,redis上已经缓存到了test数据库
在浏览器网页再次刷新查看发现更新数据无法同步 -
在server2(redis)上更新:
再次刷新网页发现数据同步更新
发现在mysql更新数据数据无法同步到redis上,可以直接在redis中更新,但是在企业中更新的数据杂且多,而数据库的数据是比较稳定的,如果只在redis上更新,如果redis出现问题,则更新的数据会丢失,这是不可取的。
二.gearman实现数据库和redis的数据同步更新
1.gearman介绍
gearman,从名字上看叫做“齿轮工”,就是通过齿轮把不同的组件组合在一起。
通常,多语言多系统之间的集成是项目开发中一个比较头疼的问题。一般会采用RPC风格或者是REST风格的WebService。但是总感觉比较麻烦。
gearman就应运而生了,作为一个任务分发架构,
它能够轻松的将前端的任务通过Job Server分发给后端的Worker处理
Gearman提供了一种通用的程序框架来将你的任务分发到不同的机器或者不同的进程当中。
它提供了你进行并行工作的能力、负载均衡处理的能力,以及在不同程序语言之间沟通的能力。
Gearman能够应用的领域非常广泛,从高可用的网站到数据库的复制任务。
总之,Gearman就是负责分发处理的中枢系统,它的优点包括:
- 开源:Gearman免费并且开源而且有一个非常活跃的开源社区
- 多语言支持:Gearman支持的语言种类非常丰富。
- 灵活:不必拘泥于固定的形式。您可以采用你希望的任何形式
- 快速:Gearman的协议非常简单,并且有一个用C语言实现的,经过优化的服务器,
保证应用的负载在非常低的水平。
2.gearman的工作原理
Gearman 提供了 Client 和 Worker 的 API,利用这些API 应用可以同 Gearman Job Server来进行通信。
Gearman 内部 Client 和 Worker 之间的通信都是通过 TCP 连接来进行的。
Gearman是一个支持分布式的任务分发框架。设计简洁,获得了非常广泛的支持。一个典型的Gearman应用包括以下这些部分:
- Gearman Job Server:Gearman核心程序,需要编译安装并以守护进程形式运行在后台
- Gearman Client:可以理解为任务的收件员,比如我要在后台执行一个发送邮件的任务,可以在程序中调用一个Gearman Client并传入邮件的信息,然后就可以将执行结果立即展示给用户,而任务本身会慢慢在后台运行。
- Gearman Worker:任务的真正执行者,一般需要自己编写具体逻辑并通过守护进程方式运行,Gearman Worker接收到Gearman Client传递的任务内容后,会按顺序处理。
类似的后台任务处理项目Resque。两者的设计其实非常接近,简单可以类比为:
- Gearman Job Server:对应Resque的Redis部分
- Gearman Client:对应Resque的Queue操作
- Gearman Worker:对应Resque的Worker和Job
这里之所以选择Gearman而不是Resque是因为Gearman提供了比较好用的MySQL UDF,工作量更小。
gearman的部署:
-
思路:
借用已经比较成熟的MySQL UDF,将MySQL数据首先放入Gearman中,然后通过一个自己编写的PHP Gearman Worker,将数据同步到Redis。比分析binlog的方式增加了不少流程,但是实现成本更低,更容易操作。 -
处理流程:
mysql–>update–>trigger–>json_map–>mysql plugin–>gearman(server)–>worker(php-gearman/php-redis)
【server1(nginx)】端:
在server1上开启gearnman服务因为之前已经下载了gearman
【mysql端(server3)】:
1.配置mysqludf_json工具,源码编译
lib_mysqludf_json 把mysql关系型数据转换成json格式的UDF工具
[root@server3 ~]# ls
lib_mysqludf_json-master.zip(相关压缩包) redis-5.0.3 redis-5.0.3.tar.gz test.sql
[root@server3 ~]# yum install unzip -y
[root@server3 ~]# unzip lib_mysqludf_json-master.zip
[root@server3 ~]# yum install gcc mariadb-devel -y //安装编译依赖软件
[root@server3 ~]# cd lib_mysqludf_json-master
[root@server3 lib_mysqludf_json-master]# ls
lib_mysqludf_json.c lib_mysqludf_json.so README.md
lib_mysqludf_json.html lib_mysqludf_json.sql
//编译mysqludf的插件模块及其.c模块
[root@server3 lib_mysqludf_json-master]# gcc $(mysql_config --cflags) -shared -fPIC -o lib_mysqludf_json.so lib_mysqludf_json.c
//将mysqludf插件模块cp到mysql的插件目录下
[root@server3 lib_mysqludf_json-master]# cp lib_mysqludf_json.so /usr/lib64/mysql/plugin/
登录mysql查看mysqludf的插件:
3.注册mysql的udf函数并且查看函数
3.安装gearman软件
4.编译安装mysql的mysqludf的json扩展
5.创建gearmna的udf函数
6.设置mysql端的gearman的nginx的前端服务器
7.编辑mysql端的测试文件打开相应的触发器模块,并且重新导入数据
8.登录数据库查看触发器
【server1(nginx)端gearman的worker的添加
1.编写worker.php
文件内容如下:
<?php
$worker = new GearmanWorker();
$worker->addServer();
$worker->addFunction('syncToRedis', 'syncToRedis');
$redis = new Redis();
$redis->connect('127.0.0.1', 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);
}
?>
2.后台运行worker
- 测试:
1.在mysql上更新数据
2.在rdis上查看数据已经同步
3.浏览器页面刷新发现数据同步