redis(三)nginx+redis+mysql实现读写分离

一、前言

1.读写分离的背景

实际的生产环境当中,客户端对数据库的读操作都是直接找redis拿数据的
如果redis缓存里面没有数据,那么就会去找mysql拿数据,并且给redis中缓存一份
redis中的数据有两种情况不能使用数据过期了或者mysql中的数据更新
用户读的时候访问redis,用户写的时候访问mysql
实际上读的需求量是很大的,redis刚好是把数据缓存在内存当中,响应速度也快
也可以降低我们后台mysql数据库的压力

2、为什么要有读写分离

一般对于高并发的系统来说,搭建一个健壮的缓存系统是不可避免的。
单机的reids的QPS可能只能上万,如果有再高并发的场景,单机是不能搞定的,就会有它的系统瓶颈。
一般来说缓存是用来支撑高并发读,这时候我们可能就会想到读写分离;
读写分离是用来处理读的并发量大,而写的并发量小的场景。

二、读写分离的实现

redis配合mysql
数据访问流程:client -> app -> redis -> mysql -> redis -> client
客户端用app访问,先在redis里读数据,因为快,redis没有才去mysql读,读完保存在redis里,然后返回客户端,下次再读就快

1、实验准备:

主机名 IP 功能
server1 172.25.58.1 前端服务器
server2 172.25.58.2 redis服务器
server3 172.25.58.3 mysql服务器

先停止server1和server3上的redis服务

[root@server1 ~]# killall redis-server     #由于之前有创建redis集群
#没有killall命令 yum whatprovides /usr/bin/killall
#[root@server1 ~]# yum install -y psmisc-22.20-11.el7.x86_64

或者:
[root@server3 ~]# /etc/init.d/redis_6379 stop
[root@server3 ~]# chkconfig redis_6379 off

开启server2上面的redis服务,并且查看redis节点是否为master节点,并且没有slave节点

搭建好共享yum源

2、基本读写分离的具体过程如下

server1上:

(1)、先安装nginx:具体详见我的关于nginx部署的博客https://mp.csdn.net/postedit/102691858

源码安装完nginx

[root@server1 ~]# ls
nginx-1.14.0.tar.gz  redis-5.0.3  redis-5.0.3.tar.gz
[root@server1 ~]# tar -xzvf nginx-1.14.0.tar.gz
[root@server1 ~]# cd nginx-1.14.0


[root@server1 nginx-1.14.0]# yum install openssl-devel -y
[root@server1 nginx-1.14.0]# yum install prce-devel -y

[root@server1 nginx-1.14.0]# ./configure --prefix=/usr/local/nginx --with-http_ssl_module --with-http_stub_status_module --with-threads --with-file-aio --user=nginx --group=nginx
[root@server1 nginx-1.14.0]# make && make install

(2)、编辑nginx的配置文件,将nginx的用户改为nginx,并加入php发布文件

[root@server1 nginx]# groupadd -g 900 nginx
[root@server1 nginx]# useradd -u 900 -g 900 nginx
[root@server1 nginx]# vim /usr/local/nginx/conf/nginx.conf

  2 #user  nobody;
  3 user  nginx nginx;


        location / {
            root   html;
            index  index.php index.html index.htm;
        }

        ...

        location ~ \.php$ {
            root           html;
            fastcgi_pass   127.0.0.1:9000;
            fastcgi_index  index.php;
            #fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
            include        fastcgi.conf;
        }

(2)、启动

启动并测试nginx

[root@server1 nginx]# /usr/local/nginx/sbin/nginx
nginx: [emerg] invalid number of arguments in "user" directive in /usr/local/nginx/conf/nginx.conf:4


###启动php-fpm
[root@server1 ~]# systemctl start php-fpm

##在server2上配置redis为master,因为之前做了主从,关闭server1的redis

#删除原来的key
[root@server2 ~]# redis-cli
127.0.0.1:6379> get name
"dd"
127.0.0.1:6379> DEL name
(integer) 1
127.0.0.1:6379> get name
(nil)

##配置测试页面
[root@server1 ~]# mv test.php /usr/local/nginx/html/
[root@server1 html]# mv test.php index.php

##再开启server3,关闭原来的mysql
[root@server3 ~]# rpm -qa | grep mysql
mysql-community-libs-5.7.24-1.el7.x86_64
mysql-community-server-5.7.24-1.el7.x86_64
mha4mysql-node-0.58-0.el7.centos.noarch
mysql-community-common-5.7.24-1.el7.x86_64
mysql-community-client-5.7.24-1.el7.x86_64
mysql-community-libs-compat-5.7.24-1.el7.x86_64

##卸载原来的mysql
[root@server3 ~]# rpm -e `rpm -qa | grep mysql` --nodeps

#安装mariadb,这里试验用这个就行
[root@server3 ~]# yum install -y mariadb-server

#清除原来数据目录里的内容
[root@server3 ~]# cd /var/lib/mysql
[root@server3 mysql]# rm -fr *

#启动mariadb
[root@server3 mysql]# systemctl start mariadb

#安全初始化
[root@server3 ~]# mysql_secure_installation    ##这里密码可以设置为简单的,如redhat

#登录数据库,授权用户
MariaDB [(none)]> create database test;
Query OK, 1 row affected (0.00 sec)

MariaDB [(none)]> grant all on test.* to redis@'%' identified by 'redhat';
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> flush privileges;
Query OK, 0 rows affected (0.00 sec)

##修改server1上nginx的发布文件test.php
vim test.php

  3         $redis->connect('172.25.0.2',6379) or die ("could net connect r    edis server");
 10                         $connect = mysql_connect('172.25.0.3','redis','    redhat');


##为server3上的mysql的test库加入一些数据
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 ;

##注释掉的目前用不到,是创建查询的触发器的


##导入数据
[root@server3 ~]# mysql -predhat < test.sql

#浏览器访问测试
172.25.0.1
可以看到导入的数据

mysql
number is 1
name is
number is 2
name is
number is 3
name is
number is 4
name is
number is 5
name is
number is 6
name is
number is 7
name is
number is 8
name is
number is 9
name is

#但是刷新一次后,可以看到后面就从redis读取数据

redis
number is 1
name is test1
number is 2
name is test2
number is 3
name is test3
number is 4
name is test4
number is 5
name is test5
number is 6
name is test6
number is 7
name is test7
number is 8
name is test8
number is 9
name is test9

#使用命令行也可以看到
[root@server2 ~]# redis-cli
127.0.0.1:6379> get 1
"test1"
127.0.0.1:6379> get 2
"test2"

##这个时候有个问题,如果此时mysql数据发生变更,redis会同步吗?
#在server3上
MariaDB [test]> update test set name='westos' where id=1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

#变更后发现,redis里没有变,浏览器也看不到变化,但是在redis里做的变化能看到
127.0.0.1:6379> set 2 redhat
OK
#刷新浏览器,看到变化,这样显然不合理

######配置gearmand######
在server1上启动
[root@server1 ~]# systemctl start gearmand

unzip lib_mysqludf_json-master.zip
在server3上解压lib_mysqludf_json-master.zip

#安装mariadb-devel
[root@server3 lib_mysqludf_json-master]# yum install -y mariadb-devel.x86_64

#编译模块(文档上有)
[root@server3 lib_mysqludf_json-master]# gcc $(mysql_config --cflags) -shared -fPIC -o lib_mysqludf_json.so lib_mysqludf_json.c

#将模块放到mysql插件目录
[root@server3 ~]# cp lib_mysqludf_json-master/lib_mysqludf_json.so /usr/lib64/mysql/plugin/

#在server3上查看
MariaDB [(none)]> show global variables like 'plugin_dir';
+---------------+--------------------------+
| Variable_name | Value                    |
+---------------+--------------------------+
| plugin_dir    | /usr/lib64/mysql/plugin/ |
+---------------+--------------------------+
1 row in set (0.00 sec)

#注册udf函数
MariaDB [(none)]> CREATE FUNCTION json_object RETURNS STRING SONAME 'lib_mysqludf_json.so';

#安装插件管理gearman的分布式队列
[root@server3 ~]# tar zxf gearman-mysql-udf-0.6.tar.gz

#先安装libgearman,从server1上scp

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

#编译安装gearman插件
[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函数
mysql -p

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;
+--------------------+-----+-------------------------+----------+
| name               | ret | dl                      | type     |
+--------------------+-----+-------------------------+----------+
| json_object        |   0 | lib_mysqludf_json.so    | function |
| gman_do_background |   0 | libgearman_mysql_udf.so | function |
| gman_servers_set   |   0 | libgearman_mysql_udf.so | function |
+--------------------+-----+-------------------------+----------+
3 rows in set (0.00 sec)

##指定gman服务信息
MariaDB [(none)]> SELECT gman_servers_set('172.25.0.1:4730');

##编写mysql触发器
[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 ;

##导入
[root@server3 ~]# mysql -p < test.sql

##查看触发器
MariaDB [(none)]> SHOW TRIGGERS FROM test;


##编写gman的worker端
[root@server1 ~]# cp worker.php /usr/local/
[root@server1 local]# vim worker.php
  7 $redis->connect('172.25.0.2', 6379);

##后台运行worker
[root@server1 ~]# nohup php /usr/local/worker.php &> /dev/null &

##修改数据库内容
MariaDB [test]> update test set name='westos' where id=2;

##在redis上查看
127.0.0.1:6379> get 2
"westos"

##页面查看,数据同步
redis
number is 1
name is redhat
number is 2
name is westos
number is 3
name is test3
number is 4
name is test4
number is 5
name is test5
number is 6
name is test6
number is 7
name is test7
number is 8
name is test8
number is 9
name is test9

发布了124 篇原创文章 · 获赞 18 · 访问量 3111

猜你喜欢

转载自blog.csdn.net/weixin_42221657/article/details/102981058