学习笔记 | 分布式技术

学习笔记 | 分布式技术

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如何写入和读取的?
原文地址:https://www.cnblogs.com/Serenity1994/p/12463640.html