Redis集群配置(创建集群,添加节点,redis结合mysql,数据同步)

一.Redis集群介绍

1.Redis 集群是一个提供在多个Redis间节点间共享数据的程序集。Redis集群并不支持处理多个keys的命令,因为这需要在不同的节点间移动数据,从而达不到像Redis那样的性能,在高负载的情况下可能会导致不可预料的错误.Redis 集群通过分区来提供一定程度的可用性,在实际环境中当某个节点宕机或者不可达的情况下继续处理命令. Redis 集群的优势:自动分割数据到不同的节点上。

2.Redis 集群的数据分片

Redis 集群没有使用一致性hash, 而是引入了 哈希槽的概念.
Redis 集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽.集群的每个节点负责一部分hash槽,举个例子,比如当前集群有3个节点,那么
节点 A 包含 0 到 5500号哈希槽.
节点 B 包含5501 到 11000 号哈希槽.
节点 C 包含11001 到 16384号哈希槽.
这种结构很容易添加或者删除节点. 比如如果我想新添加个节点D, 我需要从节点 A, B, C中得部分槽到D上. 如果我想移除节点A,需要将A中的槽移到B和C节点上,然后将没有任何槽的A节点从集群中移除即可. 由于从一个节点将哈希槽移动到另一个节点并不会停止服务,所以无论添加删除或者改变某个节点的哈希槽的数量都不会造成集群不可用的状态

二.redis集群配置

server1上安装了redis,先关闭之前的redis

[root@server1 ~]# /etc/init.d/redis_6379 stop

1.新建目录,编辑配置文件

[root@server1 ~]# mkdir /usr/local/rediscluster

[root@server1 rediscluster]# mkdir 700{1..6}
[root@server1 7001]# vim redis.conf 
port 7001
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
pidfile "/usr/local/rediscluster/7001/redis.pid"
logfile "/usr/local/rediscluster/7001/redis.log"
daemonize yes
dir "/usr/local/rediscluster/7001"

#启动
[root@server1 7001]# redis-server redis.conf
#查看进程
ps ax

 1332 ?        Ssl    0:00 redis-server *:7001 [cluster]
 [root@server1 7001]# redis-cli -p 7001
127.0.0.1:7001> info

#Cluster
cluster_enabled:1	##集群激活

#同理配置7002~7006,并启动

Redis集群配置(创建集群,添加节点,redis结合mysql,数据同步)_第1张图片

2.拷贝ruby脚本

[root@server1 src]# pwd
/root/redis-5.0.3/src
[root@server1 src]# cp redis-trib.rb /usr/local/bin/
[root@server1 src]# yum install -y ruby

3.创建集群

[root@server1 ~]# redis-cli --cluster create --cluster-replicas 1 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 127.0.0.1:7006
Redis集群配置(创建集群,添加节点,redis结合mysql,数据同步)_第2张图片
[OK] All 16384 slots covered. #看到这个表示16384个槽都分配好了

#查看集群信息
[root@server1 ~]# redis-cli --cluster info 127.0.0.1:7001
	##输入其他端口也可以,但是必须输一个端口

Redis集群配置(创建集群,添加节点,redis结合mysql,数据同步)_第3张图片

4.测试存储信息

[root@server1 ~]# redis-cli -c -p 7001
127.0.0.1:7001> get name
-> Redirected to slot [5798] located at 127.0.0.1:7002
(nil)
127.0.0.1:7002> set name douluo
OK
127.0.0.1:7002> get name 
"douluo"
127.0.0.1:7002> quit
[root@server1 ~]# redis-cli -c -p 7005
127.0.0.1:7005> get name
-> Redirected to slot [5798] located at 127.0.0.1:7002
"douluo"			#在任意节点都可以获取到信息,但是都会跳转到7002
127.0.0.1:7002> quit

##挂掉7002,key还会保存在7004上

三.redis添加新的节点

1.添加节点

server1上已经有6个节点
cd /usr/local/rediscluster
[root@server1 rediscluster]# cp 7001/redis.conf 7007/
[root@server1 rediscluster]# cp 7001/redis.conf 7008/

[root@server1 7007]# redis-server redis.conf
[root@server1 7008]# redis-server redis.conf

[root@server1 7008]# redis-cli --cluster add-node 127.0.0.1:7007 127.0.0.1:7001	
##添加节点

Redis集群配置(创建集群,添加节点,redis结合mysql,数据同步)_第4张图片

2.查看节点信息

[root@server1 7008]# redis-cli -c -p 7007
127.0.0.1:7007> cluster nodes ##查看节点信息

在这里插入图片描述

发现7007没有哈希槽
尽管新节点没有包含任何哈希槽, 但它仍然是一个主节点, 所以在集群需要将某个从节点升级为新的主节点时, 这个新节点不会被选中,所以要添加一个slave
[root@server1 ~]# redis-cli --cluster add-node 127.0.0.1:7008 127.0.0.1:7007 --cluster-slave --cluster-master-id 7d3fb70a5e9d098977cc873c3aad6433e2b064b0  
 ##master的id
[root@server1 ~]# redis-cli --cluster info 127.0.0.1:7001	##查看集群信息

Redis集群配置(创建集群,添加节点,redis结合mysql,数据同步)_第5张图片

3.为新节点分配哈希槽

reshard分配不均等,可能导致数据不同步

[root@server1 ~]# redis-cli --cluster reshard 127.0.0.1:7007

How many slots do you want to move (from 1 to 16384)? 300 ##随便分配一点

What is the receiving node ID? b9ee016d45dde6a0067dd3e19139f1044a621d77 ##接收哈希槽的节点ID

Please enter all the source node IDs.
Type ‘all’ to use all the nodes as source nodes for the hash slots.
Type ‘done’ once you entered all the source nodes IDs.
Source node #1: all
#从所有节点获取哈希槽
[root@server1 ~]# redis-cli --cluster check 127.0.0.1:7001 ##检查可以看到已经分配哈希槽
Redis集群配置(创建集群,添加节点,redis结合mysql,数据同步)_第6张图片

rebalance均分哈希槽
[root@server1 ~]# redis-cli --cluster rebalance --cluster-threshold 1 --cluster-use-empty-masters 127.0.0.1:7001	##均分哈希槽

[root@server1 ~]# redis-cli --cluster check 127.0.0.1:7001

##查看数据[root@server1 ~]# redis-cli -c -p 7008

Redis集群配置(创建集群,添加节点,redis结合mysql,数据同步)_第7张图片
Redis集群配置(创建集群,添加节点,redis结合mysql,数据同步)_第8张图片
在这里插入图片描述

查询数据成功,新节点添加完成

四.redis结合mysql

数据访问流程:client -> app -> redis -> mysql -> redis -> client
客户端用app访问,先在redis里读数据,速度快,redis没有才去mysql读,读完保存在redis里,然后返回客户端,下次获取数据回更快

1.server1上配置nginx和php

##首先在server1配置好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;
    }

#启动并测试nginx

###安装启动php-fpmRedis集群配置(创建集群,添加节点,redis结合mysql,数据同步)_第9张图片

2.server2上配置redis

/etc/init.d/redis_6379 restart 
#删除原来的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)

3.server3配置数据库

##开启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)

4.给server3数据库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

5.修改server1的默认发布页

[root@server1 ~]# mv test.php /usr/local/nginx/html/
[root@server1 html]# mv test.php index.php
我们设置nginx默认访问index.php

[root@server1 ~]# cd /usr/local/nginx/html/
[root@server1 html]# cat index.php

connect('172.25.61.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))
                {									##连接server3的mysql
                        $connect = mysql_connect('172.25.61.3','redis','redhat');
                        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 "
"; } ?>

6.测试

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

Redis集群配置(创建集群,添加节点,redis结合mysql,数据同步)_第10张图片
#但是刷新一次后,可以看到后面就从redis读取数据
Redis集群配置(创建集群,添加节点,redis结合mysql,数据同步)_第11张图片

这个时候有个问题,如果此时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(myaql数据变化,redis数据同步)

1.server1上启的gearmand

[root@server1 ~]# systemctl start gearmand ##之前已经安装过

2.server3

Redis集群配置(创建集群,添加节点,redis结合mysql,数据同步)_第12张图片

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的分布式队列
Redis集群配置(创建集群,添加节点,redis结合mysql,数据同步)_第13张图片

[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.61.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;

3.server1

##编写gman的worker端

 [root@server1 redis]# cp worker.php /usr/local/
 [root@server1 redis]# cd /usr/local/

 cat worker.php 
addServer();
$worker->addFunction('syncToRedis', 'syncToRedis');
 
$redis = new Redis();
$redis->connect('127.0.61.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);
}
?>

##后台运行worker

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

4.测试,修改数据库内容

##修改数据库内容

MariaDB [test]> update test set name='redhat' where id=2;

##在redis上查看

127.0.0.1:6379> get 2
"redhat"

##页面查看,数据同步
Redis集群配置(创建集群,添加节点,redis结合mysql,数据同步)_第14张图片
Redis集群配置(创建集群,添加节点,redis结合mysql,数据同步)_第15张图片
Redis集群配置(创建集群,添加节点,redis结合mysql,数据同步)_第16张图片

你可能感兴趣的:(Redis集群配置(创建集群,添加节点,redis结合mysql,数据同步))