mysql:数据放在磁盘
是关系型数据库,主要用于存放持久化数据,
redis:数据放在内存 AOF:增量更新 RDB:覆盖
是NOSQL,非关系型数据库。
(1)类型上
从类型上来说,mysql是关系型数据库,redis是缓存数据库
(2)作用上
mysql用于持久化的存储数据到硬盘,功能强大,但是速度较慢
redis用于存储使用较为频繁的数据到缓存中,读取速度快
当网站的处理和访问量非常大的时候,我们的数据库的压力就变大了,数据库的连接池,数据库同时处理数据的能力就会受到很大的挑战,一旦数据库承受了其最大承受能力,网站的数据处理效率就会大打折扣。此时就要使用高并发处理、负载均衡和分布式数据库,而这些技术既花费人力,又花费资金。
Redis其实就是说把表中经常访问的记录放在了Redis中,然后用户查询时先去查询Redis再去查询MySQL,确实实现了读写分离,也就是Redis只做读操作。由于缓存在内存中,所以查询会很快。
由上图可以看出, 用户端访问时,请求直接发送给redis,假如redis有数据就可以直接返给用户,假如redis没有,他就会调取数据库上的数据,用户写入的时候是直接写到了数据库上。
我们主要解决的就是redis和mysql之间的数据同步的问题。
此时我们要模拟一个业务,读的时候从redis里面读,写的时候往mysql里面写,redis中没有的时候,我们要从数据库中进行加载。
step1:将server2作为redis端
先检查2是不是master ,如果是就可以了,如果不是,按下面的步骤进行操作:
server2: vim /etc/redis/6379.conf
注销replicaof 172.25.73.1 6379
加入server2本来就是master,这部忽略
redis-cli
info查看server2是否为master
step2: server4上进行操作,将server4作为数据库端
yum install -y mariadb-server.x86_64
systemctl start mariadb.service
step3: server3是作为lamp架构,在这里一定要注意选取一个干净的server节点去重新安装lamp架构,因为之前安装server1的lamp架构修改过好多参数,直接会影响实验结果
server3安装nginx:
yum install gcc pcre-devel openssl-devel -y 安装依赖性软件
[root@server3 nginx-1.20.2]# ./configure --with-http_ssl_module
[root@server3 nginx-1.20.2]# make && make install
安装好之后,创建软连接
ln -s /usr/local/nginx/sbin/nginx /usr/local/bin/
vim /usr/local/nginx/conf/nginx.conf 如下图
yum install gcc pcre-devel openssl-devel -y 安装依赖性软件
vim /usr/local/nginx/conf/nginx.conf
server3安装php
yum install -y php-fpm-5.4.16-46.el7.x86_64.rpm
yum install -y php
yum install -y php-mysql
yum install -y php-pecl-redis-2.2.8-1.el7.x86_64.rpm php-pecl-igbinary-1.2.1-1.el7.x86_64.rpm
所有的软件安装结束后
php -m |grep mysql
php -m |grep redis 查看安装是否成功
systemctl start php-fpm 开启php
server3上先安排一个默认发布目录
cp test.php /usr/local/nginx/html/
vim /usr/local/nginx/html/test.php
登陆数据库。先在数据库新建用户,授予远程登录权力并修改密码
grant all on test.* to redis@’%’ identified by ‘westos’;
导入数据库的备份文件
mysql < test.sql
server4登陆数据库查看导入效果
mysql
use test
show tables
select * from test;
此时由于是第一次读取,所以读取的是数据库的内容,刷新一次,redis中就有了缓存,此时由mysql变成了redis,这也就是为什么redis快的原因。
上面的实验做完我们会发现一个问题:
我们在配置文中可以看到,客户端访问的数据的时候,是先访问redis,如果在redis中访问不到,再去访问mysql。
那么,如果当数据库里的信息变更之后,redis中的数据没有和mysql保持同步,这个怎么办?
下图可以看出,在server4(mysql端)修改数据以后,redis上的数据还是原来的数据,并且网站页面上的数据也不会更新:
解决方式:我们需要通过异步的方式来进行修改。
当然,你在redis中 把id=1的内容删掉,然后重新读取mysql中的内容就好了,但是在生产环境中不现实,并且也失去了redis的意义。
这个时候我们需要改动一下数据库的问题,安装点外部的函数,但是会对数据库造成侵入性,对其安全性造成问题。现在我们会选择一些侵入性较小的方案来进行设计,比如阿里的canal,它是直接把自己伪装成mysql一个slave,完全通过mysql的主从复制来同步数据,对我们的数据主库是没有任何侵入性的,这点非常不错,如下图红框所示。
但是刚刚说的canal只是完成了蓝框中的内容,他只是完成了把数据从mysql中拿过来,至于复制过来以后怎么办,是需要你自己解决。
我们采用的解决方式:把redis作为mysql的一种缓存的方式,这种方式比较成熟了,数据量适中的时候,效果还不错,
但当数据量过大时,在mysql和redis之间需要加一个分布式消息队列,就是mysql里面的数据更新后,不要直接由mysql的plugin往redis里面放,没有做解耦,很容易出问题,所以中间最好有一个分布式的分发框架来做解耦这个事情,
也就是说,不能直接就是redis同步mysql,缺乏解耦性也不行,万一中间的链路出现问题呢?这样就太不安全了。
具体操作如下:
1、数据库端的操作
step1: 首先要在server4上安装utf函数
server4:解压
yum install -y unzip
unzip lib_mysqludf_json-master.zip
step2:安装软件
server4:安装gcc用于编译,安装maria插件
yum install -y gcc
yum install -y mariadb-devel
step3:
gcc $(mysql_config --cflags) -shared -fPIC -o lib_mysqludf_json.so lib_mysqludf_json.c
lib_mysqludf_json.c的意思是转换数据格式(因为mysql和redis 的数据结构不一样),将数据转换为json格式,这种格式的数据是可以跨平台的。
登陆mysql,
show global variables like ‘plugin_dir’; 查看一下数据库存放模块的目录,后边的命令需要
退出mysql。
cp lib_mysqludf_json.so /usr/lib64/mysql/plugin/
直接把影射文件扔到数据目录下,这样数据库能读到
ls /usr/lib64/mysql/plugin/ 查看一下复制是否成功
step4:
server4上,登陆数据库,注册udf函数:
CREATE FUNCTION json_object RETURNS STRING SONAME ‘lib_mysqludf_json.so’;
select * from mysql.func; 查看函数
server4:安装gearman服务
得到三个rpm包:libgearman-devel-1.1.12-18.el7.x86_64.rpm libgearman-1.1.12-18.el7.x86_64.rpm libevent-devel-2.0.21-4.el7.x86_64.rpm
serve4:
先安装依赖性软件再configure
yum install -y libgearman-devel-1.1.12-18.el7.x86_64.rpm libgearman-1.1.12-18.el7.x86_64.rpm libevent-devel-2.0.21-4.el7.x86_64.rpm
step6:
tar zxf gearman-mysql-udf-0.6.tar.gz
cd gearman-mysql-udf-0.6/
./configure --libdir=/usr/lib64/mysql/plugin/
make && make install
sep7:在server4上登陆数据库, 注册 UDF 函数
mysql> CREATE FUNCTION gman_do_background RETURNS STRING SONAME
‘libgearman_mysql_udf.so’; (用来指定发送给谁)
mysql> CREATE FUNCTION gman_servers_set RETURNS STRING SONAME
‘libgearman_mysql_udf.so’;(用来指定gearman server是谁)
select * from mysql.func; 查看函数
step8:
接下来选择一个节点作为gearman的服务器,在这里选择server3
server3: 安装包均在rhel7目录下
yum install -y gearmand-1.1.12-18.el7.x86_64.rpm libgearman-1.1.12-18.el7.x86_64.rpm
systemctl start gearmand.service 安装成功后开启服务
netstat -antlp 查看端口,一会编辑配置文件要用到
step9:
在server4上指定 gearman 的服务信息
SELECT gman_servers_set(‘172.25.73.3:4730’);
创建触发器,通过触发器来调用之前创建的函数,在这里已经有了一个写好的test.sql,可以直接使用
vim test.sql 只留下原来加了注释那部分
mysql < test.sql 导入触发器命令
mysql> SHOW TRIGGERS FROM test; 查看触发器
此时此刻,数据库端要做的事情就结束了。
2、gearman服务器端的操作
上面的步骤,我们创建了三个函数,创建了触发器,了解到了只要对数据库中的表做了修改,那么触发器就会生效,并将转换格式后的数据发送到【172.25.254.3:4730】,然后由这个gearmand的后台帮你调度,这个后台相当于一个分布式的分发框架,
那么数据到了server3上需要做什么呢?
server3相当于数据接收端,接收到数据以后,他要向下分发,分发给谁?
step1:
把worker文件配置好
cp worker.php /usr/local/
vim /usr/local/worker.php
修改对应行的redis节点信息,redis安装在那个节点就写那个
step2:
此时在server3上查询 php -m |grep gearman
发现依然没有,需要再安装一个插件。
yum install -y php-pecl-gearman-1.1.2-1.el7.x86_64.rpm
systemctl reload php-fpm.service 重新平滑加载服务
nohup php /usr/local/worker.php & 后边按一下回车。打入后台 让他一直处于监听状态。当4730端口i接收到数据后,会分发给我们的消费端,消费端然后去redis做一个同步。
ps ax 查看
在mysql端修改数据,在resis端已经能看出数据已经做出变更:
所以,我们可以看出,业务首先访问的就是redis,redis相当于mysql的一个缓冲,当我们有数据变更,直接mysql中更新,更新后的数据通过UDF函数,配合触发器把数据发送给4730端口(server3上),由他再分发给我们的worker,