查看create-cluster文件
可以看到里面指定了六个NODES(集群节点)
集群的使用:集群并不是由一些普通的Redis实例组成的,集群模式需要通过配置启用;
创建六个以端口号为名字的子目录, 在将每个目录中运行一个 Redis 实例,编辑文件redis.conf
cluster-enabled 选项用于开启实例的集群模式;
配置节点之间超时时间;
cluster-conf-file 选项设定了保存节点配置文件的路径,nodes.conf节点配置文件无须修改, Redis 集群在启动时创建, 并在有需要时自动进行更新。
开启Redis的AOF数据持久化存储,指定redis使用守护线程的方式启动;
编辑完成之后,启动第一个实例
查看进程
同样的,将7001目录下的redis.conf文件拷贝到其余5个目录,只需修改端口号即可
启动第二个实例
依次启动剩余实例
查看进程,可以看到6个redis节点都已经启动成功
可以看到生成的 appendonly.aof 日志文件
查看帮助文档
此时已经有6个正在运行中的 Redis 实例,我们需要使用这些实例来创建集群,replicas1 表示我们希望为集群中的每个主节点创建一个从节点;
可以看到,六个节点中, 三个为主节点, 其余三个则是各个主节点的从节点;
至此,Redi集群搭建成功,最后一段文字,显示了每个节点所分配的slots(哈希槽),这里总共6个节点,其中3个是从节点,所以3个主节点分别映射了0-5460、5461-10922、10933-16383solts。
集群分片模式
如果Redis只用复制功能做主从,那么当数据量巨大的情况下,单机情况下可能已经承受不下一份数据,更不用说是主从都要各自保存一份完整的数据。在这种情况下,数据分片(哈希分片)是一个非常好的解决办法。
Redis的Cluster正是用于解决该问题。它主要提供两个功能:
(1)自动对数据分片,落到各个节点上;
(2)即使集群部分节点失效或者连接不上,依然可以继续处理命令
输入yes
使用集群;
cluster info :查看集群状态
使用redis-cli来进行集群的交互;
使用客户端连接任意一个节点即可,使用-c 表示以集群的方式登录,-p 指定端口;
注意:一定要加上-c,不然节点之间是无法自动跳转的
可以看到主从信息
注意观察,它会自动切换到另一个redis去写或者读,可以看到在端口为7001的node上进行赋值操作,会重定向到在端口为7002的node上;
可以看到,端口为7006的节点虽然是端口为7001node节点的slave,但仍然能执行复制操作,说明redis集群无中心化的特点,任何节点都能进行读写操作
测试将端口号为7002的redis实例down掉
由于端口号为7002的redis实例是7004的master
因此,此时看不到7004redis实例的master
重新开启第二个redis实例
此时连接集群节点
可以看到相应的master
接下来演示节点加入redis集群的操作方式;
同样的继续建立两个以端口号为名字的子目录,在将每个目录中运行一个 Redis 实例,编辑文件redis.conf,修改端口号,启动相应实例
添加新的master节点(端口为7007的redis实例);
注意语法,一个新节点IP:端口 空格 一个旧节点IP:端口,注意点是:
1.不能多个新节点一次性添加;
2.新节点后是旧节点
这里是将节点加入了集群中,但是并没有分配slot(哈希槽),所以这个节点并没有真正的开始分担集群工作。
集群完整性检查:
集群完整性是指所有的槽都分配到存活的redis主节点上,只要16384个槽中有一个槽未被分配,则表示集群不完整
接下来为端口号为7007的redis实例分配相应的slave节点(端口号为7008的redis实例),后面要加上对应master的id(上图所示)
再次进行集群完整性检查,准备为加入集群的新的master(7007)分配哈希槽
分配slot需要使用以下参数
host:port :指定集群的任意一节点进行迁移slot,重新分slots
设定分配1000个,此时会自动从其余三个master节点为新的master节点分配一部分哈希槽,使得所有槽均匀分配
再次进行集群完整性检查,可以看到slot已经分配成功
测试将第一个redis实例down掉
再将第一个redis实例对应的slave节点的redis实例也down掉;
此时整个redis集群就已经down掉,无法正常工作
重新启动第二个和第六个redis实例
可以看到,此时第二个实例自动变为了原本是其slave的端口号为7004的redis节点的slave
输入info,可以看到指定redis服务的详细信息
缓存机制说明:所有的查询结果都放进了缓存,也就是把MySQL查询的结果放到了redis中去, 然后第二次发起该条查询时就可以从redis中去读取查询的结果,从而不与MySQL交互,也就实现了读写分离,也就是Redis只做读操作。由于缓存在内存中,所以查询会很快,从而达到优化的效果,redis的查询速度之于MySQL的查询速度相当于内存读写速度 /硬盘读写速度。
实验环境:server1(安装httpd,php等) 、server2(作为redis服务器)、 server3(部署mysql数据库服务);
除了server2,停止其余主机的redis服务。
首先将server3上将之前添加的环境变量去掉,恢复初始设定即可
server3安装mariadb-server服务
编辑mysql配置文件
设定如下;
datadir = path:从给定目录读取数据库文件;
socket = filename:为MySQL客户程序与服务器之间的本地通信指定一个**套接字文件(**仅适用于UNIX/Linux系统;默认设置一般是/var/lib/mysql/mysql.sock文件)
启动数据库服务,测试进入数据库
真机将下载的sql数据传给server3
数据库名为test,表名也是test
将test.sql文件的内容输入重定向到mysql数据库;
进入数据库查看test表,可以看到数据信息
接下来去server2(部署redis服务器),编辑主配置文件
replicaof用于追随某个节点的redis,被追随的节点为主节点,追随的为从节点;
将replicaof注释掉,此时server2成为单独的master
查看Redis 服务器的信息
接下来对server1进行配置,安装pstree;
Psmisc软件包包含三个帮助管理/proc目录的程序:
fuser 显示使用指定文件或者文件系统的进程的PID;
killall 杀死某个名字的进程,它向运行指定命令的所有进程发出信号;
pstree 树型显示当前运行的进程。
使用killall指令将serve1之前开启的redis服务进程都杀掉
确保server1的环境变量也为初始设定
安装Apache, PHP,以及php连接mysql库组件
查看 php 扩展
查看当前的php版本
真机获取test.php 文件,传给server1的Apache默认发布目录下
编辑test.php文件,设定redis服务提供者为server2,mysql服务提供者为server3
接下来进入数据库,添加授权用户操作
可以看到,此时server1的php 扩展中没有redis模块,这样就无法将其联系起来
真机将指定目录传给server1
server1安装相应rpm包
启动httpd服务
接着客户端访问网页,可以看到此时还看不到数据,这是因为当用户访问该网页时,其实先去访问的是redis服务,如果有缓存直接获取,没有的话再去mysql数据库取数据,并且会向redis缓存一份
刷新后就可以看到数据了
server2连接Redis服务器;
Get 命令可以获取到指定 key 的值
进入数据库,使用UPDATE 命令来更新 MySQL 中的数据
更新成功
但是网页上仍然获取到的是之前的数据,并没有看到数据更新(mysql与redis不能实时同步数据)
除非在redis服务中,手动进行赋值操作
客户端才会看到同步后的数据
到这里,我们已经实现了 redis 作为 mysql 的缓存服务器,但是如果更新了 mysql,redis
中仍然会有对应的 KEY,数据就不会更新,此时就会出现 mysql 和 redis 数据不一致的情
况。所以接下来就要通过 mysql 触发器将改变的数据同步到 redis 中。
真机将 lib_mysqludf_json 压缩包传给server3,server3需要编译数据库添加插件
安装unzip解压缩工具
解压缩,安装gcc编译工具;
lib_mysqludf_json UDF 库函数将关系数据映射为 JSON 格式。通常,数据库中的数据映
射为 JSON 格式,是通过程序来转换的。
安装 MariaDB-devel (包含开发首要的文件和一些静态库),编译数据库需要mariadb-devel和gcc
编译数据库
拷贝 lib_mysqludf_json.so 模块到 mysql 的插件目录
查看 mysql 的模块目录
注册 UDF 函数,查看函数
安装与配置 gearman:
在server1上安装 gearman 软件包
启动gearmand服务
真机将 gearman-mysql-udf 插件传给server3
接下来 server3 安装 gearman-mysql-udf,这个插件是用来管理调用 Gearman 的分布式的队列
配置,此时会出现报错,因为需要安装依赖性软件
server1将libgearman、libgearman-devel、libevent-devel的rpm包传给server3
安装依赖性
重新配置
编译、安装
可以看到库函数已经被安装到了/usr/lib64/mysql/plugin目录下
以软连接的形式
进入数据库,继续注册 UDF 函数;
查看函数
指定 gearman 的服务信息
编写 mysql 触发器
将前面的内容注释,后面触发器部分打开
重新将test.sql文件输入重定向到mysql数据库;
查看触发器
server1编写 gearman 的 worker 端
# vim worker.php
<?php
$worker = new GearmanWorker();
$worker->addServer();
$worker->addFunction('syncToRedis', 'syncToRedis');
$redis = new Redis();
$redis->connect('172.25.36.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); #这条语句就是将 id 作 KEY 和 name 作 VALUE 分开存储,需要和前面写的 php 测试代码的存取一致。
}
?>
由于php 扩展没有gearman模块,因此需要安装相应rpm包
接下来后台运行 gearman 的 worker
此时更新 mysql 中的数据
刷新测试页面可以看到数据同步
查看 redis
再次更新 mysql 中的数据
查看 redis
数据仍然同步