WHCSRL 技术网

Java中高级问题整理-中间件

本系列目录

1. Redis

Redis哨兵模式

在这里插入图片描述
Redis的主从复制模式下, 一旦主节点由于故障不能提供服务, 需要人工将从节点设置为主节点, 同时还要通知客户端切换数据源,这就无法达到高可用,哨兵模式就可以解决这一问题。 哨兵是特殊的redis服务,不提供读写服务,主要用来监控redis实例节点。 哨兵架构下client端第一次从哨兵找出redis的主节点,后续就直接访问redis的主节点,不会每次都通过 sentinel代理访问redis的主节点,当redis的主节点发生变化,哨兵会第一时间感知到,并且哨兵会在从节点中重新选出来一个新的master(Redis服务是通过配置文件配置的,此时哨兵会修改主从节点的配置文件),并且将新的master信息通知给client端。这里面redis的client端一般都实现了订阅功能,订阅sentinel发布的节点变动消息。

1. 哨兵模式搭建

  1. 配置Redis的主从服务器,修改redis.conf文件如下
    # 使得Redis服务器可以跨网络访问
    bind 0.0.0.0
    # 设置密码
    requirepass "123456"
    # 指定主服务器,注意:有关slaveof的配置只是配置从服务器,主服务器不需要配置
    slaveof 192.168.11.128 6379
    # 主服务器密码,注意:有关slaveof的配置只是配置从服务器,主服务器不需要配置
    masterauth 123456
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
  2. 配置3个哨兵,每个哨兵的配置都是一样的。在Redis安装目录下有一个sentinel.conf文件,copy一份进行修改
    # 禁止保护模式
    protected-mode no
    # 配置监听的主服务器,这里sentinel monitor代表监控,mymaster代表服务器的名称,可以自定义,192.168.11.128代表监控的主服务器,6379代表端口,2代表只有两个或两个以上的哨兵认为主服务器不可用的时候,才会进行failover操作。
    sentinel monitor mymaster 192.168.11.128 6379 2
    # sentinel author-pass定义服务的密码,mymaster是服务名称,123456是Redis服务器密码
    # sentinel auth-pass <master-name> <password>
    sentinel auth-pass mymaster 123456
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

2. Java中使用哨兵模式

/**
 * 测试Redis哨兵模式
 * @author liu
 */
public class TestSentinels {
    @SuppressWarnings("resource")
    @Test
    public void testSentinel() {
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        jedisPoolConfig.setMaxTotal(10);
        jedisPoolConfig.setMaxIdle(5);
        jedisPoolConfig.setMinIdle(5);
        // 哨兵信息
        Set<String> sentinels = new HashSet<>(Arrays.asList("192.168.11.128:26379",
                "192.168.11.129:26379","192.168.11.130:26379"));
        // 创建连接池
        JedisSentinelPool pool = new JedisSentinelPool("mymaster", sentinels,jedisPoolConfig,"123456");
        // 获取客户端
        Jedis jedis = pool.getResource();
        // 执行两个命令
        jedis.set("mykey", "myvalue");
        String value = jedis.get("mykey");
        System.out.println(value);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

redis使用场景

缓存、排行榜、计数器、分布式会话、分布式锁、社交网络、最新消息、消息系统

你知道redis哪些高级功能?

消息队列、过期删除、事务、数据持久化、分布式锁、附近的人、慢查询分析、Sentinel、集群等

2. RabbitMQ

AMQP messaging 中的基本概念

在这里插入图片描述

  1. Broker: 接收和分发消息的应用,RabbitMQ Server就是Message Broker。
  2. Virtual host: 出于多租户和安全因素设计的,把AMQP的基本组件划分到一个虚拟的分组中,类似于网络中的namespace概念。当多个不同的用户使用同一个RabbitMQ server提供的服务时,可以划分出多个vhost,每个用户在自己的vhost创建exchange/queue等。
  3. Connection: publisher/consumer和broker之间的TCP连接。断开连接的操作只会在client端进行,Broker不会断开连接,除非出现网络故障或broker服务出现问题。
  4. Channel: 如果每一次访问RabbitMQ都建立一个Connection,在消息量大的时候建立TCP Connection的开销将是巨大的,效率也较低。Channel是在connection内部建立的逻辑连接,如果应用程序支持多线程,通常每个thread创建单独的channel进行通讯,AMQP method包含了channel id帮助客户端和message broker识别channel,所以channel之间是完全隔离的。Channel作为轻量级的Connection极大减少了操作系统建立TCP connection的开销。
  5. Exchange: message到达broker的第一站,根据分发规则,匹配查询表中的routing key,分发消息到queue中去。常用的类型有:direct (point-to-point), topic (publish-subscribe) and fanout (multicast)。
  6. Queue: 消息最终被送到这里等待consumer取走。一个message可以被同时拷贝到多个queue中。
  7. Binding: exchange和queue之间的虚拟连接,binding中可以包含routing key。Binding信息被保存到exchange中的查询表中,用于message的分发依据。
    参考:RabbitMQ与AMQP协议详解

RabbitMQ如何实现延时队列

通过TTL(Time To Live)和DLX(Dead-Letter-Exchange)来实现
为消息添加过期时间,时间过期后进入死信队列,然后重新发布消费,这就做到了误差极小的演示队列
参考-优选参考-预备

3. Kafka

kafka中的 zookeeper 起到什么作用

  1. broker在zk中注册
    kafka的每个broker(相当于一个节点,相当于一个机器)在启动时,都会在zk中注册,,当节点失效时,zk就会删除该节点,就很方便的监控整个集群broker的变化,及时调整负载均衡。
  2. topic在zk中注册
    在kafka中可以定义很多个topic,每个topic又被分为很多个分区。一般情况下,每个分区独立在存在一个broker上,所有的这些topic和broker的对应关系都有zk进行维护
  3. consumer(消费者)在zk中注册
    1. 注册新的消费者,当有新的消费者注册到zk中,zk会创建专用的节点来保存相关信息,路径ls /consumers/{group_id}/ [ids,owners,offset]

      Ids:记录该消费分组有几个正在消费的消费者,
      Owmners:记录该消费分组消费的topic信息,
      Offset:记录topic每个分区中的每个offset

    2. 监听消费者分组中消费者的变化

      监听/consumers/{group_id}/ids的子节点的变化,一旦发现消费者新增或者减少及时调整消费者的负载均衡

kafka启动了一个broker,可以设置多个partition吗?可以设置多个副本吗?为什么

可以设置多个partition,但是不能设置多个副本。
设置多个partition是为了可以提高性能,设置多个副本是为了提高可用性,但是只有一个broker设置多个副本是没有意义的,所以kafka也不允许副本数多与broker数

3. Elasticsearch

为什么要使用Elasticsearch?

​   因为在我们商城中的数据,将来会非常多,所以采用以往的模糊查询,模糊查询前置配置,会放弃索引,导致商品查询是全表扫面,在百万级别的数据库中,效率非常低下,而我们使用ES做一个全文索引,我们将经常查询的商品的某些字段,比如说商品名,描述、价格还有id这些字段我们放入我们索引库里,可以提高查询速度。

全文搜索(Full-text Search)

全文检索是指计算机索引程序通过扫描文章中的每一个词,对每一个词建立一个索引,指明该词在文章中出现的次数和位置,当用户查询时,检索程序就根据事先建立的索引进行查找,并将查找的结果反馈给用户的检索方式。

倒排索引(Inverted Index)

与之对应的是普通索引,普通索引是通过单词找到索引再找到文档。倒排索引相反,直接通过单词找到文档列表。
倒排索引组成:

  1. 倒排索引项:记录文档id,单词出现次数,位置信息
  2. 倒排列表:由倒排索引项组成
    在这里插入图片描述
    通过单词就可以找到倒排列表,倒排列表中倒排索引项记录了单词所有的信息

ES基本概念

  1. 索引:Elasticsearch 数据管理的顶层单位就叫做 Index(索引),相当于关系型数据库里的数据库的概念。另外,每个Index的名字必须是小写。
  2. 文档(Document):Index里面单条的记录称为 Document(文档),相当于关系型数据库column。许多条 Document 构成了一个 Index。Document 使用 JSON 格式表示。同一个 Index 里面的 Document,不要求有相同的结构(scheme),但是最好保持相同,这样有利于提高搜索效率。
  3. 类型(Type):Document 可以分组,比如employee这个 Index 里面,可以按部门分组,也可以按职级分组。这种分组就叫做 Type,它是虚拟的逻辑分组,用来过滤 Document,类似关系型数据库中的数据表。
    不同的 Type 应该有相似的结构(Schema),性质完全不同的数据(比如 products 和 logs)应该存成两个 Index,而不是一个 Index 里面的两个 Type(虽然可以做到)。
  4. 文档元数据(Document metadata):文档元数据为_index, _type, _id, 这三者可以唯一表示一个文档,_index表示文档在哪存放,_type表示文档的对象类别,_id为文档的唯一标识。

ES对比Solr

  1. Solr 利用 Zookeeper 进行分布式管理,而 Elasticsearch 自身带有分布式协调管理功能;
  2. Solr 支持更多格式的数据,而 Elasticsearch 仅支持json文件格式;
  3. Solr 官方提供的功能更多,而 Elasticsearch 本身更注重于核心功能,高级功能多有第三方插件提供;
  4. Solr 在传统的搜索应用中表现好于 Elasticsearch,但在处理实时搜索应用时效率明显低于 Elasticsearch。
  5. Solr 是传统搜索应用的有力解决方案,但 Elasticsearch 更适用于新兴的实时搜索应用。
  6. 随着数据量的增加,Solr的搜索效率会变得更低,而Elasticsearch却没有明显的变化。
    参考:Elasticsearch与Solr优缺点比较
推荐阅读