数据总线(Data Bus)模式

提出问题

前些天面试的时候被问起redis集群的问题,问及Redis集群中如何实现高可用,答曰每个节点都有Master和Slave,当Master挂了之后,Slave会升级为Master;又问其他节点(整个集群)如何知道Slave升级Master, 于是我发现之前看文档的时候这个点漏了,没有注意。

分析问题

Redis哨兵模式中哨兵节点起着监控和管理整个集群的作用,可以对节点进行主从切换。而集群模式中这个功能是怎么实现的呢,也是通过额外的类似哨兵节点或者管理节点?这样整个集群更复杂了,风险点也增加了(还要解决哨兵、管理节点的高可用等问题)。

寻找答案

于是查找Redis官方文档: https://redis.io/topics/cluster-spec
里面有一段正好解释了面试中提的问题:

In Redis Cluster nodes are responsible for holding the data, and taking the state of the cluster, including mapping keys to the right nodes. Cluster nodes are also able to auto-discover other nodes, detect non-working nodes, and promote slave nodes to master when needed in order to continue to operate when a failure occurs.
To perform their tasks all the cluster nodes are connected using a TCP bus and a binary protocol, called the Redis Cluster Bus. Every node is connected to every other node in the cluster using the cluster bus. Nodes use a gossip protocol to propagate information about the cluster in order to discover new nodes, to send ping packets to make sure all the other nodes are working properly, and to send cluster messages needed to signal specific conditions. The cluster bus is also used in order to propagate Pub/Sub messages across the cluster and to orchestrate manual failovers when requested by users (manual failovers are failovers which are not initiated by the Redis Cluster failure detector, but by the system administrator directly).

以上说的是Redis集群通过TCP连接的数据总线(Redis Cluster Bus)来进行集群的管理。功能如下:

  • 保存数据,获取集群的状态,如:将keys映射到正确的节点
  • 自动发现其他节点,探测不工作的节点以及当错误发生时将Slave升级为Master
  • 传播 发布/订阅 消息
  • 人为的故障转移处理

理解数据总线

在很多架构设计中都能看到数据总线的身影,它是一种很重要的设计模式:Data Bus
我把里面的图贴出来:

数据总线(Data Bus)模式_第1张图片
data-bus.urm.png

这个图很清晰的描述了 Data Bus模式的主要元素和他们之前的关系,它分了三部分:

数据对象(事件类型 dataType)

数据对象的抽象类中需要设置数据总线对象,即每个消息/事件都要知道它所要传输的数据总线对象,这样当一个消息/事件被发送的时候就可以使用它的数据总线进行消息的发布操作。
示例代码:

public class MessageData implements DataType{

    private DataBus dataBus;
   
  // ...
  
    public void send() {
        dataBus.publish(this);
    }

}

数据总线类

支持的动作:

  • 发布事件/消息
  • 添加成员
  • 删除成员

示例代码

public class DataBus {

    private List members = new ArrayList<>();

    public void publish(DataType data) {
        for (Member member : members) {
            member.handleData(data);
        }

    }

    public void subscribe(Member member) {
        members.add(member);
    }

    public void unSubScribe(Member member) {

        for (Member member1 : members) {
            if (member1.equals(member)) {
                members.remove(member);
            }
        }

    }

    // ...
}

成员(应用中的各个组件, 事件的处理者)

处理被总线发布的消息事件,根据是否支持来进行是否处理和忽略的判断
示例代码

public class CountMember implements Member {

    @Override
    public boolean accept(DataType event) {
        return event instanceof MessageData;
    }

    @Override
    public void handleData(DataType event) {
        
        if (accept(event)) {
            process(event);
        }

    }
    
    public void process(DataType dataType) {
        //...
    }
}

数据总线作为各个组件成员之间进行事件通信的通道,让应用中的各个成员在发送事件消息的时候不用知道其他成员的信息,只需要了解他们发送的消息/事件类型。

什么时候使用

  • 应用组件自己决定需要处理什么消息/事件
  • 多对多事件消息交互
  • 应用组件之间互相不了解或者了解有限

你可能感兴趣的:(数据总线(Data Bus)模式)