fastcgi与cgi简单区别参考:https://www.jianshu.com/p/0cdaa89eeb7a
主从复制的特点:不实时 一定有延迟 网络因素 数据库sql性能 主 多线程 io上有复制延迟 从 默认为单线程
fastcgi与cgi的区别:
fastCGI有后台进程 9000端口在后台 一直运行 请求过来直接解析
cgi:fork一个新的进程进行处理
这个实验存在的问题是数据不同步 除非清除redis的缓存,让redis再去请求mysql取数据
或者在做update时,在redis中删除数据 ,但是所以最好的方式是在mysql中做触发(下一篇博客gearman会写到)
异步同步
数据流向,分为两种情况:
- webserver ----> (r/w) redisserver ----> 内置钩子函数 ----> input ----> mysql
- webserver ----> r (redisserver cache) <–> w mysql ----> update mysql ----> trigger(触发器) ----> redisserver
传统的 redis只做缓存 用来降低mysql访问压力。当客户端有请求过来时,会判断客户端的请求是post还是get,如果为post—写 则写到mysql中,如果为get—读 则读redis的缓存数据 (cache 缓存,数据从mysql里来)
此时如果客户端的请求是修改数据,即 mysql被update(数据被更新)的话, redis和mysql两者没同步就会导致数据不一致的问题,
而redis只有在他的数据过期或没有缓存的时侯才会去找mysql拿数据,
update后 会触发redisserver
实验环境
- rhel7且firewalld和selinux为stop并且disabled。
主机名(IP) | 服务 |
---|---|
server1(172.25.11.1) | php lamp前端 |
server2(172.25.11.2) | redis(中间的缓存) |
server3(172.25.11.3) | mysql(w) |
实验步骤
server1(lamp)
- 安装lamp架构需要的软件,开启httpd服务。
[root@server1 ~]# yum install httpd php php-mysql -y
[root@server1 ~]# systemctl start httpd
- 写一个php文件用于载浏览器中测试(这里是别人写好的,我们修改两处,redis服务器的ip和mysql服务器的ip)。
[root@server1 ~]# mv test.php /var/www/html/
[root@server1 ~]# vim /var/www/html/test.php
[root@server1 ~]# cat /var/www/html/test.php
<?php
$redis = new Redis();
$redis->connect('172.25.11.2',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('172.25.11.3','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>";
}
?>
- 加载php的模块,此时有mysql模块了,但是还没有redis。
[root@server1 ~]# php -m #查看所有
[root@server1 ~]# php -m | grep mysql #与mysql相关的,有3个
mysql
mysqli
pdo_mysql
[root@server1 ~]# php -m | grep redis #与redis相关的,不存在。
- 所以我们下载php有关redis的压缩包,解压(安装php的redis扩展)。
lftp 172.25.11.250:/pub/redis> get phpredis-master.zip
[root@server1 ~]# yum install unzip -y
[root@server1 ~]# unzip phpredis-master.zip
- 进入解压后的目录下,加载php的模块,发现报错了,这是因为我们缺少php的依赖包,我们下载并安装。
注意:phpize是一个运行脚本,主要作用是检测php的环境还有就是在特定的目录生成相应的configure文件,这样makeinstall之后,生成的.so文件才会自动加载到php扩展目录下面。
[root@server1 ~]# cd phpredis-master
[root@server1 phpredis-master]# ls
[root@server1 phpredis-master]# phpize
lftp 172.25.11.250:/pub/redis> get php-devel-5.4.16-42.el7.x86_64.rpm
[root@server1 phpredis-master]# yum install php-devel-5.4.16-42.el7.x86_64.rpm -y
- 再次加载,发现加载成功。
[root@server1 phpredis-master]# phpize
- 编译并安装,编译时加上激活redis的参数选项。
[root@server1 phpredis-master]# ./configure --enable-redis
[root@server1 phpredis-master]# make && make install
- 按照提示,安装完成后生成的模块都在此目录下。
- 修改php的初始化文件,修改时区为上海。
[root@server1 modules]# vim /etc/php.ini
878 date.timezone = Asia/Shanghai
- 拷贝mysql的初始化文件,修改内容为redis的模块名,加载redis模块。
[root@server1 modules]# cd /etc/php.d/
[root@server1 php.d]# cp mysql.ini redis.ini
[root@server1 php.d]# vim redis.ini
[root@server1 php.d]# cat redis.ini
extension=redis.so
- 重启httpd,再次查看与redis有关的模块,发现成功加载。
[root@server1 php.d]# systemctl restart httpd
[root@server1 php.d]# ps ax
[root@server1 php.d]# php -m | grep redis
redis
server2(redis)
- 部署redis服务。
具体流程参考本人之前的博客,这里简写。
lftp 172.25.11.250:/pub/redis> get redis-5.0.3.tar.gz
[root@server2 ~]# tar zxf redis-5.0.3.tar.gz
[root@server2 ~]# cd redis-5.0.3
[root@server2 redis-5.0.3]# yum install gcc && make && make install
[root@server2 redis-5.0.3]# cd utils/
[root@server2 utils]# ./install_server.sh
#修改配置文件
[root@server2 init.d]# vim /etc/redis/6379.conf
70 bind 0.0.0.0
#开启服务
[root@server2 init.d]# /etc/init.d/redis_6379 status
server3(mysql)
- 下载mariadb数据库的服务器端,开启服务,尝试登陆。
[root@server3 ~]# yum install mariadb-server -y
[root@server3 ~]# systemctl start mariadb
[root@server3 ~]# mysql
- 下载并导入test.sql库。
lftp 172.25.11.250:/pub/redis> get test.sql
[root@server3 ~]# mysql < test.sql
- test.sql文件的内容。
[root@server3 ~]# 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 ;
- 导入成功后我们查询一下导入的数据。
MariaDB [(none)]> use test;
MariaDB [test]> select * from test;
- 给用户和数据库授权。
MariaDB [test]> grant all on test.* to redis@'%' identified by 'westos';
测试
- 在浏览器中访问我们下载的测试页。
172.25.11.1/test.php
- 第一次是从mysql中读取到的数据。(因为redis中还没有缓存)
- 第二次是在redis数据库中。(缓存)
- 在redis数据库端查询数据。
- 但是,主从复制存在数据不一致的问题,即当用户更新mysql数据库中的数据时,reids端并不能立即同步修改后的数据库(除非清除缓存或数据过期),用户此时查询到的依然是之前的缓存。
#更新数据
MariaDB [test]> update test set name='westos' where id=1;
MariaDB [test]> select * from test;
- 浏览器中访问的结果依然没有改变。
- 但在如果在redis数据库清除更新的数据之后,用户再访问,数据就会刷新。
- 第一次,从mysql中读。
- 第二次,从redis中读,可以看到数据已经同步,读的是redis的缓存。
- 这里让两者同步的办法是清除redis中的缓存。
总结:
1.这种方式存在明显的问题:在mysql更新数据数据无法同步到redis上,虽然可以直接在redis中更新,但是在企业中更新的数据杂且多,而数据库的数据是比较稳定的,如果只在redis上更新,如果redis出现问题,则更新的数据会丢失,这是不可取的。
2.我们已经实现了 redis 作为 mysql 的缓存服务器,但是如果更新了 mysql,redis
中仍然会有对应的 KEY,数据就不会更新,此时就会出现 mysql 和 redis 数据不一致的情
况。所以接下来就要通过 mysql 触发器将改变的数据同步到 redis 中。