• Redis与分布式:集群搭建


    如果我们服务器的内存不够用了,但是现在我们的Redis又需要继续存储内容,那么这个时候就可以利用集群来实现扩容。

    因为单机的内存容量最大就那么多,已经没办法再继续扩展了,但是现在又需要存储更多的内容,这时我们就可以让N台机器上的Redis来分别存储各个部分的数据(每个Redis可以存储1/N的数据量),这样就实现了容量的横向扩展。同时每台Redis还可以配一个从节点,这样就可以更好地保证数据的安全性。

    那么问题来,现在用户来了一个写入的请求,数据该写到哪个节点上呢?我们来研究一下集群的机制:

    首先,一个Redis集群包含16384个插槽,集群中的每个Redis 实例负责维护一部分插槽以及插槽所映射的键值数据,那么这个插槽是什么意思呢?

    实际上,插槽就是键的Hash计算后的一个结果,注意这里出现了计算机网络中的CRC循环冗余校验,这里采用CRC16,能得到16个bit位的数据,也就是说算出来之后结果是0-65535之间,再进行取模,得到最终结果:

    Redis key的路由计算公式:slot = CRC16(key) % 16384

    结果的值是多少,就应该存放到对应维护的Redis下,比如Redis节点1负责0-25565的插槽,而这时客户端插入了一个新的数据a=10,a在Hash计算后结果为666,那么a就应该存放到1号Redis节点中。简而言之,本质上就是通过哈希算法将插入的数据分摊到各个节点的,所以说哈希算法真的是处处都有用啊。

    那么现在我们就来搭建一个简单的Redis集群,这里创建6个配置,注意开启集群模式:

    1. # Normal Redis instances can't be part of a Redis Cluster; only nodes that are
    2. # started as cluster nodes can. In order to start a Redis instance as a
    3. # cluster node enable the cluster support uncommenting the following:
    4. #
    5. cluster-enabled yes

    接着记得把所有的持久化文件全部删除,所有的节点内容必须是空的。

    然后输入redis-cli.exe --cluster create --cluster-replicas 1 127.0.0.1:6001 127.0.0.1:6002 127.0.0.1:6003 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003,这里的--cluster-replicas 1指的是每个节点配一个从节点:

    输入之后,会为你展示客户端默认分配的方案,并且会询问你当前的方案是否合理。可以看到6001/6002/6003都被选为主节点,其他的为从节点,我们直接输入yes即可:

    最后分配成功,可以看到插槽的分配情况:

    现在我们随便连接一个节点,尝试插入一个值:

    在插入时,出现了一个错误,实际上这就是因为a计算出来的哈希值(插槽),不归当前节点管,我们得去管这个插槽的节点执行,通过上面的分配情况,我们可以得到15495属于节点6003管理:

    在6003节点插入成功,当然我们也可以使用集群方式连接,这样我们无论在哪个节点都可以插入,只需要添加-c表示以集群模式访问:

    可以看到,在6001节点成功对a的值进行了更新,只不过还是被重定向到了6003节点进行插入。

    我们可以输入cluster nodes命令来查看当前所有节点的信息:

    那么现在如果我们让某一个主节点挂掉会怎么样?现在我们把6001挂掉:

    可以看到原本的6001从节点7001,晋升为了新的主节点,而之前的6001已经挂了,现在我们将6001重启试试看:

    可以看到6001变成了7001的从节点,那么要是6001和7001都挂了呢?

    这时我们尝试插入新的数据:

    可以看到,当存在节点不可用时,会无法插入新的数据,现在我们将6001和7001恢复:


    可以看到恢复之后又可以继续正常使用了。

    最后我们来看一下如何使用Java连接到集群模式下的Redis,我们需要用到JedisCluster对象:

    1. public class Main {
    2. public static void main(String[] args) {
    3. //和客户端一样,随便连一个就行,也可以多写几个,构造方法有很多种可以选择
    4. try(JedisCluster cluster = new JedisCluster(new HostAndPort("192.168.0.8", 6003))){
    5. System.out.println("集群实例数量:"+cluster.getClusterNodes().size());
    6. cluster.set("a", "yyds");
    7. System.out.println(cluster.get("a"));
    8. }
    9. }
    10. }

     操作基本和Jedis对象一样,这里就不多做赘述了。

  • 相关阅读:
    笔记1.5:计算机网络体系结构
    Docker的数据管理(数据卷、容器互联)
    SinoDB数据库资源分析
    2.Linux系统管理(vi和vim的使用)
    Oracle Primavera Unifier 23.4 新特征
    axios.js get 请求 生成参数的方法,兼容golang gin
    Llama 3王者归来,可与GPT-4分庭抗礼,开源模型即将追上闭源模型了?
    Nginx重定向
    Roaring Bitmap 更好的位图压缩算法
    计算机三级数据库数据仓库与数据挖掘(一)、快照方式、元数据、数据仓库中数据特征、机器学习、聚类方法、分类算法、决策支持系统、表数据的粒度级、分布式数据库、
  • 原文地址:https://blog.csdn.net/Leon_Jinhai_Sun/article/details/126081621