Redis哨兵模式实现主从切换

redis简介:

Redis是一个开源的内存中的数据结构存储系统,
它可以用作:数据库、缓存和消息中间件

为什么要使用redis?

性能和并发
#性能? 我们在碰到需要执行耗时特别久,且结果不频繁变动的 SQL,就特别适合将运行结果放入缓存。这样,后面的请求就去缓存中读取,使得请求能够迅速响应
#特别是在秒杀系统,在同一时间,几乎所有人都在点,都在下单。。。执行的是同一操作———向数据库查数据

redis的速度:单机读可达10000次/s 写可达5000/s
#mysql 经过了这么多年优化 才1000次/S,500次/S

redis为何这么厉害?

redis 是操作内存,操作速度自然比mysql的磁盘操作要快太多了

redis单线程+多路I/O复用模型
单线程的模式解决了数据存储的顽疾:数据并发安全,
任何运行多线程同时访问数据库都会存在这个问题,
所以才有了mysql的mvcc和锁, Memcached 的cas 乐观锁,
来保证数据不会出现并发导致的数据问题,
但是redis 使用单线程就不存在这个问题:1,单线程足够简单,
无论在redis的实现还是作为调用方,都不需要为数据并发提心吊胆,不需要加锁。 2.不会出现不必要的线程调度,
你知道多线程,频繁切换上下文,也会带来很多性能消耗

什么是切换上下文?

#线程每次执行需要把数据从主内存读到工作内存,然而当线程被调度到阻塞的时候,这些工作内存的数据需要被快照到线程上下文中,其实就是一个记录各个线程状态的存储结构,等到线程被唤醒的时候,再从上下文中读取,称之为上下文切换;减少上下文切换操作,也是使用单线程的奥妙

再说 多路 I/O 复用模型,这个也是java 的NIO体系使用的IO模型,也是linux诸多IO模型中的一种,
说白了就是当一个请求来访问redis后,redis去组织数据要返回给请求,
这个时间段,redis的请求入口不是阻塞的,其他请求可以继续向redis发送请求,等到redis io流完成后,再向调用者返回数据,这样一来,单线程也不怕会影响速度了
# 这里“多路”指的是多个网络连接
# “复用”指的是复用同一个线程

##我们使用单线程的方式是无法发挥多核CPU 性能,不过我们可以通过在单机开多个Redis 实例来完善

什么是缓存击穿?

缓存一般作为RDS的前置系统和服务器直连,减轻rds的负担,常理而言,如果服务器查询缓存而不得的话,需要从rds中获取然后更新到缓存中,但是如果在“从rds中获取然后更新到缓存中”,这个阶段,缓存尚未更新成功,大量请求进来的话,rds势必压力暴增,甚至雪崩,或者歹人恶意攻击,一直查询rds和缓存中未存在key,也会导致缓存机制失效,rds压力暴增,称之为缓存击穿

#那怎么办? 缓存永不失效,定时同步rds redis,不允许应用直接请求查询rds,所有的查询以缓存中为准

##并发

在大并发的情况下,所有的请求直接访问数据库,数据库会出现连接异常。
这个时候,就需要使用 Redis 做一个缓冲操作,
让请求先访问到 Redis,而不是直接访问数据库

##Redis 的过期策略和内存淘汰机制
Redis 采用的是定期删除+惰性删除策略

##采用定期删除+惰性删除就没其他问题了么

不是的,如果定期删除没删除掉 Key。并且你也没及时去请求 Key,也就是说惰性删除也没生效。这样,Redis 的内存会越来越高

##如果一个键过期了,那么它什么时候会被删除呢? 定时删除:在设置键的过期时间的同时,创建一个定时器( timer ). 让定时器在键的过期时间来临时,立即执行对键的删除操作。
惰性删除:放任键过期不管,但是每次从键空间中获取键时,都检查取得的键是否过期,如果过期的话,就删除该键;如果没有过期,就返回该键。
定期删除: 每隔一段时间,程序就对数据库进行一次检查,删除里面的过期键。至于要删除多少过期键,以及要检查多少个数据库, 则由算法决定。
在这三种策略中,第一种和第三种为主动删除策略, 而第二种则为被动删除策略

定时删除

定时删除策略对内存是最友好的:通过使用定时器,定时删除策略可以保证过期键会尽可能快地被删除,并释放过期键所占用的内存。另一方面,定时删除策略的缺点是,它对CPU
时间是最不友好的:在过期键比较多的情况下,删除过期键这一行为可能会占用相当一部分CPU 时间,在内存不紧张但是CPU
时间非常紧张的情况下.将CPU 时间用在删除和当前任务无关的过期键上,无疑会对服务器的响应时间和吞吐量造成影响。
例如,如果正有大量的命令请求在等待服务器处理,并且服务器当前不缺少内存,那么服务器应该优先将CPU
时间用在处理客户端的命令请求上面,而不是用在删除过期键上面。除此之外,创建一个定时器需要用到Redis
服务器中的时间事件,而当前时间事件的实现方式一一无序链表,查找一个事件的时间复杂度为O(N)一并不能高效地处理大量时间事件。
因此,要让服务器创建大量的定时器,从而实现定时删除策略,在现阶段来说并不现实。

惰性删除

惰性删除策略对CPU 时间来说是最友好的:程序只会在取出键时才对键进行过期检查,这可以保证删除过期键的操作只会在非做不可的情况下进行,
并且删除的目标仅限于当前处理的键,这个策略不会在删除其他无关的过期键上花费任何CPU时间。 惰性删除策略的缺点是,它对内存是最不友好的:
如果一个键已经过期,而这个键又仍然保留在数据库中,那么只要这个过期键不被删除,它所占用的内存就不会释放。在使用惰性删除策略时,如果数据库中有非常多的过期键,而这些过期键又恰好没有被访问到的话,那么它们也许永远也不会被删除(除非用户手动执行FLUSHDB),我们甚至可以将这种情况看作是一种内存泄漏一一无用的垃圾数据占用了大量的内存,而服务器却不会自己去释放它们,这对于运行状态非常依赖于内存的Redis服务器来说,肯定不是一个好消息。
举个例子,对于一些和时间有关的数据,比如日志(log)
,在某个时间点之后,对它们的访问就会大大减少,甚至不再访问,如果这类过期数据大量地积压在数据库中,用户以为服务器已经自动将它们删除了,但实际上这些键仍然存在,
而且键所占用的内存也没有释放,那么造成的后果肯定是非常严重的。

定期删除

从上面对定时删除和惰性删除的讨论来看,这两种删除方式在单一使用时都有明显的缺陷: 定时删除占用太多CPU
时间,影响服务器的响应时间和吞吐量。惰性删除浪费太多内存,有内存泄漏的危险。 定期删除策略是前两种策略的一种整合和折中:

定期删除策略每隔一段时间执行一次删除过期键操作,并通过限制删除操作执行的时长和频率来减少删除操作对CPU
时间的影响。除此之外,通过定期删除过期键,定期删除策略有效地减少了因为过期键而带来的内存浪费。定期删除策略的难点是确定删除操作执行的时长和频率:
如果删除操作执行得太频繁,或者执行的时间太长,定期删除策略就会退化成定时删除策略,以至于将C P U 时间过多地消耗在删除过期键上面。
如果删除操作执行得太少,或者执行的时间太短,定期删除策略又会和惰性删除策略一样,出现浪费内存的情况。
因此,如果采用定期删除策略的话,服务器必须根据情况,合理地设置删除操作的执行时长和执行频率。

# 注意:如果对数据有强一致性要求,不能放缓存

Redis的事务功能

Redis会将一个事务中的所有命令序列化,然后按顺序执行。Redis不可能在一个Redis事务的执行过程中插入执行另一个客户端发出的请求。这样便能保证Redis将这些命令作为一个单独的隔离操作执行。

在一个Redis事务中,Redis要么执行其中的所有命令,要么什么都不执行。因此,Redis事务能够保证原子性。EXEC命令会触发执行事务中的所有命令。因此,当某个客户端正在执行一次事务时,如果它在调用MULTI命令之前就从Redis服务端断开连接,那么就不会执行事务中的任何操作;相反,如果它在调用EXEC命令之后才从Redis服务端断开连接,那么就会执行事务中的所有操作

为什么Redis不支持回滚

如果你具备关系型数据库的知识背景,你就会发现一个事实:在事务运行期间,虽然Redis命令可能会执行失败,但是Redis仍然会执行事务中余下的其他命令,而不会执行回滚操作,你可能会觉得这种行为很奇怪然而,这种行为也有其合理之处:

只有当被调用的Redis命令有语法错误时,这条命令才会执行失败(在将这个命令放入事务队列期间,Redis能够发现此类问题),或者对某个键执行不符合其数据类型的操作:实际上,这就意味着只有程序错误才会导致Redis命令执行失败,这种错误很有可能在程序开发期间发现,一般很少在生产环境发现。
Redis已经在系统内部进行功能简化,这样可以确保更快的运行速度,因为Redis不需要事务回滚的能力。

对于Redis事务的这种行为,有一个普遍的反对观点,那就是程序有可能会有缺陷(bug)。但是,你应当注意到:事务回滚并不能解决任何程序错误。例如,如果某个查询会将一个键的值递增2,而不是1,或者递增错误的键,那么事务回滚机制是没有办法解决这些程序问题的。请注意,没有人能解决程序员自己的错误,这种错误可能会导致Redis命令执行失败。正因为这些程序错误不大可能会进入生产环境,所以我们在开发Redis时选用更加简单和快速的方法,没有实现错误回滚的功能

redis的持久化

Redis也提供了持久化的选项,这些选项可以让用户将自己的数据保存到磁盘上面进行存储。根据实际情况,可以每隔一定时间将数据集导出到磁盘(快照),或者追加到命令日志中(AOF只追加文件),他会在执行写命令时,将被执行的写命令复制到硬盘里面。您也可以关闭持久化功能,将Redis作为一个高效的网络的缓存数据功能使用
###Redis不使用表,他的数据库不会预定义或者强制去要求用户对Redis存储的不同数据进行关联

Redis的应用

存储 缓存 用的数据;
需要高速读/写的场合使用它快速读/写;

可以参考redis中文官网
http://www.redis.cn/documentation.html

【server1】

1.编译安装redis
tar zxf redis-5.0.3.tar.gz
yum install -y gcc
Redis哨兵模式实现主从切换_第1张图片> cd /root/redis-5.0.3>
make ##这里不用configure
在这里插入图片描述
make install
Redis哨兵模式实现主从切换_第2张图片> cd /root/redis/redis-5.0.3/utils
./install_server.sh ##安装redis,安装完会自动启动
Redis哨兵模式实现主从切换_第3张图片
netstat -tnlp ##可以看到redis默认是开启127.0.0.1的6379端口,这样只能本地访问,需要配置所有接口都能访问
Redis哨兵模式实现主从切换_第4张图片
vim /etc/redis/6379.conf ##修改端口
70 bind 0.0.0.0
Redis哨兵模式实现主从切换_第5张图片
[root@server1 redis]# /etc/init.d/redis_6379 restart
##重启服务,也可以用systemctl restart redis_6379,但是重启好像不生效,可以开启服务
Redis哨兵模式实现主从切换_第6张图片
#把redis拷贝到【server2】和【server3】上
[root@server1 ~]# scp -r redis-5.0.3 [email protected]:/root
Redis哨兵模式实现主从切换_第7张图片

【server2】

#在server2上安装
[root@server2 redis-5.0.3]# make install
Redis哨兵模式实现主从切换_第8张图片
[root@server2 redis-5.0.3]# cd utils/
[root@server2 utils]# ./install_server.sh
#全部选默认,回车即可
Redis哨兵模式实现主从切换_第9张图片> #修改默认端口
[root@server2 utils]# vim /etc/redis/6379.conf
70:bind 0.0.0.0
#配置主从:在server2上配置从 slaveof 172.25.78.1 6379
##文件最后加,使其同步172.25.78.1的数据
Redis哨兵模式实现主从切换_第10张图片
在这里插入图片描述
/etc/init.d/redis_6379 restart
Redis哨兵模式实现主从切换_第11张图片
测试

在server1上

[root@server1 ~]# redis-cli
127.0.0.1:6379> set name dd
127.0.0.1:6379> get name
Redis哨兵模式实现主从切换_第12张图片
在server2上查看是否同步

[root@server2 ~]# redis-cli
127.0.0.1:6379> get name
Redis哨兵模式实现主从切换_第13张图片
###在server1上存入的值,在server2上可以看到,但是在server2上不能写入,写入会报错
Redis哨兵模式实现主从切换_第14张图片
#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秒。。。
Redis哨兵模式实现主从切换_第15张图片
redis的数据保存在/var/lib/redis/6379/dump.rdb 如果有问题,redis起不来,可以删除这文件再试

配置redis高可用

再开一台server3,配置redis

##在server1复制过来
【server1】

[root@server1 ~]# scp -r redis-5.0.3 [email protected]:/root
在这里插入图片描述> 【server3】

[root@server3 redis-5.0.3]# make install
Redis哨兵模式实现主从切换_第16张图片
[root@server3 utils]# ./install_server.sh
Redis哨兵模式实现主从切换_第17张图片
[root@server3 redis]# vim /etc/redis/6379.conf
70 bind 0.0.0.0
slaveof 172.25.78.1 6379 ##写在最后一行
Redis哨兵模式实现主从切换_第18张图片
Redis哨兵模式实现主从切换_第19张图片
[root@server3 redis]# /etc/init.d/redis_6379 restart
Redis哨兵模式实现主从切换_第20张图片
测试 [root@server3 redis]# redis-cli
127.0.0.1:6379> get name
在这里插入图片描述

配置哨兵

【server1】上(master)编辑配置文件

注意注意!!!!!!!!!!:修改完文件后,不要重启,一定要先scp到slave节点上再启动
[root@server1 redis-5.0.3]# cp sentinel.conf /etc/redis/ ##复制配置文件,sentinel哨兵
[root@server1 redis-5.0.3]# vim /e tc/redis/sentinel.conf
17 protected-mode no ##关闭保护模式
84 sentinel monitor mymaster 172.25.78.1 6379 2 ##配置master信息,后面的2表示投票机制,至少有2个节点认为master挂了,才会切换
113 sentinel down-after-milliseconds mymaster 10000
##改为10s,表示master挂后10s会切换
Redis哨兵模式实现主从切换_第21张图片
Redis哨兵模式实现主从切换_第22张图片Redis哨兵模式实现主从切换_第23张图片> [root@server1 redis]# scp sentinel.conf server2:/etc/redis/
[root@server1 redis]# scp sentinel.conf server3:/etc/redis/
##在【server2】【server3】查看文件有没有scp成功

[root@server3 utils]# cd /etc/redis — > ls
在这里插入图片描述
Redis哨兵模式实现主从切换_第24张图片
#在server2和server3上同样要开启
[root@server1 ~]# redis-server /etc/redis/sentinel.conf --sentinel ##开启哨兵
[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
Redis哨兵模式实现主从切换_第25张图片
Replication role:master connected_slaves:2 slave0:ip=172.25.78.2,port=6379,state=online,offset=95268,lag=0
slave1:ip=172.25.78.3,port=6379,state=online,offset=95133,lag=0
Redis哨兵模式实现主从切换_第26张图片
看到上面信息说明配置成功

#在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.78.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

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

Redis哨兵模式实现主从切换_第27张图片

你可能感兴趣的:(Redis哨兵模式实现主从切换)