分布式各组件深入剖析

RabbitMQ篇

分类

1.Hello World(直连):生产者发送消息到消息队列,消费者消费队列中的消息

2.Work(任务模型):让多个消费者绑定到一个队列,共同消费队列中的消息;

默认情况下rabbitmq按顺序将每个消息发送给下一个使用者,平均而言,每个消费者都会收到相同数量的消息,这种分发消息的方式称为循环;因为消息自动确认机制(autoAck : true)导致平均分配消息,这样会导致在消费消息时宕机导致数据丢失,所以关闭自动确认机制(autoAck : false),开启手动确认消息,且设置通道每次只能消费一个消息

3.Fanout(广播) :

        在广播模式下,消息发送流程

  • 可以有多个消费者
  • 每个消费者有自己的queue(队列)
  • 每个队列都要绑定exchange(交换机)【routingKey不需要,因为是群发;type : fanout】
  • 生产者发送的消息只能发送到交换机,交换机来决定发给哪个队列,生产者无法决定
  • 交换机把消息发送给绑定过的所有队列
  • 队列的消费者都能拿到消息,实现一条消息被多个消费者消费

4. Routing(路由):

        在Fanout模式中,一条消息会被所有订阅的队列消费,但是,在某些场景下,我们希望不同的消息被不同的队列消费,这时就要用Direct类型的Exchange

5.Topics(动态路由):

        Topic类型的Exchange与Direct相比,都是可以通过RoutingKey把消息路由到不同的队列。只不过Topic类型的Exchange可以让队列在绑定RoutingKey的时候使用通配符!这种模型RoutingKey一般都是由一个或多个单词组成,多个单词之间用 "," 分割

 

SpringBoot整合MQ使用

1.引入依赖

2.配置配置文件

3.发送/消费

发送

 消费(临时队列)

MQ的应用场景说明

1.异步处理:用户注册时,需要发送注册邮件和短信,串行和并行会导致增加客户等待时间,而引入消息队列后,把发送邮件,短信等不是必须的业务逻辑异步处理,提高了响应返回的时间。

2.应用解耦:双十一购物节,用户下单后,订单系统需要通知库存系统,传统做法是订单系统调用库存接口,但库存系统出现故障时,会导致订单失败。引用消息队列后,用户下单后,订单系统将消息写入消息队列,返回用户下单成功,库存系统订阅下单的消息,获取下单信息,进行库存操作,就算库存系统出现故障,也不会导致订单消息的丢失。

3.流量削峰:秒杀活动时,会因为流量过大导致应用挂掉,加入消息队列,可以控制活动人数,超过指定人数订单直接丢弃,同时,可以缓解段时间的高流量压垮应用。

集群架构

1.普通集群

        其他节点无法复制主节点消息队列,使用其他节点时会通过主节点去查询消息队列,但主节点宕机后,其他节点无法使用...

 2.镜像集群

发布消息确认和消费消息确认

发布消息确认

RabbitMQ有两种方式来解决这个问题:

  1. 通过AMQP提供的事务机制实现;
  2. 使用发送者确认模式实现;

1.事务的实现主要是对信道(Channel)的设置,主要的方法有三个:

  1. channel.txSelect()声明启动事务模式;
  2. channel.txComment()提交事务;
  3. channel.txRollback()回滚事务;

2.Confirm的三种实现方式:

  1. channel.waitForConfirms()普通发送方确认模式;发送消息之前只需要通过 channel开启发送方确认模式,等到消息发送完之后,可以调用channel.waitForConfirms()来确认消息是否发送成功,如果返回true则表示消息成功发送,如果返回false,则表示消息发送失败;
  2. channel.waitForConfirmsOrDie()批量确认模式;使用同步方式等所有的消息发送之后才会执行后面代码,只要有一个消息未被确认就会抛出IOException异常,所以可以在程序里面捕获异常,当有异常抛出时,就表示消息发送失败,然后可以处理对应逻辑。
  3. channel.addConfirmListener()异步监听发送方确认模式;异步模式的优点,就是执行效率高,不需要等待消息执行完,只需要监听消息即可,当消息发送成功时,回调handleAck()方法,当消息发送失败的时候,回调handleNack()方法,可以在失败的回调方法里面写相关的处理逻辑。
消费消息确认 

 RabbitMQ有一个ACK机制。当消费者获取消息后,会向RabbitMQ发送回执ACK,告知消息已经被接收。不过这种回执ACK分两种情况:

  • 自动ACK:消息一旦被接收,消费者自动发送ACK(默认)

  • 手动ACK:消息接收后,不会发送ACK,需要手动调用

redis篇

介绍

redis是可基于内存也可持久化的Key-Value数据库,其中value支持五种数据类型:

持久化

RDB:将内存中数据以快照的方式写入到二进制文件中,由于快照方式是在一定间隔时间做一次的,所以如果 redis 意外当机的话,就会丢失最后一次快照后的所有数据修改;

AOF:将每一个收到的写命令都通过 write 函数追加到文件中,当redis重启时会通过重新执行文件中保存的写命令来在内存中重建整个数据库的内容

Redis过期策略

  • 定时过期:每个设置过期时间的key都需要创建一个定时器,到过期时间就会立即清除。该策略可以立即清除过期的数据,对内存很友好;但是会占用大量的CPU资源去处理过期的数据,从而影响缓存的响应时间和吞吐量。
  • 惰性过期:只有当访问一个key时,才会判断该key是否已过期,过期则清除。该策略可以最大化地节省CPU资源,却对内存非常不友好。极端情况可能出现大量的过期key没有再次被访问,从而不会被清除,占用大量内存。
  • 定期过期:每隔一定的时间,会扫描一定数量的数据库的expires字典中一定数量的key,并清除其中已过期的key。该策略是前两者的一个折中方案。通过调整定时扫描的时间间隔和每次扫描的限定耗时,可以在不同情况下使得CPU和内存资源达到最优的平衡效果。 (expires字典会保存所有设置了过期时间的key的过期时间数据,其中,key是指向键空间中的某个键的指针,value是该键的毫秒精度的UNIX时间戳表示的过期时间。键空间是指该Redis集群中保存的所有键。)Redis中同时使用了惰性过期和定期过期两种过期策略。

Redis应用场景

一.订单超时自动取消

1.使用redis过期特性

        下单时,订单状态是待支付。将订单编号作为key,下单的时间戳作为value,设置过期时间是30分钟。服务器监听redis的key过期事件,如果是订单过期(还会有其他key过期),则修改订单的状态为已取消。当30分钟后未支付则触发redis过期事件,只需修改订单状态即可。若30分钟内支付成功,则需要删除此订单在redis的值。当然,在支付时,需要检查订单是否已超时或已支付。

注意:由于存在多个键的过期,故必须对键进行判断,是否是订单超时造成的过期。

2.使用RabbitMQ的过期队列

        RabbitMQ本身不支持延迟队列,可以使用存活时间ttl + 死信队列dlx实现消息延迟。发送的消息设置ttl,所在的队列不设置消费者。队列绑定死信队列,消息超时之后,变成死信消息,再发送给死信队列,最后发送给消费者。发送多条不同延迟时间消息,前面消息没有到延迟时间,会阻塞后面延迟更低的消息,因为队列有先进先出的特性。RabbitMQ的x-delay-message插件可以解决消息时序问题。带有ttl的消息发送x-delayed-message类型的交换机,消息不会直接路由到队列中。而且存储到分布式数据系统中,该系统会检测消息延迟时间。消息到达延迟时间,消息才能会投递到队列中,最后发送给消费者。

二.会话缓存

        添加注解 @EnableRedisHttpSession,设置 Session 失效时间,当用户在系统A上登陆以后,假如后续的一些操作被负载均衡到系统B上面,避免用户重新登陆。

三.消息队列 (发布/订阅功能)

        List 是一个双向链表,可以通过 lpush 和 rpop 写入和读取消息。不过最好使用RabbitMQ 等消息中间件。

四.分布式锁实现 (Redis提供了setXX指令来实现分布式锁)

  1. setnx key value提供的分布式锁;【存在问题:线程还没释放锁系统宕机了,造成死锁】
  2. setnx + setex:给锁设置过期时间,到期自动删除;【存在问题:因为加锁和过期时间设置非原子,存在设置超时时间失败情况,导致死锁】
  3. set(key,value,nx,px):将setnx+setex变成原子操作,利用Redisson可解决任务超时,锁自动释放问题。其通过开启另一个服务,后台进程定时检查持有锁的线程是否继续持有锁,如是将锁声明周期通过重置延长,防止线程释放锁之前过期,只要线程一加锁成功,就会启动一个watch dog看门狗,它是一个后台线程,会每隔10秒检查一下(锁续命周期就是设置的超时时间的三分之一),如果线程还持有锁,就会不断的延长锁key的生存时间。当业务执行完,释放锁后,再关闭守护线程
  4. redis集群解决方案使用redlock解决;【顺序向5个节点请求加锁(5个节点相互独立,没任何关系)根据超时时间来判断是否要跳过该节点,如果大于等于3节点加锁成功,并且使用时间小于锁有效期,则加锁成功,否则获取锁失败,解锁】

五.排行榜(ZSET)

  1. zadd key score member   添加分数、成员到键;【zadd rank 1000 Tom  汤姆的分数是1000分,把这个信息添加(或更新Tom的分数)到redis的rank键下】
  2. zrem key member  移除某个成员;【zrem  rank Tom 从排行榜中移除掉汤姆这个人】
  3. zcard key  返回有序集合key的成员数;【zcard rank 看看排行榜有多少人】
  4. zscore key member  返回成员的分数;【zscore rank Tom  看看汤姆多少分】
  5. zrevrange key start stop  返回范围内成员;【zrevrange rank 0 9  返回分数最高的前十名】
  6. zrank key start stop  返回范围内成员;【zrank rank 0 9  返回分数最低的前十名】

Redis缓存

一.缓存穿透

1.概念

        key 对应的数据在redis中并不存在,每次针对此 key的请求从缓存获取不到,请求转发到数据库,访问量大了可能压垮数据库。比如用一个不存在的用户 id 获取用户信息。

2.解决方案

  • key null: 如果查询返回的数据为空,将这个空结果(null)进行缓存,然后设置空结果的过期时间。(只能作为简单的应急方案)
  • 设置可访问的名单(白名单):使用 bitmaps 类型定义一个可以访问的名单,名单 id 作为 bitmaps 的偏移量,每次访问和 bitmap 里面的 id 进行比较,如果访问 id 不在 bitmaps 里面,进行拦截,不允许访问。
  • 布隆过滤器:使用一组哈希函数,将元素映射成一组位数组中的索引位置。当要检查一个元素是否在集合中时,将该元素进行哈希处理,然后查看哈希值对应的位数组的值是否为1。如果哈希值对应的位数组的值都为1,那么这个元素可能在集合中,否则这个元素肯定不在集合中

二.缓存击穿

1.概念

        redis中的某个热门的key过期了,而此时客户端对这个key的访问量激增,redis无法命中,这些访问就会转发到数据库,造成数据库瞬间压力过大,

2.解决方案

  • 预先设置热门数据: 在 redis 高峰访问之前,把一些热门数据提前存入到redis 里面,加大这些热门数据 key 的时长;
  • 实时调整:现场监控哪些数据热门,实时调整 key 的过期时长;
  • 使用锁:

三.缓存雪崩

1.概念

        缓存雪崩针对很多 key 失效导致redis无法命中,数据库压力激增。

2.解决方案

  • 构建多级缓存架构: nginx 缓存 + redis 缓存 +其他缓存(ehcache 等),程序设计较为复杂
  • 使用锁或队列: 用加锁或者队列的方式来保证不会有大量的线程对数据库一次性进行读写,从而避免失效时大量的并发请求落到底层存储系统上。效率低,不适用高并发情况
  • 设置过期标志更新缓存: 记录缓存数据是否过期(设置提前量),如果过期会触发通知另外的线程在后台去更新实际 key 的缓存
  • 将缓存失效时间分散开: 比如我们可以在原有的失效时间基础上增加一个随机值,比如 1-5 分钟随机,这样每一个缓存的过期时间的重复率就会降低,就很难引发集体失效的事件

Redis数据一致性

        一致性是指系统中各节点数据保持一致。分布式系统中,可以理解为多个节点中的数据是一致的。一致性根据严苛程度分类:

  • 强一致性:写进去的数据是什么,读出来的数据就是什么,对性能影响最大;
  • 弱一致性:数据写入成功后,系统不保证能立刻读出最新的数据,也不承诺多久之后数据可以达到一致,但保证到某个时间级别后,数据能达到一致;

最终一致性:最终一致性是弱一致性的一个特例,最终一致性同样只保证数据写入成功后,在某个时间点后数据会达到一致。这个系统无法保证强一致性的时间片段被称为不一致窗口。不一致时间窗口的时间长短取决于很多因素,比如副本个数、网络延迟、系统负载等。最终一致性是弱一致性中非常受大众推崇的一种一致性模型,也是目前业界在大型分布式系统的数据一致性上比较推崇的模型。为保证缓存数据与数据库数据一致,主要考虑如下两种策略实现:

1.先删除缓存,再更新数据库;(可能存在A线程更新数据库失败导致B线程查询数据库读取到脏数据)

        通过失败重试 + 延时双删,加入更新失败重试机制,降低数据不一致可能性;同时再更新成功后,延迟一段时间,再次删除缓存。

先更新数据库,再删除缓存;(可能存在A线程删除缓存失败导致B线程查询缓存读取到旧数据)

        引入消息队列,若Redis删除缓存失败,则将Redis key放入消息队列,消费端监听消息队列并删除Redis直至删除成功。

需要注意的是上述描述的解决方案也只能保证最终数据一致性,无法保证强一致性。

ElasticSearch篇

ElasticSearch入门

        开源的ElasticSearch是目前全文搜索引擎的首选。它可以快速地储存、搜索和分析海量数据。ES本质上是一个分布式数据库,允许多台服务器协同工作,每台服务器可以运行多个 ES实例。单个 ES实例称为一个节点(node)。

Elasticsearch 能做什么?

  • 应用搜索,比如我们常见的 github,抖音,音乐,视频,电信 app 里的搜索
  • 网站搜索
  • 企业搜索
  • 日志记录和日志分析
  • 基础设施指标和容器监控
  • 应用性能监控
  • 地理空间数据分析和可视化
  • 安全分析
  • 商业分析

XXL-JOB篇

介绍

        XXL-JOB是一个分布式任务调度平台, 平台架构分为调度器和执行器(就是你的业务程序), 调度器一般是一个单独的服务。

数据库初始化

 原理分析

系统组成

  • 调度中心:维护执行器(节点注册及注销),维护调度任务,发起调度及重试,失败告警,统计执行信息,人员及权限管理
  • 执行器:向调度中心注册,根据调度请求执行任务,记录执行日志,返回调度及执行结果
  • MySQL:保存所有任务信息、调度记录等重要信息
  • 文件系统:保存任务执行日志及回调失败日志

Nacos

Nacos是什么

        是一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台,帮助我们发现、配置和管理微服务。

Nacos实现服务注册与发现流程

        server向nacos发起注册任务请求,并维持一个心跳检测的定时任务,naocs会通过阻塞队列异步地处理这些请求,并实时的通过UDP推送到client,为防止UDP数据丢失,client也会通过定时任务每隔10s向nacos发送拉取请求,当服务列表改变,nacos再返回。

Nacos配置共享

Nacos配置管理——配置共享_nacos 共享配置_杨 戬的博客-CSDN博客

CAP理论

Seata入门系列(27)-分布式事务之CAP、BASE理论_seata cap_云烟成雨TD的博客-CSDN博客

java 面试备战---分布式那点事

nacos 和erueka 的区别

  • CAP理论区别【eureka只支持AP,nacos支持CP和AP两种】
  • 连接方式【nacs使用的是netty和服务直接进行连接,属于长连接;eureka是使用定时发送和服务进行联系,属于短连接】
  • 服务异常剔除【Eureka-client在默认情况每隔30s向Server发送一次心跳,当Server在默认连续90s秒的情况下没有收到心跳, 会把client从注册表中剔除,在由Server60秒的清除间隔,把client给下线;nacos-client 通过心跳上报方式告诉 nacos注册中心健康状态,默认心跳间隔5秒,nacos会在超过15秒未收到心跳后将实例设置为不健康状态,可以正常接收到请求超过30秒nacos将实例删除,不会再接收请求】
  • 操作实例方式【nacos-提供了nacos console可视化控制话界面,可以对实例列表进行监听,对实例进行上下线,权重的配置,并且config server提供了对服务实例提供配置中心,且可以对配置进行CRUD,版本管理;eureka-仅提供了实例列表,实例的状态,错误信息,相比于nacos过于简单】

Docker容器

什么是Docker

Docker容器_后端阿一的博客-CSDN博客

vue

组件传值

1.父组件传给子组件

        在子组件里定义一个props获取父组件的值,即props:[‘msg’]。

2.子组件传给父组件

       使用自定义事件,在子组件中使用this.$emit(‘myEvent’) 触发,然后在父组件中使用@myEvent监听

3.兄弟组件间传值

        定义一个公共的事件总线eventBus,通过它作为中间桥梁,我们就可以传值给任意组件了。通过eventBus.$emit('事件名', 参数)发送消息,通过eventBus.$on('事件名', (参数) => {})监听消息

4.父组件访问子组件的方法和属性

        通过 ref= 的能力,给子组件定义一个ID,父组件通过这个ID可以直接访问子组件里面的方法和属性( this.$refs )

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值