redis应用02:redis内存策略,集群

redis cluster 分布式存储, 主从模式

redis几个问题

1、redis是内存版的数据库,如果内存存储满了,怎么办?
2、redis是否是线程安全的数据库?
3、关于redis的hash槽,你是怎么理解的?(redis数据库是如何存储的?)
4、redis缓存穿透,缓存击穿,缓存雪崩?

https://www.jianshu.com/p/5fcf7a3e9f4d

参考

https://redis.io/topics/cluster-tutorial

http://www.runoob.com/redis/redis-partitioning.html

为什么要集群

Redis Cluster还在分区期间提供一定程度的可用性,实际上是在某些节点发生故障或无法通信时继续运行的能力。 但是,如果发生较大的故障(例如,当大多数主设备不可用时),群集将停止运行。

那么实际上,你使用Redis Cluster获得了什么?

能够在多个节点之间自动拆分数据集。
当节点的子集遇到故障或无法与群集的其余部分通信时,能够继续操作。

hash slot:分布式存储

Redis群集数据分片
Redis Cluster不使用一致的散列,而是使用不同形式的分片,其中每个键在概念上都是我们称之为散列槽的一部分。

Redis集群中有16384个散列槽,为了计算给定密钥的散列槽,我们只需采用密钥模数16384的CRC16。

Redis群集中的每个节点都负责散列槽的子集,因此例如,您可能拥有一个包含3个节点的群集,其中:

节点A包含从0到5500的散列槽。
节点B包含从5501到11000的散列槽。
节点C包含从11001到16383的散列槽。
这允许轻松添加和删除群集中的节点。例如,如果我想添加一个新节点D,我需要将一些哈希槽从节点A,B,C移动到D.同样,如果我想从群集中删除节点A,我可以只移动A服务的哈希槽到B和C.当节点A为空时,我可以完全从集群中删除它。

因为将哈希槽从一个节点移动到另一个节点不需要停止操作,添加和删除节点,或者更改节点所拥有的哈希槽的百分比,所以不需要任何停机时间。

只要涉及单个命令执行(或整个事务或Lua脚本执行)的所有键都属于同一个哈希槽,Redis Cluster就支持多个键操作。用户可以通过使用称为哈希标记的概念强制多个密钥成为同一哈希槽的一部分。

分区缺点:


4165335-e255e99b1bf02c75.png
redis分区缺点.png

Redis Cluster主从模型

如果没有主从模式,redis分片只能算作是分布式,而非集群;
添加了主从模式,才能算作是集群。

为了在主节点子集发生故障或无法与大多数节点通信时保持可用,Redis群集使用主从模型,其中每个散列槽从1(主机本身)到N个副本(N -1个额外的从节点)。

在我们的节点A,B,C的示例集群中,如果节点B出现故障,则集群无法继续,因为我们无法再在5501-11000范围内提供服务散列槽的方法。

然而,当创建集群时(或稍后),我们向每个主节点添加一个从节点,以便最终集群由作为主节点的A,B,C和作为从节点的A1,B1,C1组成。 ,如果节点B出现故障,系统可以继续。

节点B1复制B,B失败,集群将节点B1作为新主节点升级,并将继续正常运行。

但请注意,如果节点B和B1同时出现故障,Redis Cluster将无法继续运行。

Redis群集一致性保证

Redis Cluster无法保证强一致性。实际上,这意味着在某些条件下,Redis Cluster可能会丢失系统向客户端确认的写入。

Redis Cluster可能丢失写入的第一个原因是它使用异步复制。这意味着在写入期间会发生以下情况:

您的客户端写入主B.
主人B向您的客户回复确定。
主设备B将写入传播到其从设备B1,B2和B3。
正如你所看到的,在回复客户端之前,B不会等待来自B1,B2,B3的确认,因为这对Redis来说是一个过高的延迟惩罚,所以如果你的客户端写了一些内容,B会确认写入,但在崩溃之前崩溃能够将写入发送到其从属服务器,其中一个从属服务器(没有接收到写入)可以被提升为主服务器,永远丢失写入。

这与配置为每秒将数据刷新到磁盘的大多数数据库所发生的情况非常相似,因此,由于过去使用不涉及分布式系统的传统数据库系统的经验,因此您已经能够推断这种情况。同样,您可以通过在回复客户端之前强制数据库刷新磁盘上的数据来提高一致性,但这通常会导致性能过低。在Redis Cluster的情况下,这相当于同步复制。

基本上需要在性能和一致性之间进行权衡。

Redis Cluster在绝对需要时支持同步写入,通过WAIT命令实现,这使得丢失写入的可能性大大降低,但请注意,即使使用同步复制,Redis Cluster也不会实现强一致性:在更复杂的情况下,它总是可能的无法接收写入的从站被选为主站的故障情形。

还有另一个值得注意的情况是,Redis群集将丢失写入,这种情况发生在网络分区中,其中客户端与少数实例(至少包括主服务器)隔离。

以我们的6节点集群为例,包括A,B,C,A1,B1,C1,3个主站和3个从站。还有一个客户,我们称之为Z1。

在发生分区之后,可能在分区的一侧有A,C,A1,B1,C1,在另一侧有B和Z1。

Z1仍然可以写入B,它将接受其写入。如果分区在很短的时间内恢复,群集将继续正常运行。但是,如果分区持续足够的时间使B1在分区的多数侧被提升为主站,则Z1发送给B的写入将丢失。

请注意,Z1将能够发送到B的写入量有一个最大窗口:如果分区的多数方面已经有足够的时间将从属设备选为主设备,则少数端的每个主节点都会停止接受写入。

这段时间是Redis Cluster非常重要的配置指令,称为节点超时。

节点超时过后,主节点被视为失败,可以由其中一个副本替换。类似地,在节点超时已经过去而主节点无法感知大多数其他主节点之后,它进入错误状态并停止接受写入。

redis cluster搭建

三、集群
即使使用哨兵,redis每个实例也是全量存储,每个redis存储的内容都是完整的数据,浪费内存且有木桶效应。为了最大化利用内存,可以采用集群,就是分布式存储。即每台redis存储不同的内容,
共有16384个slot。每个redis分得一些slot,hash_slot = crc16(key) mod 16384 找到对应slot,键是可用键,如果有{}则取{}内的作为可用键,否则整个键是可用键

集群至少需要3主3从,且每个实例使用不同的配置文件,主从不用配置,集群会自己选。

修改每个实例的配置文件:

cluster-enabled yes  --开启集群

cluster-config-file nodes-6382.conf --集群配置文件名,每个实例配置的要不同,redis会根据文件名自动新建

用集群工具创建集群:
我们可以用集群工具进行集群,该工具是redis源码包中,用ruby编写,所以需要先安装ruby。

1、安装rubygems

yum install ruby 
yum install rubygems  
gem install redis

2、把6个redis实例都起来,每个实例的集群都打开。

3、redis安装目录的src执行./redis-trib.rb create --replicas 1 127.0.0.1:6380 127.0.0.1:6381 127.0.0.1:6382 127.0.0.1:6383 127.0.0.1:6384 127.0.0.1:6385

提示信息如下

Connecting to node 127.0.0.1:6380: OK
Connecting to node 127.0.0.1:6381: OK
Connecting to node 127.0.0.1:6382: OK
Connecting to node 127.0.0.1:6383: OK
Connecting to node 127.0.0.1:6384: OK
Connecting to node 127.0.0.1:6385: OK

Performing hash slots allocation on 6 nodes...
Using 3 masters:
127.0.0.1:6380
127.0.0.1:6381
127.0.0.1:6382
Adding replica 127.0.0.1:6383 to 127.0.0.1:6380
Adding replica 127.0.0.1:6384 to 127.0.0.1:6381
Adding replica 127.0.0.1:6385 to 127.0.0.1:6382
M: d4f906940d68714db787a60837f57fa496de5d12 127.0.0.1:6380 slots:0-5460 (5461 slots) master
M: b547d05c9d0e188993befec4ae5ccb430343fb4b 127.0.0.1:6381 slots:5461-10922 (5462 slots) master
M: 887fe91bf218f203194403807e0aee941e985286 127.0.0.1:6382 slots:10923-16383 (5461 slots) master
S: e0f6559be7a121498fae80d44bf18027619d9995 127.0.0.1:6383 replicates d4f906940d68714db787a60837f57fa496de5d12
S: a61dbf654c9d9a4d45efd425350ebf720a6660fc 127.0.0.1:6384 replicates b547d05c9d0e188993befec4ae5ccb430343fb4b
S: 551e5094789035affc489db267c8519c3a29f35d 127.0.0.1:6385 replicates 887fe91bf218f203194403807e0aee941e985286
Can I set the above configuration? (type 'yes' to accept):

输入yes,这样集群就建立了。

登录任一台redis,执行 info cluster,提示cluster_enabled:1

集群过程:
首先redis-trib.rb会以客户端的形式尝试连接所有的节点,并发送PING命令以确定节点能够正常服务。如果有任何节点无法连接,则创建失败。同时发送 INFO 命令获取每个节点的运行ID以及是否开启了集群功能(即cluster_enabled为1)。 准备就绪后集群会向每个节点发送 CLUSTER MEET命令,格式为 CLUSTER MEET ip port,这个命令用来告诉当前节点指定ip和port上在运行的节点也是集群的一部分,从而使得6个节点最终可以归入一个集群。

然后redis-trib.rb会分配主从数据库节点,分配的原则是尽量保证每个主数据库运行在不同的IP地址上,同时每个从数据库和主数据库均不运行在同一IP地址上,以保证系统的容灾能力

3主3从,当1个主故障,大家会给对应的从投票,把从立为主,若没有从数据库可以恢复则redis集群就down了。

客户端连接:
使用redis-cli -c -p 任意一个端口


作者:黄河边上的牧马人
来源:CSDN
原文:https://blog.csdn.net/c295477887/article/details/52487621
版权声明:本文为博主原创文章,转载请附上博文链接!

java客户端连接集群

集群至少需要3主3从,且每个实例使用不同的配置文件,主从不用配置,集群会自己选。

https://juejin.im/post/5ad54d76f265da23970759d3

客户端连接redis cluster: JedisCluster

    @Test
    public void testJedisCluster() throws Exception {
        // 创建一个JedisCluster对象。有一个参数nodes是一个set类
型。set中包含若干个HostAndPort对象。
        Set<HostAndPort> nodes = new HashSet<>();
        nodes.add(new HostAndPort("192.168.25.155", 7001));
        nodes.add(new HostAndPort("192.168.25.155", 7002));
        nodes.add(new HostAndPort("192.168.25.155", 7003));
        nodes.add(new HostAndPort("192.168.25.155", 7004));
        nodes.add(new HostAndPort("192.168.25.155", 7005));
        nodes.add(new HostAndPort("192.168.25.155", 7006));
        JedisCluster jedisCluster = new JedisCluster(nodes);
        // 直接使用JedisCluster对象操作redis。
        jedisCluster.set("test", "123");
        String string = jedisCluster.get("test");
        System.out.println(string);
        // 关闭JedisCluster对象
        jedisCluster.close();
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值