Redis完全教程:全面学习指南(六)

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介: Redis完全教程:全面学习指南(六)

13、Redis集群

13.1、问题

  • 容量不够,redis如何进行扩容?
  • 并发写操作,redis如何分摊?
  • 主从模式,薪火相传,主机宕机,导致ip发生变化,需要修改很多配置,相当繁琐,但是redis3.0中提供了解决方案,就是无中心化集群配置。

13.2、什么是集群

Redis集群实现了对Redis的水平扩容,即启动N个redis节点,将整个数据库分布存储在这N个节点中,每个节点存储总数据的1/N

Redis集群通过分区(partiition)来提供一定程度的可用性(availablity):即使集群中有一部分节点失效或者无法进行通讯,集群也可以继续处理命令请求。

13.3、准备开始搭建集群

1、创建/myredis-sluster文件夹来存放我们的相关文件

mkdir myredis-cluster

2、复制一份redis.conf放进去(跟主从那块一样)

[root@VM-4-12-centos /]# cd myredis-cluster/
[root@VM-4-12-centos myredis-cluster]# cp /usr/local/bin/redis.conf /myredis-cluster/redis.conf

3、创建6个配置文件,一个主一个从,也就是三组主从关系

redis6390.conf , redis6391.conf

redis6392.conf , redis6393.conf

redis6394.conf , redis6395.conf

先创建一个文件,其他的进行复制修改端口即可,执行命令:

vi redis6390.conf

然后在文件中加入以下内容

include /myredis-cluster/redis.conf
pidfile "/var/run/redis_6390.pid"
port 6390
dbfilename "dump6390.rdb"
cluster-enabled yes
cluster-config-file nodes-6390.conf
cluster-node-timeout 15000

配置解释

cluster-enabled yes:打开集群模式

cluster-config-file:设定节点配置文件名

cluster-node-timeout: 节点失联时间,超过后集群自动进行主从切换

然后复制5份不同端口的文件,只许改动端口号即可。完成后如下所示:

[root@VM-4-12-centos myredis-cluster]# ls
redis6390.conf  redis6392.conf  redis6394.conf  redis.conf
redis6391.conf  redis6393.conf  redis6395.conf

4、启动这6个端口

redis-server redis6390.conf
redis-server redis6391.conf
redis-server redis6392.conf
redis-server redis6393.conf
redis-server redis6394.conf
redis-server redis6395.conf

5、将6个节点合成一个集群

进入你的src目录下,也就是redis安装位置下面的src文件夹

cd redis-6.2.6/src

执行以下命令即可:

redis-cli --cluster create --cluster-replicas 1 10.0.4.12:6390 10.0.4.12:6392 10.0.4.12:6394 10.0.4.12:6391 10.0.4.12:6393 10.0.4.12:6395

**注意:**此处不要用127.0.0.1,请求真实ip地址。

replicas 1:代表每台主机下面从机的个数,一台主机一台从机,正好三组

执行命令后出现以下提示:

会给你分配好主机从机的对应关系,输入yes即可。

注意这里[ok] All 16384 slots covered,稍后在slots进行分析

13.4、什么是slots

上面我们将6个节点合并为集群后,最后的结果有一句话

``[ok] All 16384 slots covered`

解释:

一个Redis集群包含16384个插槽(hash slot),数据中的每个键都属于这16384个插槽的其中一个。

集群使用公式CRC16(key)% 16384来计算键key属于哪个槽,其中CRC16(key)语句用于计算键key的CRC16校验和。

集群中的每一部分负责处理一部分插槽。

举例:

比如有A、B、C三个节点,A负责【0-5460】,B负责【5461-10922】,C负责【10923-16383】

13.5、-c采用集群策略连接,设置的数据会自动切换到相应的写主机

如果想设置多个值呢

不在一个slot下的键值,是不能使用mget,mset等多键操作

可以通过{}来定义组的概念,从而使key中{}内相同内容的键值放到一个slot中去

13.6、查询集群中的值

查询某个键的插槽值

10.0.4.12:6390> cluster keyslot k2
(integer) 449

查看某个插槽中有几个key(注意:只能在自己的范围插槽内进行查询)

10.0.4.12:6390> set city beijing
-> Redirected to slot [11479] located at 10.0.4.12:6394
OK
10.0.4.12:6394> cluster countkeysinslot 11479
(integer) 1

在指定插槽里面返回指定的个数的key

10.0.4.12:6390> set city beijing
-> Redirected to slot [11479] located at 10.0.4.12:6394
OK
10.0.4.12:6394> cluster getkeysinslot 11479 1
1) "city"

13.7、故障修复

shutdown一个主节点,从节点会自动升为主节点

1、将6394主节点shutdown掉,然后重新集群策略连接一个主节点

2、cluster nodes:查看集群主从机相关信息

结论:从节点自动升为主节点,原来的主节点fail掉

主节点恢复后,主从关系如何?主节点变回从机

1、新开一个窗口重新启动6394

redis-server redis6394.conf

2、集群信息变化

结论:主节点恢复后,主节点会变成从机

如果某个节点的主从节点全部宕掉,redis服务是否可以继续

结论:

与redis.conf中的参数 cluster-require-full-coverage有关

如果cluster-require-full-coverage为yes,那么所有集群都挂掉

反之,其他插槽依然可以使用,该插槽全部数据不能使用,也无法存储。

13.8、优缺点

优点

  • 实现扩容
  • 分摊压力
  • 无中心配置

缺点:

  • 多键操作不被支持
  • 多键的Redis事务不被支持

14、Redis应用问题

14.1、缓存穿透

概念

缓存穿透的概念很简单,用户想要查询一个数据,发现redis内存数据库没有,也就是缓存没有命中,于是向持久层数据库查询。发现也没有,于是本次查询失败,当用户很多的时候,缓存都没有命中,全部请求了持久层数据库,这会给持久层数据库造成很大的压力,这时候就相当于出现了缓存穿透。

解决方案

缓存空值

如果一个查询返回的数据为空,我们仍然对这个空结果进行缓存,设置空结果的过期时间会很短,最长不超过5分钟

布隆过滤器

布隆过滤器是一种数据结构,对所有可能查询的参数以hash形式存储,在控制层先进行校验,不符合则丢弃,从而避免了对底层存储系统的查询压力。

14.2、缓存击穿

概念

缓存击穿,是指一个key非常热点,在不停的扛着大并发,大并发集中对这个点进行访问,当在这个key失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在屏障上凿开一个洞

解决方案

设置热点时间永不过期

加互斥锁

分布式锁:保证对于每个key同时只有一个线程去查询后端服务,其他线程没有获得分布式锁的权限,因此只需要等待即可

14.3、缓存雪崩

概念

缓存雪崩是指缓存中数据大批量到过期时间,而查询数据量巨大,引起数据库压力过大甚至down机。

解决方案

redis高可用

就是多搭建redis集群

限流

缓存失效后,通过加锁或者队列来控制数据库写缓存的线程数量,比如对某个key只允许一个线程查询数据和写缓存,其他线程等待。

15、分布式锁

15.1、概念

随着业务发展的需要,原单体单机部署的系统被演化成分布式集群系统后,由于分布式系统多线程、多进程并且分布在不同的机器上,这将使原单机部署的情况并发控制锁策略失效,单纯的Java API并不能提供分布式锁的能力,为了解决这个问题就需要一种跨JVM的互斥机制来控制共享资源的访问,这就是分布式锁要解决的问题

15.2、分布式锁的主流实现方案

  • 基于数据库实现分布式锁
  • 基于缓存(Redis等)
  • 基于Zookeeper

优缺点

  • 性能:redis最高
  • 可靠性:zookeeper最高

15.3、使用redis实现分布式锁

15.3.1、设置锁和过期时间

setnx key value`:设置key后,不可修改,除非删除后(或者过期后),也就是释放锁后才能再次操作

127.0.0.1:6380> setnx k1 v1
(integer) 1
# 不能修改
127.0.0.1:6380> setnx k1 v2
(integer) 0
127.0.0.1:6380> del k1
(integer) 1
127.0.0.1:6380> setnx k1 v1
(integer) 1

**问题一:**如果刚上完锁突然断点了,那过期时间无法设置了,那锁岂不是这个时间段一直没释放?

解决:我们可以在上锁的时候同时设置过期时间

set key value nx ex 12:即上锁又设置过期时间

127.0.0.1:6380> set k2 v2 nx ex 12
OK

15.3.2、UUID防止误删

问题

在redis分布式锁的时候,会去设置一个key,如果可以设置成功(也就是这个key不存在)则说明拿到锁,反之没有拿到锁(这个key已经存在,代表已经被上锁),但是会不会有这么一种情况?一个没有拿到锁的线程,把这个key给删掉,也就是释放了别人的锁,这种情况是肯定不能出现的。

解决

在拿锁的时候,key对应的value值可以用UUID生成,每次在释放锁的时候都要先进行判断,如果对应的value是你自己设置的value,就成功释放,防止误删操作。

15.3.3、LUA保证删除原子性

问题描述

a拿到锁—>执行具体操作—>比较uuid(一样)—>准备删除锁,但是还没有删除的时候锁到了过期时间自动释放—>这个时候b拿到锁—>a继续删除操作—>最终a释放了b的锁

解决方案

使用LUA脚本,类似于redis事务,有一定的原子性,不会被其他命令插队,可以完成一些redis事务性的操作。

15.3.4、分布式锁的几个必要条件

  • 互斥性:任意时刻,只有一个客户端能持有锁
  • 不会发生死锁,即使一个客户端持有锁期间崩溃而没有主动解锁,也能保证后续客户端可以加锁
  • 加锁解锁必须是同一个客户端
  • 加锁和解锁必须具有原子性
相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
4月前
|
存储 NoSQL Linux
小白带你学习linux的Redis基础(三十二)
小白带你学习linux的Redis基础(三十二)
74 0
|
3月前
|
存储 NoSQL Redis
redis源码学习
redis源码学习
|
4月前
|
存储 NoSQL Ubuntu
在Ubuntu上安装Redis并学习使用get、set和keys命令
在Ubuntu上安装Redis并学习使用get、set和keys命令
|
5月前
|
缓存 NoSQL Redis
【Redis 系列】redis 学习十六,redis 字典(map) 及其核心编码结构
【Redis 系列】redis 学习十六,redis 字典(map) 及其核心编码结构
|
5月前
|
NoSQL 算法 Redis
【Redis 系列】redis 学习十四,sorted_set 初步探究梳理
【Redis 系列】redis 学习十四,sorted_set 初步探究梳理
|
5月前
|
存储 NoSQL Redis
【Redis 系列】redis 学习十五,redis sds数据结构和底层设计原理
【Redis 系列】redis 学习十五,redis sds数据结构和底层设计原理
|
3月前
|
NoSQL 中间件 API
分布式锁【数据库乐观锁实现的分布式锁、Zookeeper分布式锁原理、Redis实现的分布式锁】(三)-全面详解(学习总结---从入门到深化)(下)
分布式锁【数据库乐观锁实现的分布式锁、Zookeeper分布式锁原理、Redis实现的分布式锁】(三)-全面详解(学习总结---从入门到深化)
82 2
|
3月前
|
NoSQL Java API
分布式锁【数据库乐观锁实现的分布式锁、Zookeeper分布式锁原理、Redis实现的分布式锁】(三)-全面详解(学习总结---从入门到深化)(上)
分布式锁【数据库乐观锁实现的分布式锁、Zookeeper分布式锁原理、Redis实现的分布式锁】(三)-全面详解(学习总结---从入门到深化)
74 0
|
5月前
|
存储 NoSQL 算法
[Redis 系列]redis 学习 17,redis 存储结构原理 1
[Redis 系列]redis 学习 17,redis 存储结构原理 1
|
1月前
|
存储 NoSQL Java
【Redis】1、学习 Redis 的五大基本数据类型【String、Hash、List、Set、SortedSet】
【Redis】1、学习 Redis 的五大基本数据类型【String、Hash、List、Set、SortedSet】
54 0

热门文章

最新文章