飞道的博客

Redis进阶(主从复制、Redis集群、缓存穿透、缓存击穿、缓存雪崩)

345人阅读  评论(0)

目录

1、主从复制(读写分离)

1.1、什么是主从复制

1.2、主从复制的作用

1.3、环境搭建

1.4、一主二仆

1.5、注意事项

1.6、反客为主

1.7、哨兵模式(sentinel)

2、Redis集群

2.1、什么是集群

2.2、什么是redis集群

2.3、Redis集群中的哈希槽

2.4、Redis集群中节点的通信

2.5、如何判断某个节点挂掉

3、缓存穿透

3.1、缓存穿透概述

3.2、解决方案

4、缓存击穿

4.1、缓存击穿概述

4.2、解决方案

5、缓存雪崩

5.1、缓存雪崩概述

5.2、解决方案


 

1、主从复制(读写分离)

1.1、什么是主从复制

主从复制,是用来建立一个和主数据库完全一样的数据库环境,称为从数据库;主数据库一般是实时的业务数据库,从数据库的作用和使用场合一般有几个:一是作为后备数据库,主数据库服务器故障后,可切换到从数据库继续工作;二是可在从数据库作备份、数据统计等工作,这样不影响主数据库的性能。

1.2、主从复制的作用

做数据的热备,作为后备数据库,主数据库服务器故障后,可切换到从数据库继续工作,避免数据丢失。

主服务器: 一般用作写操作。

从服务器: 一般用于读操作。

 

1.3、环境搭建

首先在把redis下的redis.conf配置文件copy一份到一个新的文件夹,这里我创建一个myredis文件夹

[root@localhost myredis]# cp /usr/local/redis/redis-6.2.6/redis.conf myredis/redis.conf

复制端口6379

[root@localhost myredis]# vim redis6379.conf

将下面代码编辑到该配置文件
include  usr/local/redis/myredis/redis.conf
pidfile /var/run/redis_6379.conf
port 6379
dbfilename dump6379.rdb 

复制端口6380

[root@localhost myredis]# vim redis6380.conf

将下面代码编辑到该配置文件
include  usr/local/redis/myredis/redis.conf
pidfile /var/run/redis_6380.conf
port 6380
dbfilename dump6380.rdb 

复制端口6381

[root@localhost myredis]# vim redis6381.conf

将下面代码编辑到该配置文件
include  usr/local/redis/myredis/redis.conf
pidfile /var/run/redis_6381.conf
port 6381
dbfilename dump6381.rdb 

启动各个端口的redis 

[root@localhost myredis]# redis-server redis6379.conf
[root@localhost myredis]# redis-server redis6380.conf
[root@localhost myredis]# redis-server redis6381.conf 

查看redis进程

[root@localhost myredis]# ps -ef | grep redis
root       5209      1  0 06:10 ?        00:00:01 redis-server 127.0.0.1:6380
root       5243      1  0 06:10 ?        00:00:01 redis-server 127.0.0.1:6381
root       5611      1  0 06:24 ?        00:00:00 redis-server 127.0.0.1:6379
root       5620   3992  0 06:24 pts/0    00:00:00 grep --color=auto redis 

分别打开三个窗口连接三个服务器 

redis-cli -p 6379
redis-cli -p 6380
redis-cli -p 6381 

 

1.4、一主二仆

这里把6379当作主服务器,把6380、6381当作为从服务器,那么6380、6381就要通过命令去绑定主服务器,在6380、6381服务器分别输入以下命令,将6379服务器当作主服务器。

127.0.0.1:6380> slaveof 127.0.0.1 6379
OK

127.0.0.1:6381> slaveof 127.0.0.1 6379
OK 

 

-- 测试主服务器 写 操作    
127.0.0.1:6379> set a 1
OK
-- 从服务器 读 操作
127.0.0.1:6380> get a
"1"
127.0.0.1:6381> get a
"1"

1.5、注意事项

1、当其中的一个从服务器 shutdown 挂掉了,从服务器再次启动还会不会重新连接到主服务器中?

不会,会自动变成主服务器。

2、如果把挂掉的从服务器重新连到主服务器后,主服务器的数据还会不会复制过来?

会。

3、当主服务器挂掉后,从服务器不会做任何事情,查看从服务器 info replication服务器情况,还认主服务器只是状态挂掉了,再次重启主服务器,又回到主服务位置。

1.6、反客为主

将主服务器挂掉

-- 主服务器挂掉 --
127.0.0.1:6379> shutdown

把从服务器上位为主服务器

-- 把从服务器上位为主服务器 --
127.0.0.1:6380> slaveof no one
OK

 

 -- 6381从服务器挂上6380服务器 --
127.0.0.1:6381> slaveof 127.0.0.1 6380
OK

1.7、哨兵模式(sentinel)

是一种容灾方案。以上主服务器挂了,虽然从服务器变成了主服务器,但是有一个问题,是手动变成服务器

哨兵:实则是一个在特殊模式下的Redis服务器,里面存储的是自己本身的信息,主服务器的信息,从服务器的信息。

用一个或者多个哨兵来监视主服务器(也就是进行写操作的服务器)是否在正常执行任务,一旦哨兵发现主服务器不可用时,就找到一个合适的从服务器成为主服务器。

恢复到6379位主服务器,6380、6381位从服务器的状态

在当前myredis目录下创建 sentinel.conf 文件,名字不要写错,配置如下

sentinel monitor mymaster 127.0.0.1 6379 1

mymaster为监控对象起的服务器名字 ,1 只要有一个哨兵认为master宕机就可以切换,同时会选举1个哨兵进行迁移的数据

启动哨兵模式

[root@localhost myredis]# redis-sentinel sentinel.conf

 

把主服务器6379服务器 shutdown , 查看哨并是否会自动把从服务器变成主服务器

-- 主服务器 shutdown 宕机 --
127.0.0.1:6379> SHUTDOWN

-- 只剩下6380和6381--
[root@localhost myredis]# ps -ef|grep redis
root       5209      1  0 06:10 ?        00:00:10 redis-server 127.0.0.1:6380
root       5243      1  0 06:10 ?        00:00:10 redis-server 127.0.0.1:6381
yanqi      6597   5400  0 07:36 pts/2    00:00:00 redis-cli -p 6380
yanqi      6598   5327  0 07:36 pts/1    00:00:00 redis-cli -p 6381
root       7279   7080  0 08:07 pts/3    00:00:00 redis-sentinel *:26379 [sentinel]
root       7333   3992  0 08:10 pts/0    00:00:00 grep --color=auto redis

此时哨兵会检测到主服务器宕机,会再选择一个从服务器上位主服务器

 

 

2、Redis集群

2.1、什么是集群

如果说主从复制是各司其职的话,那么集群就是一群同样的个体做着同样的事情。在Redis中,数据的写入操作次数很大的情况下,只使用单独一个服务器来进行写入操作的话,效率不高,那么如果使用集群方案,利用多个Redis服务器来进行写操作,大量的数据,你写一点,我写一点,大家都分担一点,那么效率会高很多。就像工地上搬砖,一个人搬肯定效率非常慢,但是叫来十几个人一起搬,用不了多少时间就会被搬空,人越多效率越高,也就是说我们数据容量大大提升了!

集群模式的思想可以在多处使用。总之就是,一个个体完成不了或者说效率很低的场景下,都可以使用这种思想。

2.2、什么是redis集群

  • Redis-Cluster的概念 Redis-Cluster采用无中心结构,集群中的每个节点都是平等的关系,都是对等的,每个节点都保存各自的数据和整个集群的状态。每个节点都和其他所有节点连接,而且这些连接保持活跃,这样就保证了我们只需要连接集群中的任意一个节点,就可以获取到其他节点的数据。

  • 数据分散存储 Redis 集群并没有使用传统的一致性哈希来分配数据,而是采用另外一种叫做 哈希槽(hash slot) 的方式来分配的。redis cluster 默认分配了 16384 个slot,当我们set一个key 时,会用CRC16算法来取模得到所属的slot,然后将这个key 分到哈希槽区间的节点上,具体算法就是:CRC16(key) % 16384。

  • Redis 是在内存中保存数据的,而我们的电脑一般内存都不大, 这也就意味着 Redis 不适合存储大数据,适合存储大数据的是 Hadoop 生态系统的 Hbase 或 者是 MogoDB。Redis 更适合处理高并发,一台设备的存储能力是很有限的,但是多台设备 协同合作,就可以让内存增大很多倍,这就需要用到集群。

  • Redis 集群搭建的方式有多种,例如使用客户端分片、Twitter开发的Twemproxy、豌豆荚开发的Codis 等,但从 redis 3.0 之后版本支持 redis-cluster 集群,它是 Redis 官方提出的解决方案, Redis-Cluster 采用无中心结构,每个节点保存数据和整个集群状态,每个节点都和其他所 有节点连接。

2.3、Redis集群中的哈希槽

Redis集群中引入了哈希槽的概念,Redis集群有16384个哈希槽,进行set操作时,每个key会通过CRC16校验后再对16384取模来决定放置在哪个槽,搭建Redis集群时会先给集群中每个master节点分配一部分哈希槽。 比如当前集群有3个master节点,

master1节点包含0~5500号哈希槽, master2节点包含5501~11000号哈希槽, master3节点包含11001~16384号哈希槽,

当我们执行“set key value”时,假如 CRC16(key) % 16384 = 777,那么这个key就会被分配到master1节点上,如下图

 

2.4、Redis集群中节点的通信

既然Redis集群中的数据是通过哈希槽的方式分开存储的,那么集群中每个节点都需要知道其他所有节点的状态信息,包括当前集群状态、集群中各节点负责的哈希槽、集群中各节点的master-slave状态、集群中各节点的存活状态等。Redis集群中,节点之间通过建立TCP连接,使用gossip协议来传播集群的信息。如下图:

2.5、如何判断某个节点挂掉

首先要说的是,每一个节点都存有这个集群所有主节点以及从节点的信息。它们之间通过互相的ping-pong判断是否节点可以连接上。如果有一半以上的节点去ping一个节点的时候没有回应,集群就认为这个节点宕机了,然后去连接它的备用节点。

3、缓存穿透

3.1、缓存穿透概述

缓存穿透是指缓存和数据库中都没有的数据,这样每次请求都会去查库,不会查缓存,如果同一时间有大量(高并发)请求进来的话,就会给数据库造成巨大的查询压力,甚至击垮数据库。

3.2、解决方案

1、对空值缓存:如果一个查询返回的数据为空,不管数据是否存在,我们仍然把这个空值作缓存,设置空值的过期时间很短。

2、设置访问的白名单:使用bitmaps类型定义一个可以访问的名单,名单id作为bitmaps偏移的量,每次访问和bitmaps有id进行对比,如果不存在就拦截,不允许访问

3、布隆过滤器:布隆过滤器底层使用bit数组存储数据,该数组中的元素默认值是0。布隆过滤器第一次初始化的时候,会把数据库中所有已存在的key,经过一些列的hash算法(比如:三次hash算法)计算,每个key都会计算出多个位置,然后把这些位置上的元素值设置成1。 之后,有用户key请求过来的时候,再用相同的hash算法计算位置。

  • 如果多个位置中的元素值都是1,则说明该key在数据库中已存在。这时允许继续往后面操作。

  • 如果有1个以上的位置上的元素值是0,则说明该key在数据库中不存在。这时可以拒绝该请求,而直接返回。

其实,布隆过滤器最致命的问题是:如果数据库中的数据更新了,需要同步更新布隆过滤器。但它跟数据库是两个数据源,就可能存在数据不一致的情况。

比如:数据库中新增了一个用户,该用户数据需要实时同步到布隆过滤。但由于网络异常,同步失败了。

这时刚好该用户请求过来了,由于布隆过滤器没有该key的数据,所以直接拒绝了该请求。但这个是正常的用户,也被拦截了。

很显然,如果出现了这种正常用户被拦截了情况,有些业务是无法容忍的。所以,布隆过滤器要看实际业务场景再决定是否使用,它帮我们解决了缓存穿透问题,但同时了带来了新的问题。

4、缓存击穿

4.1、缓存击穿概述

有时候,我们在访问热点数据时。比如:我们在某个商城购买某个热门商品。 为了保证访问速度,通常情况下,商城系统会把商品信息放到缓存中。但如果某个时刻,该商品到了过期时间失效了。 此时,如果有大量的用户请求同一个商品,但该商品在缓存中失效了,一下子这些用户请求都直接到了数据库,可能会造成瞬间数据库压力过大,而直接挂掉。

4.2、解决方案

1、设置热点数据永不过期。(也是一种解决方式,但是实际过程中不推荐)

2、加锁的方式:锁的对象就是key,这样,当大量查询同一个key的请求并发进来时,只能有一个请求获取到锁,然后获取到锁的线程查询数据库,然后将结果放入到缓存中,然后释放锁,此时,其他处于锁等待的请求即可继续执行,由于此时缓存中已经有了数据,所以直接从缓存中获取到数据返回,并不会查询数据库。也就是加锁让一个人去查询数据并把数据存储到缓存中,其他人再查询的时候就直接从缓存中获取了。

5、缓存雪崩

5.1、缓存雪崩概述

缓存雪崩是指当缓存中有大量的key在同一时刻过期,或者Redis直接宕机了,导致大量的查询请求全部到达数据库,造成数据库查询压力骤增,甚至直接挂掉。

5.2、解决方案

  • 给不同的key的TTL添加随机值,避免大量的key同时到期

  • 利用Redis集群提高服务的可用性,避免Redis服务宕机后的数据丢失和请求直达数据库

  • 给缓存业务添加降级限流策略

  • 给业务添加多级缓存


转载:https://blog.csdn.net/select_myname/article/details/128024304
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场