主从复制
主从复制,是指将一台 Redis 服务器的数据,复制到其他的 Redis 服务器。 前者称为主节点(master),后者称为从节点(slave),数据的复制是单向的,只能 由主节点到从节点。
使用一个 Redis 实例作为主机,其余的作为备份机。主机和备份机的数据完 全一致,主机支持数据的写入和读取等各项操作,而从机则只支持与主机数据的 同步和读取。也就是说,客户端可以将数据写入到主机,由主机自动将数据的写 入操作同步到从机。主从模式很好的解决了数据备份问题,并且由于主从服务数 据几乎是一致的,因而可以将写入数据的命令发送给主机执行,而读取数据的命 令发送给不同的从机执行,从而达到读写分离的目的。
主从复制的作用主要包括:
1.**数据冗余:**主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。
2.**故障恢复:**当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢 复;实际上是一种服务的冗余。
3.负载均衡:在主从复制的基础上,配合读写分离,可以由主节点提供写服务, 由从节点提供读服务(即写 Redis 数据时应用连接主节点,读 Redis 数据时应 用连接从节点),分担服务器负载;尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高 Redis 服务器的并发量。
4.高可用(集群)基石:除了上述作用以外,主从复制还是哨兵和集群能够实施 基础,因此说主从复制是 Redis 高可用的基础。
主从复制配置
主从复制时只需要配置从库即可,其默认为主库模式.
打开 redis 客户端登录,使用命令 info replication 查看.
主从复制可以搭建真集群,也可以搭建伪集群.真集群就是有多台主机,每台主机 安装一个 redis.伪集群就是在一台主机上复制多份配置,修改其端口,运行多个 redis 实例.配置方式两者相同
主从配置实例
复制多份配置文件,一主二从 (这是条件所限用一台机子测试,配置了多个redis,一机可以启动多个redis分别当主机和从机使用)
主机配置
cd /usr/local/redis/bin
bind 0.0.0.0
#任何 ip 都可以访问
daemonize yes 后台运行
pidfile /var/run/redis_6379.pid #进程号文件
logfile “6379.log”
#日志文件
注意文件名修改只是为了区分
dbfilename dump6379.rdb #数据文件
requirepass root #主机密码
从机配置
cd /usr/local/redis/bin
#bind 注释
daemonize yes 后台运行
pidfile /var/run/redis_6380.pid #进程号文件
logfile “6380.log”
#日志文件
注意文件名修改只是为了区分
dbfilename dump6380.rdb #数据文件
replicaof 主机 ip 主机端口
masterauth 主机密码
#requirepass(只有主机才需要密码) 注释
进入客户端,使用 info replication 命令查看模式
如果是条件所限只有一台机子,又想测试redis中的主从复制的话那么需要复制多个redis.conf文件,在从机中将端口号改了不能和主机重复,在进入客户端时应该redis-cli -p 此从机的端口号
先依次启动主机和从机
测试图例
哨兵机制
概述
哨兵模式是一种特殊的模式,首先 Redis 提供了哨兵的命令,哨兵是一个独立的 进程,作为进程,它会独立运行。其原理是哨兵通过发送命令,等待 Redis 服务 器响应,从而监控运行的多个 Redis 实例。
单哨兵
哨兵集群
哨兵配置
从安装包中复制 sentinel.conf 文件到 bin 目录中
缓存穿透,缓存击穿,缓存雪崩
缓存处理流程
前台请求,后台先从缓存中取数据,取到直接返回结果,取不到时从数据库中取,数据库取到更新缓存,并返回结果,数据库也没取到,那直接返回空结果
缓存穿透
key 对应的数据在数据库中并不存在,每次针对此 key 的请求从缓存获取不 到,请求都会到数据库,从而可能压垮数据库。比如用一个不存在的用户 id 获 取用户信息,不论缓存还是数据库都没有,若黑客利用此漏洞进行攻击可能压垮 数据库。
数据库没有,缓存没有
解决办法:
-
使用布隆过滤器(BloomFilter)或者压缩 filter 提前拦截.
2.将这个空对象设置到缓存里边去。下次再请求的时候,就可以从缓存里边获取 了。这种情况我们一般会将空对象设置一个较短的过期时间.
3.对参数进行校验,不合法参数进行拦截
缓存击穿
某个 key 对应的数据库中存在,但在 redis 中的某个时间节点过期了,此时若有大量并发请求过来,这些请求发现缓存过期,都会从后端 DB 加载数据并回设到缓存,这个时候大并发的请求可能会瞬间把后端 DB 压垮。
解决办法:
1.热点数据设置永不过期
2.加上互斥锁:上面的现象是多个线程同时去查询数据库的这条数据,那么我们可以在第一个查询数据的请求上使用一个互斥锁来锁住它其他的线程走到这一步拿不到锁就等着,等第一个线程查询到了数据,然后将数据放到 redis 缓存起来。后面的线程进来发现已经有缓存了,就直接走缓存.
缓存雪崩
缓存雪崩是指,在高并发情况下,大量的缓存失效,或者缓存层出现故障。于是所有的请求都会达到数据库,数据库的调用量会暴增,造成数据库也会挂掉的情况。
解决方法:
1.随机设置 key 失效时间,避免大量 key 集体失效。
setRedis(Key,value,time + Math.random() * 10000);
2.若是集群部署,可将热点数据均匀分布在不同的 Redis 库中也能够避免 key 全部失效问题
3.不设置过期时间
4.跑定时任务,在缓存失效前刷进新的缓存
总结
雪崩是大面积的key缓存失效;穿透是redis里不存在这个缓存key;
击穿是redis 某一个热点 key 突然失效,最终的受害者都是数据库。
对于“Redis 宕机,请求全部走数据库”这种情况,我们可以有以下的思路:
**事发前:**实现 Redis 的高可用(主从架构+Sentinel(哨兵),尽量避免 Redis 挂掉这种情况发生。
**事发中:**万一 Redis 真的挂了,我们可以设置本地缓存(ehcache)+限流,尽量 避免我们的数据库被干掉(起码能保证我们的服务还是能正常工作的)
**事发后:**redis 持久化,重启后自动从磁盘上加载数据,快速恢复缓存数据。
解决缓存穿透之布隆过滤器
布隆过滤器(Bloom Filter)是1970年由布隆提出的。它实际上是一个很长的二进制向量和一系列映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都比一般的算法要好的多,缺点是有一定的误识别率和删除困难。
如果想要判断一个元素是不是在一个集合里,一般想到的是将所有元素保存起来,然后通过比较确定。链表,树等等数据结构都是这种思路. 但是随着集合中元素的增加,我们需要的存储空间越来越大,检索速度也越来越慢。不过世界上还有一种叫作散列表(又叫哈希表,Hash table)的数据结构。它可以通过一个Hash函数将一个元素映射成一个位阵列中的一个点。这样一来,我们只要看看这个点是不是1就可以知道集合中有没有它了。这就是布隆过滤器的基本思想。
算法:
- 首先需要k个hash函数,每个函数可以把key散列成为1个整数
- 初始化时,需要一个长度为n比特的数组,每个比特位初始化为0
- 某个key加入集合时,用k个hash函数计算出k个散列值,并把数组中对应的比特位置为1
- 判断某个key是否在集合时,用k个hash函数计算出k个散列值,并查询数组中对应的比特位,如果所有的比特位都是1,认为在集合中。
布隆过滤器数据结构
BloomFilter 是由一个固定大小的二进制向量或者位图(bitmap)和一系列映射函数组成的。
在初始状态时,对于长度为 m 的位数组,它的所有位都被置为0,如下图所示:
当有变量被加入集合时,通过 K 个哈希函数将这个变量映射成位图中的 K 个点,把它们置为 1(假定有两个变量都通过 3 个映射函数)。
查询某个变量的时候我们只要看看这些点是不是都是 1 就可以大概率知道集合中有没有它了.
· 如果这些点有任何一个 0,则被查询变量一定不在;
· 如果都是 1,则被查询变量很**可能存在**
为什么说是可能存在,而不是一定存在呢?那是因为映射函数本身就是散列函数,散列函数是会有碰撞的。
优点:不需要存储key,节省空间
缺点:
- 算法判断key在集合中时,有一定的概率key其实不在集合中
2. 无法删除