redis 作为 mysql的缓存服务器(读写分离)
环境准备
| IP | 主机名 | 服务 |
| 192.168.131.132 |
redis |
redis |
| 192.168.131.133 |
lnmp |
mysql+nginx+php |
[root@localhost ~]
CentOS Linux release 7.6.1810 (Core)
[root@localhost ~]
SELinux status: disabled
[root@localhost ~]
● firewalld.service - firewalld - dynamic firewall daemon
Loaded: loaded (/usr/lib/systemd/system/firewalld.service; disabled; vendor preset: enabled)
Active: inactive (dead)
Docs: man:firewalld(1)
[root@localhost ~]
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
[root@localhost ~]
[root@localhost ~]
部署nginx
[root@lnmp ~]
[root@lnmp ~]
php php-fpm php-cli php-common php-gd \
php-mbstring php-mysql php-pdo php-devel \
php-xmlrpc php-xml php-bcmath php-dba php-enchant
[root@lnmp ~]
nginx version: nginx/1.16.1
[root@lnmp ~]
PHP 5.4.16 (cli) (built: Apr 1 2020 04:07:17)
Copyright (c) 1997-2013 The PHP Group
Zend Engine v2.4.0, Copyright (c) 1998-2013 Zend Technologies
[root@lnmp ~]
[root@lnmp ~]
server {
listen 80;
server_name localhost;
root /usr/share/nginx/html;
include /etc/nginx/default.d/*.conf;
location / {
}
location ~ \.php$ {
root /usr/share/nginx/html;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /usr/share/nginx/html/$fastcgi_script_name;
include fastcgi_params;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
[root@lnmp ~]
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@lnmp ~]
[root@lnmp ~]
[root@lnmp ~]
[root@lnmp ~]
<?php
phpinfo();
?>
部署mysql
[root@lnmp ~]# wget https://repo.mysql.com/mysql57-community-release-el7-11.noarch.rpm
[root@lnmp ~]# yum -y install mysql57-community-release-el7-11.noarch.rpm
[root@lnmp ~]# yum -y install yum-utils # 安装yum管理工具
[root@lnmp ~]# yum-config-manager --disable mysql80-community # 禁用8.0版本
[root@lnmp ~]# yum-config-manager --enable mysql57-community # 启用5.7版本
[root@lnmp ~]# yum repolist enabled | grep mysql # 检查一下,确保只有一个版本
mysql-connectors-community/x86_64 MySQL Connectors Community 165
mysql-tools-community/x86_64 MySQL Tools Community 115
mysql57-community/x86_64 MySQL 5.7 Community Server 444
[root@lnmp ~]# yum -y install mysql-community-server mysql
[root@lnmp ~]# systemctl enable mysqld --now # 设为开机自启,并立即启动
[root@lnmp ~]# grep "temporary password" /var/log/mysqld.log
2020-07-30T12:36:18.820133Z 1 [Note] A temporary password is generated for root@localhost: 3j3Otwv%=uD*
[root@lnmp ~]# mysql -uroot -p'3j3Otwv%=uD*'
mysql> alter user 'root'@'localhost' identified by 'Test123.com';
Query OK, 0 rows affected (0.00 sec)
mysql> grant all privileges on *.* to 'root'@'192.168.131.%' identified by 'Test123.com';
Query OK, 0 rows affected, 1 warning (0.02 sec)
部署redis
[root@redis ~]
[root@redis ~]
[root@redis ~]
[root@redis ~]
[root@redis local]
[root@redis local]
[root@redis redis]
[root@redis redis]
[root@redis redis]
bind 192.168.131.133
protected-mode no
daemonize yes
[root@redis redis]
49183:C 09 Aug 15:03:11.798
49183:C 09 Aug 15:03:11.799
49183:C 09 Aug 15:03:11.799
[root@redis redis]
LISTEN 0 128 192.168.131.133:6379 *:* users:(("redis-server",pid=49184,fd=6))
[root@lnmp ~]
[root@lnmp ~]
[root@lnmp ~]
[root@lnmp phpredis-4.0.2]
Configuring for:
PHP Api Version: 20100412
Zend Module Api No: 20100525
Zend Extension Api No: 220100525
[root@lnmp phpredis-4.0.2]
[root@lnmp phpredis-4.0.2]
[root@lnmp ~]
[root@lnmp ~]
[redis]
extension=redis.so
[root@lnmp ~]
实现redis作为mysql的缓存服务器
[root@lnmp ~]# mysql -uroot -p
Enter password:
mysql> create database test;
Query OK, 1 row affected (0.01 sec)
mysql> use test;
Database changed
mysql> CREATE TABLE `test` (`id` int(7) NOT NULL AUTO_INCREMENT, `name` char(8) DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (0.11 sec)
mysql> INSERT INTO `test` VALUES (1,'test01'),(2,'test02'),(3,'test03'),(4,'test04'),(5,'test05'),(6,'test06'),(7,'test07'),(8,'test08'),(9,'test09');
Query OK, 9 rows affected (0.04 sec)
Records: 9 Duplicates: 0 Warnings: 0
mysql> select * from test.test;
+----+--------+
| id | name |
+----+--------+
| 1 | test01 |
| 2 | test02 |
| 3 | test03 |
| 4 | test04 |
| 5 | test05 |
| 6 | test06 |
| 7 | test07 |
| 8 | test08 |
| 9 | test09 |
+----+--------+
9 rows in set (0.00 sec)
编写php测试代码
[root@lnmp ~]
<?php
$redis = new redis();
$redis->connect('192.168.131.132',6379) or die ("could net connect redis server");
$query = "select * from test limit 8";
for ($key = 1; $key < 9; $key++)
{
if (!$redis->get($key))
{
$connect = mysql_connect('192.168.131.133','root','Test123.com');
mysql_select_db(test);
$result = mysql_query($query);
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 < 9; $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>";
}
?>
浏览器访问:192.168.131.133/test.php
可以获取到mysql内插入的内容就是成功了
到这里,我们已经实现了redis作为mysql的缓存服务器,但是如果更新了mysql,redis中仍然会有对应的KEY,数据就不会更新,此时就会出现mysql和redis数据不一致的情况。所以接下来就要通过mysql触发器将改变的数据同步到redis中。
通过gearman实现同步
Gearman是一个支持分布式的任务分发框架:
- Gearman Job Server:'Gearman核心程序,需要编译安装并以守护进程形式运行在后台。
- Gearman Client:'可以理解为任务的请求者。
- Gearman Worker:'任务的真正执行者,一般需要自己编写具体逻辑并通过守护进程方式运行,Gearman Worker接收到Gearman Client传递的任务内容后,会按顺序处理。
安装gearmand
[root@lnmp~]
[root@lnmp ~]
安装gearman的php扩展
[root@lnmp ~]
[root@lnmp ~]
[root@lnmp ~]
[root@lnmp gearman-1.1.2]
Configuring for:
PHP Api Version: 20100412
Zend Module Api No: 20100525
Zend Extension Api No: 220100525
[root@lnmp gearman-1.1.2]
[root@lnmp gearman-1.1.2]
[root@lnmp ~]
[gearman]
extension = gearman.so
[root@lnmp ~]
安装lib_mysqludf_json
[root@lnmp ~]# wget https://mirrors.tuna.tsinghua.edu.cn/mysql/downloads/MySQL-5.7/mysql-community-devel-5.7.31-1.el7.x86_64.rpm
[root@lnmp ~]# yum -y localinstall mysql-community-devel-5.7.31-1.el7.x86_64.rpm
[root@lnmp ~]# wget https://github.com/mysqludf/lib_mysqludf_json/archive/master.zip
[root@lnmp ~]# mv master.zip /usr/local/
[root@lnmp ~]# cd /usr/local/
[root@lnmp ~]# unzip master.zip
Archive: master.zip
37f851c808c4161beb4d5e535771dc0c59c82de6
creating: lib_mysqludf_json-master/
inflating: lib_mysqludf_json-master/README.md
inflating: lib_mysqludf_json-master/lib_mysqludf_json.c
inflating: lib_mysqludf_json-master/lib_mysqludf_json.html
inflating: lib_mysqludf_json-master/lib_mysqludf_json.so
inflating: lib_mysqludf_json-master/lib_mysqludf_json.sql
[root@lnmp local]# cd lib_mysqludf_json-master/
[root@lnmp lib_mysqludf_json-master]# gcc $(mysql_config --cflags) -shared -fPIC -o lib_mysqludf_json.so lib_mysqludf_json.c
[root@lnmp ~]# mysql -uroot -p
Enter password:
mysql> show global variables like 'plugin_dir';
+---------------+--------------------------+
| Variable_name | Value |
+---------------+--------------------------+
| plugin_dir | /usr/lib64/mysql/plugin/ |
+---------------+--------------------------+
1 row in set (0.06 sec)
[root@lnmp ~]# cp /usr/local/lib_mysqludf_json-master/lib_mysqludf_json.so /usr/lib64/mysql/plugin/ # 将插件copy到上面mysql获取到的目录下
[root@lnmp ~]# mysql -uroot -p
Enter password:
mysql> CREATE FUNCTION json_object RETURNS STRING SONAME 'lib_mysqludf_json.so';
Query OK, 0 rows affected (0.00 sec)
安装gearman-mysql-udf
[root@lnmp ~]# wget https://launchpad.net/gearman-mysql-udf/trunk/0.6/+download/gearman-mysql-udf-0.6.tar.gz
[root@lnmp ~]# tar xf gearman-mysql-udf-0.6.tar.gz
[root@lnmp ~]# cd gearman-mysql-udf-0.6/
[root@lnmp gearman-mysql-udf-0.6]# ./configure --with-mysql=/usr/bin/mysql_config --libdir=/usr/lib64/mysql/plugin/ # libdir的路径,要改为自己mysql里面查询出来的路径
[root@lnmp gearman-mysql-udf-0.6]# make && make install
# 注册UDF函数
[root@lnmp ~]# mysql -uroot -p
Enter password:
mysql> CREATE FUNCTION gman_do_background RETURNS STRING SONAME 'libgearman_mysql_udf.so';
Query OK, 0 rows affected (0.01 sec)
mysql> CREATE FUNCTION gman_servers_set RETURNS STRING SONAME 'libgearman_mysql_udf.so';
Query OK, 0 rows affected (0.00 sec)
mysql> 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 |
+--------------------+-----+-------------------------+----------+
2 rows in set (0.00 sec)
编写mysql触发器
# 根据实际情况编写
[root@lnmp ~]# mysql -uroot -p
Enter password:
mysql> use test;
Database changed
mysql> DELIMITER $$
mysql> 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 $$
mysql> DELIMITER;
编写gearman的worker端
[root@lnmp ~]
<?php
$worker = new GearmanWorker();
$worker->addServer();
$worker->addFunction('syncToRedis', 'syncToRedis');
$redis = new redis();
$redis->connect('192.168.131.132', 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);
}
?>
[root@lnmp ~]
更新mysql中的数据
[root@lnmp ~]# mysql -uroot -p
Enter password:
mysql>set @RECV= 1;
mysql>select @RECV;
l>use mytest;
mysql> update test set name = 'ssss' where id = 1;
mysql> select @RECV;