文章 62
浏览 15135
哈希槽和一致性hash

哈希槽和一致性hash

- 首先,从使用 hash 取模数据分片开始说起 先从经典的 hash 取模数据分片说起 经典哈希取模分片的问题和对策: -** 一致性 hash 算法** 第一阶段,需要完成 key 到 slot 槽位之间的映射 第二阶段,需要完成 slot 槽位到 Redis node 节点之间的映射。 Hash 槽位环 一致性哈希原理: 经典场景 1:Key 入环 经典场景 2:新增 Redis 节点 经典场景 3:删除 Redis 节点 -** 经典哈希取模与一致性 hash 的对比:** -** 一致性 hash 的数据不平衡(数据倾斜)问题** 什么是 虚拟节点? 一致性 hash 的简易实现 回顾下一致性 Hash 算法 -** Redis 为什么使用哈希槽而不用一致性哈希** -** Redis Cluster 集群核心特点一:去中心化** 先看分布式集群的设计中的核心:元数据存储 设计。 中心化的 元数据存储架构 去中心化的 元数据存储架构 -** 去中心化场景如何保证元数据一致?** 问题 1:Redis 如何进行数据分片的? Redis cluster 哈希槽 增加节点 减少节点....

记录使用JSON.toString遇到的问题

记录使用JSON.toString遇到的问题

事情的起因是我再自测我自己的需求,开始写单元测试,测试自己的业务代码,其中有个场景我用到了 json,toString()像将实体对象转为 JSON 字符串,但是遇到了问题 我准备了一个 person 实体类,该类有两个字段 id,name private String name; private Integer id; public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Integer getTest() { System.out.println("我执行这个方法了....."); return id + 100; } public void SetTest(Integer id) { System.out.println("id = " + id); } 然后我....

单生产者单消费者模式队列的搭建(三)

单生产者单消费者模式队列的搭建(三)

包装消费者 我要包装消费者的原因很简单,因为之前我为自己的程序引入进度序号 Sequence 时,我说现在消费者有了自己的消费进度,看起来更加立体了,所以想包装它一下。但是现在我想再跟大家提出另一个要包装它的重要原因。这个原因当然也很简单,那就是消费逻辑都是用户自己定义的,这就决定了它的身份比较特殊,不能只是一个简单的线程执行一个任务。当然,最后用户定义的消费者逻辑,或者说消费者任务肯定是要交给线程执行的。但是,从用户提交消费者任务,到线程最终开始执行这个任务之间会发生什么呢?让我来给大家分析一下。 比如说,还是沿用上一章的例子,环形数组中存放的都是一个个 Request 对象,而生产者真正生产的是 Integer 对象。这就意味着消费者最后要消费的就是这个 Integer 对象。比如说消费者的消费逻辑就是得到这个 Integer 对象,然后在控制台输出一句“我消费了第 +Integer+ 个数据了”,如果是这样的话,那么这个消费逻辑是不是就应该定义到一个 Runnable 当中,然后把这个 Runnable 交给一个消费者线程来执行?那么在线程执行这个任务之前,是不是应该知道,这个任....

单生产者单消费者模式队列的搭建(二)

单生产者单消费者模式队列的搭建(二)

大家好,在上一章的结尾,我苦于程序中存在太多的问题,迫切地希望给程序来一个翻天覆地的变革和重构。并且,我还为自己的队列找准了一个切入点,就是把 ArrayBlockingQueue 类中的 count 成员变量去掉。改为直接比较读写指针来判断我的队列是否可读可写。当然,我知道有的朋友可能会说,只是一个简单的 count 成员变量而已,费不着大动干戈,其实只要把 count 定义为 AtomicInteger 类型的,然后让它使用 getAndIncrement 方法自增就行了,用 CAS 方式解决并发问题。这确实是个好办法,但是,我相信我大刀阔斧重构之后的程序会非常完美,所以,我宁愿按照自己的方式来重构程序。 那么,话说回来,为什么我会忽然产生这样一种想法,或者说我的编程思路怎么突然转变了呢?因为我终于意识到,避免并发问题的终极解决方法,也是最简单的方法,就是不让多个线程产生操作数据的交汇,不让它们操作相同的数据。这一点一旦明确了,很快我就发现我之前在 ArrayBlockingQueue 类中定义的 count 成员变量的唯一作用就是用来和容器数组的长度进行判断,然后决定队列目前是否....

单生产者单消费者模式队列的搭建(一)

单生产者单消费者模式队列的搭建(一)

简单回顾 JDK 中的队列体系 **队列是什么,我相信大家都很清楚了。**所谓队列,就是一个线性容器,加上操作容器的一些规则。线程容器就是数组,链表(其实,在我看来链表并不能算作容器,它的每一个节点都是一个对象,用指针连接构成了链表本身。我们可以说链表就是把一些对象或者说一些数据精心设计之后,实现了容器的作用,但不能说链表本身就是一个容器。但这些小概念都无关紧要了)。而操作这个容器的规则就是从数组的一端存入数据,从另一端将数据取出,并且操作的过程中要让这些数据先进先出。 按照上面的规则来实现一个队列,显然非常容易了。请看下面的定义。 数组 + 先进先出 = 队列 链表 + 先进先出 = 队列 其实,在 JDK 中的队列,几乎都是采用了上面两种定义实现的。比如大家最熟悉的 ArrayBlockingQueue 和 LinkedBlockingQueue 队列。这些队列的结构也都很简单,首先,还是定义一个通用的接口 Queue,然后在该接口中定义几个基础方法。请看下面代码块。 public interface Queue<E> extends Collection<E&g....

人民有信仰 民族有希望 国家有力量