• 学习笔记 | 分布式技术


    学习笔记 | 分布式技术

    1. MQ相关

    1-1. 为啥要使用MQ?

    1. 解耦
      比如说在这个项目中,客户通过我们这个平台下订单买车后,会发短信提示他,这个发短信的动作,如果不使用mq, 要在订单支付成功时去调用发短信的接口,然后才能返回下单成功.如果以后需求改了,不要发短信了,那这时候又要去改动订单这个模块,这个设计的就很耦合.但是如果使用了mq,在下单成功后,只需要向mq发送下单成功的消息就可以了,发送短信啥的可以直接订阅这个下单成功的消息,在获取到下单成功后,调用发送短信. 以后需求更改,也不用去修改订单这个模块.
    2. 异步
      同样,还是下单这个例子,发送短信可能耗时比较长,如果写在下单的逻辑里面的话,下单耗时就会增加,实际上,下单成功不需要关注是否发送短信通知成功.
    3. 削峰
      比方说如果在某个时间点突然有大量用户访问你这个系统,如果不使用mq,这些连接可能就直接去调用业务代码,可能就会导致系统数据量太大,服务宕机,这个时候如果使用mq,用户请求先进mq,业务系统根据自己的能力从mq中获取请求,这样就避免了系统宕机.

    1-2. MQ的优点和缺点

    • 优点就是上面的三个:解耦,异步和削峰
    • 缺点:
      • 系统可用性降低,MQ一旦故障,整个依靠mq的业务都不能使用了
      • 系统复杂性提高了
      • 一致性问题,A系统处理完了发送消息到MQ后就直接返回成功了,用户以为这个请求就成功了,但是问题是,如果其他系统消费该消息后,如果有一个系统出现了问题,导致数据丢失,最后就会发生数据不一致的问题.

    1-3. 各种MQ的比较

    • ActiveMQ
      • 老牌的ActiveMQ,有概率丢失数据.
    • RabbitMQ
      • 管理页面做的非常详细,吞吐量万级,使用erlang开发,看源码有困难.
    • RocketMQ
      • 阿里开源项目,吞吐量10万级别的,topic可以几百到几千个,分布式架构,可以做到消息0丢失.
    • Kafka
      • 支持简单的MQ功能,在大数据领域的实时计算以及日志采集方面被大规模使用.
    • 总结
      中小型公司,技术实力一般,吞吐量也不高,推荐使用RabbitMQ,功能完备,管理后台好用,开源社区活跃,基本遇到问题都能在网上找到答案.
      大型公司,有研究和定制源码的技术,推荐使用RocketMQ,设计的比RabbitMQ好,吞吐量也更高.
      大数据领域,实时计算或者日志采集方面,使用Kafka

    1-4. 如何保证MQ的高可用

    • RabbitMQ的普通集群模式
      • 比方说有三个MQ的实例,其中只有一个实例上保存了queue的实际数据,其他的实例上只保存了queue的元数据(也就是queue的实际位置信息等)
      • 普通集群模式的缺点:
        • 在集群内部产生大量数据传输
        • 可用性不高,保存queue数据的节点宕机了整个系统就不能用了
      • RabbitMQ的镜像集群模式
        • 消息会同步到每一个节点上.
        • 缺点:不是分布式的集群,如果queue中消息很多,一个节点无法容纳.
      • Kafka分布式集群模式
        • 一个topic可以分发到几个不同的MQ节点,也就是一个topic的全部内容由这几个节点中的内容组成.每一个节点又可以设置备份节点,主节点叫做leader节点,备份节点叫做follower节点.leader节点由这几个节点选举产生.只有leader节点向外提供服务,follower节点只是用来备份.当leader节点不可用时,会由follower 节点重新选举出leader节点来提供服务.

    1-5. MQ的重复消费

    • 为啥会出现重复消费
      • Kafka中,消费者按顺序消费消息,并定时更新当前消费完的消息的offset到zookeeper,mq从zookeeper中读取消费者已消费消息的offset,并将之后的消息发送给消费者.如果当消费者消费完消息还没发送到zookeeper时,消费者重启了,这时mq从zookeeper中获取消息的offset是之前的数据,这样就会出现重复消费的情况
    • 重复消费了怎么办
      • 要设计消息消费的幂等性,可以在消息中加入唯一识别字段,每次消费时判断该消息是否已经被消费过.

    1-6. 消息丢失问题

    1. RabbitMQ如何保证数据不丢失
      1. 在写入消息过程中确保数据不丢失,有两种方式,开启事务和回调.
        • 开启事务方式:发送消息时开启事务,如果发送失败可以回滚或者重新发送.这种方式会降低系统的吞吐量
        • 回调的方式:在生产者那里提供回调方法,在消息发送后,会自动调用回调方法,在回调方法中可以设置失败重新发送等处理办法.
      2. 消息的持久化,防止mq意外宕机重启后数据丢失
      3. 消费端关闭autoAck,只有当真正处理完消息,手动发送ack给MQ
    2. Kafka如何保证数据不丢失
      1. 生产者发送消息后,需要确认leader和follower都写入消息才算发送成功,否则会一直重试
      2. 设置每个leader下至少有一个follower在正常工作
      3. 消费者消费成功后才手动返回消费消息的offset

    1-7. 如何保证消息的顺序性

    • RabbitMQ中,一个queue可能对应多个消费者,多个消费者同时从queue中消费数据,就可能出现消息的顺序性问题.
      • 解决方案:enter description here
    • Kafka中,可以把相同key的消息发送到同一个partition中,保证消息在mq中的有序性,但是消费者可能会使用多个线程来并发处理消息,这样也可能会出现消息的顺序性问题.
      • 解决方案:enter description here

    1-8. 消息队列中积压了大量数据怎么办

    • enter description here
    • enter description here

    1-9. 如果让你设计一个消息队列,你会怎么做

    • 保证消息队列的可扩容性,分布式架构,一个topic可以分发到不同的partition中,
    • 消息的持久化保存,这样mq故障恢复不会丢失数据
    • 保证mq的高可用性,可采用多副本机制,即一个leader多个follower,leader向follower同步数据,如果leader挂了,从follower中重新选举出leader
    • 保证mq的数据0丢失,在生产者端可以设计成消息发送后必须等到所有的leader和follower都写入这条消息后才算发送成功,否则就重新发送.

    2. Redis

    2-1. 项目中如何使用缓存的?

    2-2. 为什么要使用缓存

    • 高性能,
    • 高并发

    2-3. redis的线程模型

    • redis是单线程的
    • 采用IO多路复用模式,一个线程去轮询所有连接,并将轮询到的事件压入队列,由文件事件分派器从队列中去读事件并相应处理.

    2-4. redis的单线程为啥还能这么快?

    • redis的操作都是基于内存的
    • redis的请求是非阻塞的,采用IO多路复用器模式,轮询所有连接,并将事件压入队列,由文件事件分派器从队列中读取事件并处理.

    2-5. redis有哪些数据类型,分别在哪些场景下使用

    • string,用来做kv缓存
    • hash,用来保存简单的对象
    • list,有序列表,可以用来保存文章评论信息之类,支持分页查询
    • set
    • sorted set

    2-6. redis的过期策略有哪些,内存满了之后怎么办.

    • 过期策略:redis中,数据过期后并不是直接就被删除了,redis中采用定期删除+惰性删除策略
      1. 定期删除:redis每隔一段时间就会去检查数据库,删除其中过期的key,并不是删除所有的过期的key,而是随机删除一部分(因为如果数据量大,遍历数据库所有过期的key消耗过大
      2. 惰性删除:每次查询key的数据时,先检查该key对应的数据有没有过期,如果过期就删除掉,返回null

    2-7. redis内存满了怎么办

    1. 增加内存
    2. 设置redis的内存淘汰策略
      • redis配置文件中的maxmemory可以设置最大内存
      • maxmemory-policy可以设置当redis达到最大内存后的策略
        1. volatile-lru 使用lru算法删除一个最少使用的过期的键
        2. allkeys-lru 使用lru算法删除一个键 (建议使用这个,因为可能没有过期时间的键太多)
        3. volatile-random 随机删除一个过期键
        4. allkeys-random 随机删除一个键
        5. volatile-ttl 删除一个最近即将过期的键
        6. noenviction 不删除,只返回错误(这个是默认的策略)
    3. 使用redis集群

    2-8. redis的主从架构

    • 概述: 一个master对应多个slave节点. master节点会将数据同步给它的所有slave节点.
    • slave节点启动及同步数据过程
      • 当slave节点启动时,它会发送一个psync命令给master节点,
      • 如果slave是第一次连接master,就会触发master的full resynchronization.master会启动一个后台线程,生成当前数据库的RDB快照文件,然后将这个RDB发送给slave节点.slave会先将这个RDB写入本地磁盘,然后再从本地磁盘加载到内存中.
      • 如果这个slave节点是重新连接master节点,那么master节点就会增量复制slave缺少的数据.
    • 主从复制的断点续传
      • 从redis2.8开始,就支持主从复制的断点续传.如果主从复制过程中,网络连接断掉了,那么重新连接后,可以接着上次复制的地方继续复制下去,而不是从头开始复制一份.
      • master节点会在内存中存一个backlog,保存了每个slave节点已经同步的数据的 replica offset.如果网络断线重新连接后,slave会让master从上次的replica offset位置开始继续复制.如果没有找到对应的offset,那么就会执行一个full resynchronization.
    • 无磁盘化复制
      • master在内存中直接创建RDB,然后发送给slave,不会在本地磁盘创建.
      • repl-diskless-sync
    • 过期key处理
      • slave不会过期key,maste过期或者通过lru淘汰了一个key时,会把slave中的这个key给删除掉.

    2-9. redis如何做到高可用性?

    • redis采用主从架构,一个master节点可以有多个slave节点,master节点可以提供写数据服务,master会把数据向它的slave节点同步数据,slave节点只提供读服务.当master节点出现故障,redis会自动检测,并将某个slave节点自动切换为master,这个过程叫做主备切换.这样就保证了redis的高可用性.
    • master节点是否可用是通过哨兵来检测的,同时主备切换过程也是通过哨兵来完成的.(哨兵的英文 sentinal)

    2-10. redis的哨兵及哨兵下数据丢失问题

    • 通常会启动三个哨兵进程的集群,用来管理redis的集群.哨兵会监控master集群是否故障,如果有两个或以上哨兵检测到master不可用,这时就会选取一个slave节点,将其设置为master.
    • 这样就会有个问题,如果master中有数据还未同步到slave节点就挂掉了,这时候就会造成数据丢失
    • 还有一种情况,master正常工作,但是哨兵和master之间网络通信出现问题,这时候哨兵以为master挂掉了,重新选举了一个slave作为master,这时候就有两个master节点在工作了,用户数据可能还是会写入到原先的master上,假如过了一段时间,哨兵又可以和原先的master通信了,它会把原先的master作为现有master的一个slave节点,这样的话,原先master中新写入的数据就会丢失了.
    • 为了降低上述两个场景的数据丢失损失,可以设置master节点的最小slave 节点同步时间,也就是说如果有N个节点的连接延时都超过了M秒,那个这个master就会停止接受外来的写请求,需要下面两个配置
      • min-slaves-to-write 3
      • min-slaves-max-lag 10
    • 通过上面两个配置,就表示:假如有大于等于3个从redis的连接延迟大于10秒,那么主redis就不再接受外部的写请求

    2-11. redis的持久化

    • redis支持两种持久化方式:RDB和AOF

    2-12. 分布式搜索引擎(elasticsearch, solr,lucene)

    es基本内容:
    index -> type -> mapping -> document -> field

    1. es分布式架构如何实现的?
    2. es如何写入和读取的?
  • 相关阅读:
    Android 3.0 r1 API中文文档(108) —— ExpandableListAdapter
    Android 3.0 r1 API中文文档(113) ——SlidingDrawer
    Android 3.0 r1 API中文文档(105) —— ViewParent
    Android 中文 API (102)—— CursorAdapter
    Android开发者指南(4) —— Application Fundamentals
    Android开发者指南(1) —— Android Debug Bridge(adb)
    Android中文API(115)——AudioFormat
    Android中文API(116)——TableLayout
    Android开发者指南(3) —— Other Tools
    Android中文API (110) —— CursorTreeAdapter
  • 原文地址:https://www.cnblogs.com/Serenity1994/p/12463640.html
Copyright © 2020-2023  润新知