一.关于redis的介绍
Redis(全称:Remote Dictionary Server 远程字典服务)是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。
redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set–有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。
Redis 是一个高性能的key-value数据库。
redis的出现,很大程度补偿了memcached这类key/value存储的不足,在部 分场合可以对关系数据库起到很好的补充作用。它提供了Java,C/C++,C#,PHP,JavaScript,Perl,Object-C,Python,Ruby,Erlang等客户端,使用很方便。
就Redis技术而言,它的性能十分优越,可以支持每秒十几万此的读/写操作,其性能远超数据库,并且还支持集群、分布式、主从同步等配置,原则上可以无限扩展,让更多的数据存储在内存中,更让人欣慰的是它还支持一定的事务能力,这保证了高并发的场景下数据的安全和一致性
1.redis与memcache区别
1.redis可以用来做存储(storge)、而memcache是来做缓存(cache)。这个特点主要是因为其有“持久化”功能
2.存储的数据有“结构”,对于memcache来说,存储的数据,只有一种类型—>“字符串”,而redis则可以存储字符串、链表、集合、有序集合、哈序结构
二.redis的安装以及主从复制
https://redis.io/download下载
在server1上:
[root@server1 ~]# tar zxf redis-6.2.4.tar.gz
[root@server1 ~]# cd redis-6.2.4
在源码编译的时候,会有依赖性,根据提示安装
yum install -y gcc
make USER_SYSTEMD=no
make install
cd utils/
vim install_server.sh
因为新版本的redis打开很麻烦,用这个脚本打开很迅速,没有限制,但是需要把脚本修改一下:注释掉判定!!
./install_server.sh
然后一路enter即可成功!
从上图中可以看出redis的配置文件
[root@server1 redis-5.0.8]# vim /etc/redis/6379.conf
我们修改一下监听全局:0.0.0.0
然后重启服务:
/etc/init.d/redis_6379 restart
netstat -antlp | grep 6379
接着尝试使用一下redis:
redis-cli
get name
set name 'westos'
get name
接着在server2上和server1差不多:
tar zxf redis-6.2.4.tar.gz
cd redis-6.2.4
yum install -y gcc
make USER_SYSTEMD=no
make install
cd utils/
vim install_server.sh
./install_server.sh
vim /etc/redis/6379.conf
76 bind 0.0.0.0
480 replicaof 172.25.1.1 6379
配置完成之后,重启服务:
可以看到刚才创建的name也存在server2中!!
/etc/init.d/redis_6379 restart
redis-cli
get name
输入info可以看到master的地址:
可以在server1上修改内容在server2上查看:
我们可以看出在server1中输入的键值在server2中可以get到,所以实现主从关系!!
三.redis的常用指令
config get * //查看配置
select 1 //选择数据库
flushdb //清空当前数据库
flushall //清空所有数据库
move key 1 //移动key
del key //删除
rename oldkey newkey //改名
expire key 10 //设置过期时间
persist key //设置持久化
keys user* //查询
exists key //判断是否存在
edis-cli 是Redis命令行界面,这是一个简单的程序,它允许直接从终端向Redis发送命令并读取服务器发送的回复。
四.redis的高可用
Redis 的 Sentinel 系统用于管理多个 Redis 服务器(instance)该系统执行以下三个任务:
监控(Monitoring): Sentinel 会不断地检查你的主服务器和从服务器是否运作正常。
提醒(Notification): 当被监控的某个 Redis 服务器出现问题时, Sentinel 可以通过 API 向管理员或者其他应用程序发送通知。
自动故障迁移(Automatic failover): 当一个主服务器不能正常工作时, Sentinel 会开始一次自动故障迁移操作, 它会将失效主服务器的其中一个从服务器升级为新的主服务器, 并让失效主服务器的其他从服务器改为复制新的主服务器; 当客户端试图连接失效的主服务器时, 集群也会向客户端返回新主服务器的地址, 使得集群可以使用新主服务器代替失效服务器。
1.配置sentinel
我们需要三台虚拟机,同样的方法进行redis配置,其中server1作为master server2和server3作为slave;(一主二从)
步骤同上server2!!
配置之后,记得重启:
/etc/init.d/redis_6379 restart
[root@server1 redis-6.2.4]# vim sentinel.conf
sentinel monitor mymaster 172.25.1.1 6379 2
sentinel down-after-milliseconds mymaster 10000
[root@server1 redis-6.2.4]# cp sentinel.conf /etc/redis/
[root@server1 redis]# scp sentinel.conf server2:/etc/redis/
[root@server1 redis]# scp sentinel.conf server3:/etc/redis/
2.启动Sentinel
对于 redis-server 程序, 你可以用以下命令来启动一个运行在 Sentinel 模式下的 Redis 服务器:
在三台机子上都执行以下命令来启动sentinel服务:
三台虚拟机都执行:
redis-sentinel /etc/redis/sentinel.conf ##保持这个页面不能推出,可以远程连接到server1上查看
再打开一个窗口链接server1然后挂掉redis!!
redis-cli
shutdown
然后在之前的server1,2,3上查看变化:
这是我们查看info,master已经是server2了,并且当原来的master.server1开启之后也不会再跳回去,server1自动变成slave
从下面的数据也是可以看出来的:
info查看:
3.主观下线和客观下线
主观下线(Subjectively Down, 简称 SDOWN)指的是单个 Sentinel 实例对服务器做出的下线判断。
客观下线(Objectively Down, 简称 ODOWN)指的是多个 Sentinel 实例在对同一个服务器做出 SDOWN 判断, 并且通过 SENTINEL is-master-down-by-addr 命令互相交流之后, 得出的服务器下线判断。 (一个 Sentinel 可以通过向另一个 Sentinel 发送 SENTINEL is-master-down-by-addr 命令来询问对方是否认为给定的服务器已下线。)
如果一个服务器没有在 master-down-after-milliseconds 选项所指定的时间内, 对向它发送 PING 命令的 Sentinel 返回一个有效回复(valid reply), 那么 Sentinel 就会将这个服务器标记为主观下线。
这里指的Ping的回复包括:
返回 +PONG 。
返回 -LOADING 错误。
返回 -MASTERDOWN 错误。
客观下线条件只适用于主服务器,对于任何其他类型的 Redis 实例, Sentinel 在将它们判断为下线前不需要协商, 从服务器或者其他 Sentinel 永远不会达到客观下线条件。
只要一个 Sentinel 发现某个主服务器进入了客观下线状态, 这个 Sentinel 就可能会被其他 Sentinel 推选出, 并对失效的主服务器执行自动故障迁移操作。
五.redis的集群
1.介绍
Redis 集群是一个提供在多个Redis间节点间共享数据的程序集。
Redis集群并不支持处理多个keys的命令,因为需要移动数据,这样在高负载的情况下会发生不可预计的后果!!
Redis 集群的优势:
自动分割数据到不同的节点上。
整个集群的部分节点失败或者不可达的情况下能够继续处理命令。
2.集群的使用
集群并不是由一些普通的Redis实例组成的,集群模式需要通过配置启用。
创建六个以端口号为名字的子目录, 稍后我们在将每个目录中运行一个 Redis 实例: 命令如下:
cd /usr/local/
mkdir redis
cd redis
mkdir 7000
mkdir 700{1..6}
mkdir 7000
在文件夹 7000 至 7006中, 各创建一个 redis.conf 文件,和前面的配置类似,我们选择7000开始
[root@server1 ~]# cd 7000/
[root@server1 7000]# vim redis.conf
port 7000
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
daemonize yes
cluster-enabled 选项用于开实例的集群模式
cluster-conf-file 选项则设定了保存节点配置文件的路径
而它后面指定的文件:
nodes.conf节点配置文件无须人为修改, Redis 集群在启动时创建, 并在有需要时自动进行更新。
六个节点: 三个为主节点, 其余三个则是各个主节点的从节点。
打开实例:
[root@server1 7000]# redis-server redis.conf
ps ax 看一下进程是否创建成功?
紧接着把7001-7005都配置一下:
记得改配置文件,把port都改为相应的数字7001-7005!!
[root@server1 7000]# cp redis.conf ../7001/
[root@server1 7000]# cp redis.conf ../7002/
[root@server1 7000]# cp redis.conf ../7003/
[root@server1 7000]# cp redis.conf ../7004/
[root@server1 7000]# cp redis.conf ../7005/
[root@server1 7000]# cd ../7001
[root@server1 7001]# vim redis.conf
[root@server1 7001]# redis-server redis.conf
[root@server1 7001]# cd ../7002
[root@server1 7002]# vim redis.conf
[root@server1 7002]# redis-server redis.conf
[root@server1 7002]# cd ../7003
[root@server1 7003]# vim redis.conf
[root@server1 7003]# redis-server redis.conf
[root@server1 7003]# cd ../7004
[root@server1 7004]# vim redis.conf
[root@server1 7004]# redis-server redis.conf
[root@server1 7004]# cd ../7005
[root@server1 7005]# vim redis.conf
[root@server1 7005]# redis-server redis.conf
ps ax 查看一下进程:
搭建集群:
我们已经有了7正在运行中的 Redis 实例,我们需要使用这些实例来创建集群, 并为每个节点编写配置文件。
Redis 集群命令行工具 redis-trib
redis-cli --cluster create --cluster-replicas 1 127.0.0.1:7000 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
然后可以看到每一个master都分配了一个slave!成功!
使用集群
测试 Redis 集群比较简单的 redis-cli
redis-cli --cluster info 127.0.0.1:7000
redis-cli --cluster check 127.0.0.1:7000
测试之后,使用redis:
redis-cli -c -p 7000
进去之后,
set name westos
set westos linux
get name
get westos
观察变化,它会自动切换到另一个redis去写或者读:
接下来试试这个:
我们会发现挂掉集群中与之对应的redis之后,就查不到信息了,但是重新开启之后,有可以看到了!
redis-cli -c -p 7000
get name 发现连到7001上去查看
redis-cli -c -p 7001
shutdown 关掉这个redis
exit
redis-cli -c -p 7000
get name 看不到了
ls
cd 7001
redis-server redis.conf
redis-cli -c -p 7000
get name 又可以看到了
六.redis与mysql的结合
用到server1 server2 server4:
只需要server2有redis 其他的虚拟机的redis 关掉它
在server1中:
先搞定php
在我真机上有php的目录直接下载
以下实验所以需要的包链接: 需要的软件包及依赖 提取码: hend
我的文件目录叫做update里面是php的所有包!
scp -r update/ server1:~
直接写在下载目录里面去下载在即可!
[root@server1 ~]# cd /etc/yum.repos.d/
[root@server1 yum.repos.d]# ls
dvd.repo redhat.repo
[root@server1 ~]# mv update /
[root@server1 yum.repos.d]# vim update.repo
[update]
name=update
baseurl=file:///update/
gpgcheck=0
yum clean all
yum repolist #列出文件
yum install php-fpm
cd /etc/php-fpm.d
ls
vim www.conf
只修改用户和组为nginx
useradd nginx
systemctl start php-fpm
###nginx 这块最好重新找个包,解压编译一下,和之前文章里面的步骤一样!!
因为我没有重新编译,开始出问题了!!
[root@server1 nginx]# cd /usr/local/nginx/conf/
[root@server1 conf]# vim nginx.conf
nginx
nginx -s reload
[root@server1 html]# cd /usr/local/nginx/html/
[root@server1 html]# vim index.php
<?php
phpinfo()
?>
访问网页:http://172.25.1.1/index.php
若是不行,关掉防火墙即可!!
root@server1 ~]# yum install -y php-mysql.x86_64 php-redis
[root@server1 ~]# cd /usr/local/nginx/html/
[root@server1 html]# vim test.php
这个test.php是我已经准备好的!
<?php
$redis = new Redis();
$redis->connect('172.25.1.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.1.4','wxh','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 "<br>";
for ($key = 1; $key < 10; $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>";
}
?>
systemctl reload php-fpm
get php-devel-5.4.16-46.el7.x86_64.rpm #下载的包
[root@server1 html]# yum install php-devel-5.4.16-46.el7.x86_64.rpm -y
mirror -r rhel7 #是我从lftp上拷贝下来的目录
[root@server1 ~]# cd rhel7/
[root@server1 rhel7]# yum install php-pecl-redis-2.2.8-1.el7.x86_64.rpm php-fpm-5.4.16-46.el7.x86_64.rpm
php-pecl-igbinary-1.2.1-1.el7.x86_64.rpm -y
[root@server1 rhel7]# systemctl reload php-fpm
[root@server1 rhel7]# php -m | grep mysql
get phpredis-master.zip #下载一个包
unzip phpredis-master.zip
cd phpredis-master/
ls
yum install -y php-devel
phpize
然后ls会看到出现了configure
./configure
make
make install
cd /etc/php.d/
cp mysql.ini redis.ini
vim redis.ini
; Enable redis extension module
extension=redis.so
systemctl reload php-fpm
php -m | grep redis
接着访问网页:http://172.25.1.1/test.php
打开server4虚拟机:
yum install -y mariadb
yum install -y mariadb-server
systemctl start mariadb
mysql
grant all on test.* to wxh@'%' identified by 'westos';
get test.sql #下载的sql数据
mysql < test.sql
对于server2:
redis-cli
info #查看信息是否为master
get 1
get 2
应该可以看到数据库同步过来的数据!!
若是Null的话,把server4上的数据重新导入数据库,再重启数据库,重启redis试试。
不行的话,把网页多刷新几次就出来了!http://172.25.1.1/test.php
info看到的信息如下:
redis查看同步的数据如下:
再访问网页:http://172.25.1.1/test.php
1.mysql与redis不能实时同步
比如:
在server4上修改了数据库内容:
mysql
use test
update test set name='westos' where id =1 ;
select * from test;
但是在server2上的redis和网页上访问都不能同步过来
2.实现mysql与redis数据同步
为了解决上面的同步问题:
配置 gearman 实现数据同步
Gearman 是一个支持分布式的任务分发框架:Gearman Job Server: Gearman 核心程序,需要编译安装并以守护进程形式运行在后台。
Gearman Client:可以理解为任务的请求者。
Gearman Worker:任务的真正执行者,一般需要自己编写具体逻辑并通过守护进程方式
Gearman Worker 接收到 Gearman Client 传递的任务内容后,会按顺序处理。
大致流程:
编写的mysql 触发器,就相当于 Gearman 的客户端。修改表,插入表就相当于直接下发任务。然后通过 lib_mysqludf_json UDF 库函数将关系数据映射为 JSON 格式,然后在通过 gearman-mysql-udf 插件将任务加入到 Gearman 的任务队列中,最后通过redis_worker.php,也就是 Gearman 的 worker 端来完成 redis 数据库的更新。
3.安装 gearman
我们需要的包为:lib_mysqludf_json-master.zip
server4上操作:
在server4上安装
找到包ib_mysqludf_json-master.zip
yum install -y unzip
unzip lib_mysqludf_json-master.zip
cd lib_mysqludf_json-master
yum install -y gcc
yum install -y mysql-devel
gcc $(mysql_config --cflags) -shared -fPIC -o lib_mysqludf_json.so lib_mysqludf_json.c
mysql
show global variables like 'plugin_dir';
cd /root/lib_mysqludf_json-master
cp lib_mysqludf_json.so /usr/lib64/mysql/plugin/
mysql
注册 UDF 函数
mysql> CREATE FUNCTION json_object RETURNS STRING SONAME'lib_mysqludf_json.so';
查看函数
mysql> select * from mysql.func;
安装 gearman-mysql-udf
接下来安装 gearman-mysql-udf:
需要这个包:
gearman-mysql-udf-0.6.tar.gz
tar zxf gearman-mysql-udf-0.6.tar.gz
cd gearman-mysql-udf-0.6
./configure --libdir=/usr/lib64/mysql/plugin/
我这里有需要的依赖性在目录rhel7下面,你们需要自行寻找下载,但是版本一定要对哦!
安装依赖性:
yum install libgearman-* libevent-* -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
重新编译
cd /root/gearman-mysql-udf-0.6
./configure --libdir=/usr/lib64/mysql/plugin
make
make install
cd /usr/lib64/mysql/plugin
ls
查看成功!
注册 UDF 函数
mysql
mysql> CREATE FUNCTION gman_do_background RETURNS STRING SONAME
'libgearman_mysql_udf.so';
mysql> CREATE FUNCTION gman_servers_set RETURNS STRING SONAME
'libgearman_mysql_udf.so';
查看函数
mysql> select * from mysql.func;
指定gearman的服务信息
server4:
yum install gearmand-1.1.12-18.el7.x86_64.rpm -y
systemctl start gearmand.service
yum install -y gearmand-1.1.12-18.el7.x86_64.rpm
netstat -antlp | grep :4730
mysql> SELECT gman_servers_set('172.25.1.2:4730');
编写 mysql 触发器(根据实际情况编写)
# 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 ;
# mysql < test.sql
就是把之前的test.sql文件后面注释部分打开了!没有注释的部分注释起来
mysql < test.sql
查看触发器
mysql> SHOW TRIGGERS FROM test;
编写 gearman 的 worker 端
[root@server4 rhel7]# scp worker.php server1:~
这个worker.php也是提前准备好的
在server1上操作:
修改IP!
# vim worker.php
<?php
$worker = new GearmanWorker();
$worker->addServer();
$worker->addFunction('syncToRedis', 'syncToRedis');
$redis = new Redis();
$redis->connect('172.25.1.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 测试代码的存取一致。
}
?>
在server4把安装包传给server1
或者自行找到这些安装包
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
php-pecl-gearman-1.1.2-1.el7.x86_64.rpm
gearmand-1.1.12-18.el7.x86_64.rpm
[root@server4 rhel7]# scp php-pecl-gearman-1.1.2-1.el7.x86_64.rpm server1:~
[root@server4 rhel7]# scp libgearman-* libevent-devel-2.0.21-4.el7.x86_64.rpm server1:~
scp gearmand-1.1.12-18.el7.x86_64.rpm server1:~
server1 然后开始安装
[root@server1 ~]# yum install php-pecl-gearman-1.1.2-1.el7.x86_64.rpm libgearman-* libevent-devel-2.0.21-4.el7.x86_64.rpm -y
yum install gearmand-1.1.12-18.el7.x86_64.rpm
[root@server1 ~]# php -m | grep gearman
启动服务:
[root@server1 ~]# systemctl start gearmand
netstat -antlp | grep :4730
重启服务:
[root@server1 ~]# systemctl reload php-fpm
后台运行 worker
nohup php worker.php &
看一下后台进程
ps ax | grep php
若是出现打入后台失败的问题,或者查不到进程,那么就work.php没有写对!!
执行php worker.php看它提示哪行有问题,改哪行!!
4.更新 mysql 中的数据进行测试
server4
mysql> update test set name='redhat';
serve2上查看
查看 redis
redis-cli
get 1
刷新测试页面数据同步
访问网页:http://172.25.1.1/test.php
实现同步更新,mysql不管怎么修改 redis和网页都可以同步时时更新!