redis(二)应用
节点 | 作用 |
---|---|
server1(172.25.0.1) | master |
server2(172.25.0.2) | slave |
server3(172.25.0.3) | slave |
一个简单的主从
#1.编译安装redis
tar zxf redis-5.0.3.tar.gz
yum install -y gcc
cd /root/redis-5.0.3
make ##这里不用configure
make install
cd /root/redis-5.0.3/utils
./install_server.sh ##安装redis,安装完会自动启动
netstat -tnlp ##可以看到redis默认是开启127.0.0.1的6379端口,这样只能本地访问,需要配置所有接口都能访问
vim /etc/redis/6379.conf ##修改端口
'70 bind 0.0.0.0'
[root@server1 redis]# /etc/init.d/redis_6379 restart
##重启服务,也可以用systemctl restart redis_6379,但是重启好像不生效,可以开启服务
#把redis拷贝到server2上
[root@server1 ~]# scp -r redis-5.0.3 root@172.25.0.2:
#在server2上安装
[root@server2 redis-5.0.3]# make install
[root@server2 redis-5.0.3]# cd utils/
[root@server2 utils]# ./install_server.sh #全部选默认
#修改默认端口
[root@server2 utils]# vim /etc/redis/6379.conf
bind 0.0.0.0
[root@server2 ~]# /etc/init.d/redis_6379 restart
#配置主从:在server2上配置从
[root@server2 ~]# vim /etc/redis/6379.conf
slaveof 172.25.0.1 6379 ##文件最后加
/etc/init.d/redis_6379 restart
#测试
在server1上:
[root@server1 ~]# redis-cli
127.0.0.1:6379> set name wsp
OK
127.0.0.1:6379> get name
"wsp"
在server2上:
[root@server2 ~]# redis-cli
127.0.0.1:6379> get name
"wsp"
在server1上存入的值,在server2上可以看到,但是在server2上不能写入
[root@server2 ~]# vim /etc/redis/6379.conf
[root@server2 ~]# redis-cli
127.0.0.1:6379> get name
"wsp"
127.0.0.1:6379> set name westos
(error) READONLY You can't write against a read only replica.
#redis的数据保存在/var/lib/redis/6379/dump.rdb
如果有问题,redis起不来,可以删除这文件再试
####可以参考redis中文官网http://www.redis.cn
http://www.redis.cn/documentation.html
#vim /etc/redis/6379.conf
219 save 900 1 ##这几行表示,有一个键值发生变化时,会过900s更新,下面依次类推,因为不停更新会耗费资源
220 save 300 10
221 save 60 10000
分别表示900秒(15分钟)内有1个更改,300秒(5分钟)内有10个更改以及60秒内有10000个更改
先看60秒,如果有10000个更改,那就save了吧。
如果没有,那么等到300秒,看是否有10个更改,有就save了吧。
同理900秒。。。
高可用
[root@server1 redis-5.0.3]# cp sentinel.conf /etc/redis/ ##复制配置文件,sentinel哨兵
[root@server1 ~]# scp -r redis-5.0.3 root@172.25.0.3:
[root@server3 redis-5.0.3]# make install
[root@server3 utils]# ./install_server.sh
[root@server3 redis]# vim 6379.conf
70 bind 0.0.0.0
89 protected-mode no
1379 slaveof 172.25.0.1 6379 ##写在最后一行
[root@server3 redis]# /etc/init.d/redis_6379 restart
测试
[root@server3 redis]# redis-cli
127.0.0.1:6379> get name
"wsp"
##配置哨兵
在server1上(master)编辑配置文件
[root@server1 ~]# vim /etc/redis/sentinel.conf
17 protected-mode no ##关闭保护模式
121 sentinel monitor mymaster 172.25.0.1 6379 2 ##配置master信息,后面的2表示投票机制,至少有2个节点认为master挂了,才会切换
146 sentinel down-after-milliseconds mymaster 10000 ##改为10s,表示master挂后10s会切换
'####注意注意:一定要先scp到slave节点上再启动'
[root@server1 ~]# redis-server /etc/redis/sentinel.conf --sentinel ##开启哨兵
#在server2和server3上同样要开启
[root@server1 redis]# scp sentinel.conf server2:/etc/redis/
[root@server1 redis]# scp sentinel.conf server3:/etc/redis/
[root@server2 ~]# redis-server /etc/redis/sentinel.conf --sentinel
[root@server3 ~]# redis-server /etc/redis/sentinel.conf --sentinel
#在server1上查看信息
[root@server1 ~]# redis-cli
127.0.0.1:6379> info
# Replication
role:master
connected_slaves:2
slave0:ip=172.25.0.2,port=6379,state=online,offset=95268,lag=0
slave1:ip=172.25.0.3,port=6379,state=online,offset=95133,lag=0
看到上面信息说明配置成功
#在server1上可以看到sentinel信息
[root@server1 ~]# redis-cli -p 26379
127.0.0.1:26379> info
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=172.25.0.1:6379,slaves=2,sentinels=3
#挂掉server1的redis
[root@server1 ~]# redis-cli
127.0.0.1:6379> SHUTDOWN
not connected>
可以看到server1的6379端口挂掉
sentinel哨兵也能看到信息
1036:X 31 Mar 2019 17:49:21.927 # +odown master mymaster 172.25.0.1 6379 #quorum 3/2
1036:X 31 Mar 2019 17:49:22.546 # +switch-master mymaster 172.25.0.1 6379 172.25.0.2 6379
现在server2是master
#启动之后会看到两个WARNING
在server1上修改此参数的值
[root@server1 ~]# sysctl -w vm.overcommit_memory=1
#表示内核允许分配所有的物理内存,而不管当前的内存状态如何,
0表示内核将检查是否有足够的可用内存供应用进程使用;
如果有足够的可用内存,内存申请允许;否则,内存申请失败,
并把错误返回给应用进程
redis集群
http://www.redis.cn/topics/cluster-tutorial.html ##配置参考官网
#先关闭之前的redis
[root@server1 ~]# /etc/init.d/redis_6379 stop
#新建redis目录
[root@server1 ~]# mkdir /usr/local/rediscluster
[root@server1 rediscluster]# mkdir 700{1..6}
#编辑配置文件
[root@server1 7001]# cat redis.conf
port 7000
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 *:7000 [cluster]
#测试
[root@server1 7001]# redis-cli -p 7001
127.0.0.1:7001> info
# Cluster
cluster_enabled:1 ##集群激活
#同理配置7002~7006,并启动
ps ax
1348 ? Ssl 0:00 redis-server *:7001 [cluster]
1382 ? Ssl 0:00 redis-server *:7002 [cluster]
1388 ? Ssl 0:00 redis-server *:7003 [cluster]
1394 ? Ssl 0:00 redis-server *:7004 [cluster]
1400 ? Ssl 0:00 redis-server *:7005 [cluster]
1405 ? Ssl 0:00 redis-server *:7006 [cluster]
#拷贝ruby脚本
[root@server1 src]# pwd
/root/redis-5.0.3/src
[root@server1 src]# cp redis-trib.rb /usr/local/bin/
#执行命令
[root@server1 src]# redis-trib.rb
/usr/bin/env: ruby: No such file or directory ##报错了,因为没有ruby
[root@server1 src]# yum install -y ruby
[root@server1 src]# redis-trib.rb
WARNING: redis-trib.rb is not longer available!
You should use redis-cli instead. ##redis-trib.rb不可用了,用redis-cli
[root@server1 ~]# redis-cli --cluster help
#创建集群
[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
#--cluster-replicas 1表示为每一个master创建1个slave
然后输入yes
[OK] All 16384 slots covered. #看到这个表示16384个槽都分配好了
#查看集群信息
[root@server1 ~]# redis-cli --cluster info 127.0.0.1:7001 ##输入其他端口也可以,但是必须输一个端口
#测试存储信息
[root@server1 ~]# redis-cli -c -p 7001
127.0.0.1:7001> set name wsp
-> Redirected to slot [5798] located at 127.0.0.1:7002
OK
127.0.0.1:7002> get name
"wsp"
#数据保存在5798个哈希槽中,在7002上
[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
"wsp" #在任意节点都可以获取到信息,但是都会跳转到7002
##挂掉7002,key还会保存在7004上
[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
"wsp"
127.0.0.1:7002> SHUTDOWN
not connected>
################################################################
[root@server1 src]# redis-cli -c -p 7001
127.0.0.1:7001> get name
-> Redirected to slot [5798] located at 127.0.0.1:7002
Could not connect to Redis at 127.0.0.1:7002: Connection refused
Could not connect to Redis at 127.0.0.1:7002: Connection refused
not connected> exit
[root@server1 src]# redis-cli --cluster info 127.0.0.1:7001
Could not connect to Redis at 127.0.0.1:7002: Connection refused
127.0.0.1:7001 (70f07453...) -> 0 keys | 5461 slots | 1 slaves.
127.0.0.1:7006 (3d5a0313...) -> 1 keys | 5462 slots | 0 slaves.
127.0.0.1:7003 (ae486b18...) -> 0 keys | 5461 slots | 1 slaves.
[OK] 1 keys in 3 masters.
0.00 keys per slot on average.
[root@server1 src]# redis-cli -c -p 7001
127.0.0.1:7001> get name
-> Redirected to slot [5798] located at 127.0.0.1:7006
################################################################
[root@server1 ~]# redis-cli --cluster info 127.0.0.1:7001
Could not connect to Redis at 127.0.0.1:7002: Connection refused
127.0.0.1:7001 (4f5065af...) -> 0 keys | 5461 slots | 1 slaves.
127.0.0.1:7004 (fc590a43...) -> 1 keys | 5462 slots | 0 slaves.
127.0.0.1:7003 (0b2f0c60...) -> 0 keys | 5461 slots | 1 slaves.
[OK] 1 keys in 3 masters.
0.00 keys per slot on average.
##再挂掉7004,key丢失
[root@server1 ~]# redis-cli -c -p 127.0.0.1:7004
Could not connect to Redis at 127.0.0.1:127: Connection refused
not connected>
[root@server1 ~]# redis-cli -c -p 7004
127.0.0.1:7004> SHUTDOWN
not connected>
#########################################################
[root@server1 ~]# redis-cli --cluster info 127.0.0.1:7001
Could not connect to Redis at 127.0.0.1:7004: Connection refused
Could not connect to Redis at 127.0.0.1:7002: Connection refused
127.0.0.1:7001 (4f5065af...) -> 0 keys | 5461 slots | 1 slaves.
127.0.0.1:7003 (0b2f0c60...) -> 0 keys | 5461 slots | 1 slaves.
[OK] 0 keys in 2 masters.
0.00 keys per slot on average.
#########################################################
[root@server1 ~]# redis-cli -c -p 7001
127.0.0.1:7001> get name
(error) CLUSTERDOWN The cluster is down
[root@server1 ~]# cd /usr/local/rediscluster/
[root@server1 7002]# cat appendonly.aof
*2
$6
SELECT
$1
0
*3
$3
set
$4
name
$3
wsp
#可以看到刚才添加的信息
#再启动7002和7004 ###注意4和2一定是匹配的
[root@server1 7002]# redis-server redis.conf
[root@server1 7004]# redis-server redis.conf
[root@server1 ~]# redis-cli -c -p 7001
127.0.0.1:7001> get name
-> Redirected to slot [5798] located at 127.0.0.1:7006
"wsp"
#正常查询
####redis添加新节点
[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 ##添加节点
[root@server1 7008]# redis-cli -c -p 7007
127.0.0.1:7007> cluster nodes ##查看节点信息
b9ee016d45dde6a0067dd3e19139f1044a621d77 127.0.0.1:7007@17007 myself,master - 0 1554949235000 0 connected
#发现7007没有哈希槽
#尽管新节点没有包含任何哈希槽, 但它仍然是一个主节点,
#所以在集群需要将某个从节点升级为新的主节点时,
#这个新节点不会被选中,所以要添加一个slave
[root@server2 ~]# redis-cli --cluster help ##查看帮助
add-node new_host:new_port existing_host:existing_port
--cluster-slave
--cluster-master-id <arg>
[root@server1 ~]# redis-cli --cluster add-node 127.0.0.1:7008 127.0.0.1:7007 --cluster-slave --cluster-master-id b9ee016d45dde6a0067dd3e19139f1044a621d77
[root@server1 ~]# redis-cli -c -p 7001
127.0.0.1:7001> cluster nodes ##查看
[root@server1 ~]# redis-cli --cluster info 127.0.0.1:7001 ##查看集群信息
##为新节点分配哈希槽
[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 这个意思是从所以的节点里选出500个槽位
#从所有节点获取哈希槽
redis-cli --cluster check 127.0.0.1:7001 ##检查可以看到已经分配哈希槽
####但是上面分配不均等,可能导致数据不同步
[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
127.0.0.1:7008> get name
-> Redirected to slot [5798] located at 127.0.0.1:7007
"wsp"
####集群完成####
redis+mysql
数据访问流程:client -> app -> redis -> mysql -> redis -> client
客户端用app访问,先在redis里读数据,因为快,redis没有才去mysql读,读完保存在redis里,然后返回客户端,下次再读就快
killall redis-server
#没有killall命令 yum whatprovides /usr/bin/killall
#[root@server1 ~]# yum install -y psmisc-22.20-11.el7.x86_64
##首先在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-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
Gearmand 是一个用来把工作委派给其它机器、分布式的调用更适合做某项工作的机器、并发的做某项工作在多个调用间做负载均衡、或用来调用其它语言的函数的系统。
简单来讲,就是客户端程序把请求提交给 gearmand,gearmand 会把请求转发给合适的 worker 来处理这个请求,最后还通过 gearmand 返回结果。
运行流程:
Client --> Job --> Worker
1、Client 请求发起者,客户端程序可以是任何一种语言,C 、PHP 、Perl 、Python 等。
2、Job 请求调度者,负载协调把 Client 发出的请求转发给合适的 Worker。
3、Worker 请求处理者,处理 Job 分发来的请求,可以是任何一种语言
#在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 redis]# tar zxf gearman-mysql-udf-0.6.tar.gz
[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