redis 是一个高性能的 key-value 数据库。 redis 的出现,很大程度补偿了memcached 这类 keyvalue 存储的不足,在部分场合可以对关系数据库起到很好的补充作用。它提供了 Python,Ruby,Erlang,PHP 客户端,使用很方便。Redis 的所有数据都是保存在内存中,然后不定期的通过异步方式保存到磁盘上(这称为“半持久化模式”); 也可以把每一次数据变化都写入到一个 appendonly file(aof)里面(这称为“全持久化模式”)。
Redis 的两种同步模式对比
A>半持久化模式:RDB(全量同步)
i>RDB是Redis默认同步方式
ii>不定期的通过异步方式保存到磁盘上,快照最终结果( 快照二进制文件为dump.rdb)
iii>在恢复大数据集时的速度比 AOF 的恢复速度要快。
B>全持久化模式:(增量同步)
i>把每一次数据变化都写入到一个 append only file(aof)里面.
ii>没有RDB同步的快,但采用了高并发机制,对系统内存要求高.
iii>使用方式
#appendfsync always实时同步
appendfsync everysec每秒同步(推荐使用)
# appendfsync no
Redis作Mysql缓存服务器原理:
php默认从redis索取缓存数据,只有redis过期或删除,php才会从数据库索求数据。
实验环境:rhel6.5
server1:172.25.81.1(php)
server2:172.25.81.2(mysql)
server3:172.25.81.3(redis缓存)
server1配置:
1. 安装 lnmp 环境
安装以下软件包:
nginx php php-fpm php-cli php-common php-gd php-mbstring php-mysql
php-pdo php-devel mysql mysql-server
2. 安装 php 的 redis 扩展
3.安装并配置nginx
[root@server1 ~]# cd /usr/local/nginx/conf/
[root@server1 conf]# vim nginx.conf
43 location / {
44 root html;
45 index index.php index.html index.htm;
46 }65 location ~ \.php$ {
66 root html;
67 fastcgi_pass 127.0.0.1:9000;
68 fastcgi_index index.php;
69 #fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
70 include fastcgi.conf;
71 }[root@server1 conf]# ln -s /usr/local/nginx/sbin/nginx /sbin/
[root@server1 conf]# nginx -t
[root@server1 conf]# nginx
4.启动php
[root@server1 php-fpm.d]# systemctl start php-fpm
5.编辑nginx发布文件,设定server2为redis缓存,server3为mysql数据库
[root@server1 php-fpm.d]# cd /usr/local/nginx/html/
[root@server1 html]# ls
50x.html index.html[root@server1 html]# vim index.php
$redis = new Redis();
$redis->connect('172.25.81.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.81.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 "
";
for ($key = 1; $key < 10; $key++)
{
echo "number is $key";echo "
";echo "name is $data[$key]";
echo "
";
}
?>
server2配置
配置并开启redis服务
server3配置
配置mysql数据库
<1>清除之前安装过的mysql及其配置
[root@server3 ~]# cd /var/lib/mysql
[root@server3 mysql]# rm -fr *
[root@server3 ~]# rpm -qa | grep mysql
[root@server3 ~]# rpm -e `rpm -qa | grep mysql` --nodeps
<2>安装mariadb-server
[root@server3 ~]# yum install -y mariadb-server
[root@server3 ~]# systemctl start mariadb
<3>安全初始化
[root@server3 ~]# mysql_secure_installation
[root@server3 ~]# mysql -p
MariaDB [(none)]> create database test;
MariaDB [(none)]> grant all on test.* to redis@'%' identified by 'westos';
MariaDB [(none)]> flush privileges;
<4>
[root@server3 ~]# mysql -pwestos < test.sql ##将test数据库导入mysql
查看test数据库
测试:访问172.25.81.1
php默认从redis索取数据,第一次redis无缓存,则php从mysql索取数据
刷新页面,此时redis存在缓存,则php从redis索取数据
将server3中数据库内容更新
但php默从redis索取数据,redis不更新数据,故网页上数据无更新
以上redis 作为 mysql 的缓存服务器,但是如果更新了 mysql,redis中仍然会有对应的 KEY,数据就不会更新,此时就会出现 mysql 和 redis 数据不一致的情况。
mysql 触发器+gearman+php.worker
因为mysql和redis数据格式不同,不能实现直接同步,所以将MySQL数据首先放入Gearman中,然后通过一个自己编写的PHP+Gearman+Worker,将数据同步到Redis。
Gearman 是一个支持分布式的任务分发框架:
Gearman Job Server: Gearman 核心程序,需要编译安装并以守护进程形式运行在后台。
Gearman Client:可以理解为任务的请求者。
Gearman Worker:任务的真正执行者,一般需要自己编写具体逻辑并通过守护进程方式运行.
Gearman Worker 接收到 Gearman Client 传递的任务内容后,会按顺序处理。
大致流程:
1)下面要编写的 mysql 触发器,就相当于 Gearman 的客户端。
2)修改表,插入表就相当于直接下发任务。
3)再通过 lib_mysqludf_json UDF 库函数将关系数据映射为 JSON 格式
4)再通过 gearman-mysql-udf 插件将任务加入到 Gearman 的任务队列中
5)最后通过redis_worker.php,也就是 Gearman 的 worker 端来完成 redis 数据库的更新。
server1:
<1>php安装gearmand并开启服务
[root@server1 rhel7]# yum install -y gearmand-1.1.8-2.el6.x86_64.rpm libgearman-* libevent-*
[root@server1 ~]# systemctl start gearmand
<2>编写 gearman 的 worker 端
[root@server1 ~]# vim /usr/local/worker.php
$worker = new GearmanWorker();
$worker->addServer();
$worker->addFunction('syncToRedis', 'syncToRedis');$redis = new Redis();
$redis->connect('172.25.81.2', 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);
}
?>
server3:
<1>安装 lib_mysqludf_json并生成lib_mysqludf_json.so模块
[root@server3 ~]# unzip lib_mysqludf_json-master.zip
[root@server3 ~]# cd lib_mysqludf_json-master
[root@server3 lib_mysqludf_json-master]# yum install -y mariadb-devel gcc
[root@server3 lib_mysqludf_json-master]# gcc $(mysql_config --cflags) -shared -fPIC -o lib_mysqludf_json.so lib_mysqludf_json.c
拷贝 lib_mysqludf_json.so 模块:
[root@server3 lib_mysqludf_json-master]# cp lib_mysqludf_json.so /usr/lib64/mysql/plugin/
<2>注册 UDF 函数
[root@server3 lib_mysqludf_json-master]# mysql -p
MariaDB [(none)]> show global variables like 'plugin_dir'; ## 查看 mysql 的模块目录:
MariaDB [(none)]> CREATE FUNCTION json_object RETURNS STRING SONAME 'lib_mysqludf_json.so'; ##注册 UDF 函数
MariaDB [(none)]> select * from mysql.func; ##查看函数
<3>编译、安装gearman
这个插件是用来管理调用 Gearman 的分布式的队列。
[root@server3 ~]# yum install -y libgearman-1.1.12-18.el7.x86_64.rpm libgearman-devel-1.1.12-18.el7.x86_64.rpm libevent-devel-2.0.21-4.el7.x86_64.rpm ##安装编译所需的依赖包
[root@server3 ~]# tar zxf gearman-mysql-udf-0.6.tar.gz
[root@server3 ~]# cd gearman-mysql-udf-0.6
[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
指定 gearman 的服务信息
[root@server3 plugin]# 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 gman_servers_set('172.25.81.1:4730'); ##指定 gearman 的服务信息
编写 mysql 触发器
[root@server3 ~]# vim test.sql
use test;
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
查看触发器
[root@server3 ~]# mysql -p
MariaDB [(none)]> SHOW TRIGGERS FROM test;
测试:
server1:开启nginx、php-fpm
后台运行 worker
[root@server1 ~]# nohup php /usr/local/worker.php &> /dev/null &
server3:更改test数据库信息
[root@server3 ~]# mysql -p
MariaDB [(none)]> use test;
MariaDB [test]> update test set name='change' where id=1;
server2查看 redis
客户端: