Spring 自动装配原理深度解析
Spring 自动装配原理一、基础介绍SpringBoot 的自动装配原理是基于 Spring Framework 的条件化配置和@EnableAutoConfiguration 注解实现的。这种机制允许开发者在项目中引入相关的依赖,SpringBoot 将根据这些依赖自动配置应用程序的上下文和功能。 SpringBoot 定义了一套接口规范,这套规范规定:SpringBoot 在启动时会扫描外部引用 jar 包中的 META-INF/Spring.factories 文件,将文件中配置的类型信息加载到 Spring 容器(此处涉及到 JVM 类加载机制与 Spring 的容器知识),并执行类中定义的各种操作。对于外部 jar 来说,只需要按照 SpringBoot 定义的标准,就能将自己的功能装置进 SpringBoot。 通俗来讲,自动装配就是通过注解或一些简单的配置就可以在 SpringBoot 的帮助下开启和配置各种功能,比如数据库访问、Web 开发。 二、实现原理@EnableAutoConfiguration 核心注解@EnableAutoConfigura...
RocketMQ 其他特性深度解析
RocketMQ 其他特性一、延时 / 定时消息实现延迟消息(Scheduled Message)是指生产者发送的消息 不会立即被消费者消费,而是延迟一定时间后才可被消费。 RocketMQ 延迟消息通过 延迟级别 + 定时投递 实现: 1️⃣ Producer 发送延迟消息时指定 DelayLevel,消息写入 CommitLog 并标记延迟级别 2️⃣ Broker 的定时调度线程扫描延迟消息,检查延迟时间是否到达 3️⃣ 延迟时间到达后,将消息投递到普通队列,Consumer 可正常消费 延迟消息本质上还是普通消息,只是 消费可见性被延迟。RocketMQ 并没有单独的延迟队列,而是通过 定时任务 + 队列偏移控制 实现延迟投递。 二、过滤消息实现支持 Tag过滤(服务器端) 和 SQL92表达式过滤消息属性,消息发送时可设置属性,消费者订阅时使用 Tag 或 SQL 表达式。Broker 优先做服务器端过滤,消费端可做二次过滤。 三、为什么不使用 Kafka?性能与适用场景Kafka在数据吞吐上是远超rocketmq的,但是它的topic很多的情况下,性能又远低...
RocketMQ 死信队列机制深度解析
RocketMQ 死信队列什么是死信队列当一条消息消费失败,RocketMQ就会自动进行消息重试。而如果消息超过最大重试次数,RocketMQ就会认为这个消息有问题。但是此时,RocketMQ不会立刻将这个有问题的消息丢弃,而会将其发送到这个消费者组对应的一种特殊队列:死信队列。 死信队列的特征1. 队列归属 一个死信队列对应一个ConsumGroup,而不是对应某个消费者实例。如果一个ConsumeGroup没有产生死信消息,RocketMQ就不会为其创建相应的死信队列。 2. 消费行为 死信队列中的消息不会再被消费者正常消费。 3. 有效期 死信队列的有效期跟正常消息相同。默认3天,对应broker.conf中的fileReservedTime属性。超过这个最长时间的消息都会被删除,而不管消息是否消费过。 死信消息的处理通常,一条消息进入了死信队列,意味着消息在消费处理的过程中出现了比较严重的错误,并且无法自行恢复。此时,一般需要人工去查看死信队列中的消息,对错误原因进行排查。然后对死信消息进行处理,比如转发到正常的Topic重新进行消费,或者丢弃。
RocketMQ 集群高可用方案深度解析
RocketMQ 集群高可用一、故障型高可用多节点部署以便故障转移如果Broker以一个集群的方式部署,会有一个master节点和多个slave节点,消息需要从Master复制到Slave上。而消息复制的方式分为同步复制和异步复制。 同步复制: 同步复制是等Master和Slave都写入消息成功后才反馈给客户端写入成功的状态,同步复制会增大数据写入的延迟,降低系统的吞吐量。 异步复制: 异步复制是只要master写入消息成功,就反馈给客户端写入成功的状态。然后再异步的将消息复制给Slave节点在异步复制下,系统拥有较低的延迟和较高的吞吐量。但是如果master节点故障,而有些数据没有完成复制,就会造成数据丢失。 RocketMQ 的主从架构中,Master 是消息的写入和读取主节点,而 Slave 主要是复制 Master 消息,用于容灾和故障转移。 二、容量型高可用消息积压处理RocketMQ 消息积压是指 Broker 中待消费消息堆积过多,消费者消费速度跟不上生产者发送速度。 处理方法主要包括: 1️⃣ 监控队列堆积指标,及时发现问题 2️⃣ 对生产者进行流控或延迟发送,缓...
RocketMQ 消息可靠性原理深度解析
RocketMQ 消息可靠原理一、链路上的可靠性保障1. 消息持久化基础介绍分布式队列因为有高可靠性的要求,所以数据要进行持久化存储。 MQ收到一条消息后,需要向生产者返回一个ACK响应,并将消息存储起来。(告诉生产者已经将消息进行存储) MQ Push一条消息给消费者后,等待消费者的ACK响应,需要将消息标记为已消费。如果没有标记为已消费,MQ会不断的尝试往消费者推送这条消息。 MQ需要定期删除一些过期的消息,这样才能保证服务一直可用。 RocketMQ采用直接用磁盘文件来保存消息,而不需要借助MySQL这一类索引工具。rocketmq默认文件–commitLog。 abort文件: 这个文件是RocketMQ用来判断程序是否正常关闭的一个标识文件。正常情况下,会在启动时创建,而关闭服务时删除。但是如果遇到一些服务器宕机,或者kill -9这样一些非正常关闭服务的情况,这个abort文件就不会删除,因此RocketMQ就可以判断上一次服务是非正常关闭的,后续就会做一些数据恢复的操作。 CommitLogCommitLog:存储消息的元数据。所有消息都会顺序存入到Commit...
RocketMQ 架构设计深度解析
RocketMQ 架构设计一、基础架构RocketMQ主要由NameServer、Broker、Producer以及Consumer四部分构成。 1. NameServer主要负责对于源数据的管理,包括了对于Topic和路由信息的管理。NameServer是一个功能齐全的服务器,其角色类似Dubbo中的Zookeeper,但NameServer与Zookeeper相比更轻量。主要是因为每个NameServer节点互相之间是独立的,没有任何信息交互。也就是去中心化,NameServer 之间不通信。 2. Producer消息生产者,负责产生消息,一般由业务系统负责产生消息。Producer 由用户进行分布式部署,消息由Producer通过多种负载均衡模式发送到Broker集群路由解耦,发送低延时,支持快速失败。 3. Broker消息中转角色,负责存储消息,转发消息。Broker是具体提供业务的服务器,单个Broker节点与所有的NameServer节点保持长连接及心跳,并会定时将Topic信息注册到NameServer,也就是服务注册,顺带一提底层的通信和连接都是基于Netty...
Redis 其他知识点汇总
Redis 其他知识点一、事务(待补充内容) 二、多线程2.1 多线程 I/O 的引入因为 Redis 的性能瓶颈有时会出现在网络 I/O 的处理上,为了提高网络 I/O 的并行度,采用多个 I/O 线程来处理网络请求。但是对于命令的执行,Redis 仍然使用单线程来处理,引入了多线程 I/O 之后,Redis 的性能至少提升了一倍以上。 2.2 多线程配置不过默认的多线程 I/O 只针对发送响应数据(write client socket),并不会以多线程的方式去处理读请求(read client socket)。 若要开启多线程处理客户端读请求,就需要把 Redis.conf 配置文件中的 io-threads-do-reads 配置项设为 yes,当然还有 IO 多线程个数的配置项。 注意: 主线程也算是一个 I/O 线程。 1io-threads N 2.3 线程模型在 Redis 6.0 版本之后,Redis 在启动的时候,默认会额外创建 4 个 IO 线程。 Redis-server 是 Red...
Redis 缓存应用深度解析
Redis 缓存一、淘汰策略1.1 基本介绍Redis 4.0 之前一共实现了 6 种内存淘汰策略,在 4.0 之后,又增加了 2 种策略。我们可以按照是否会进行数据淘汰把它们分成两类: 不进行数据淘汰的策略:只有 noeviction 这一种 会进行淘汰的 7 种其他策略 会进行淘汰的 7 种策略,我们可以再进一步根据淘汰候选数据集的范围把它们分成两类: 在设置了过期时间的数据中进行淘汰:包括 volatile-random、volatile-ttl、volatile-lru、volatile-lfu(Redis 4.0 后新增)四种 在所有数据范围内进行淘汰:包括 allkeys-lru、allkeys-random、allkeys-lfu(Redis 4.0 后新增)三种 默认情况下,Redis 在使用的内存空间超过 maxmemory 值时,并不会淘汰数据,也就是设定的 noeviction 策略。对应到 Redis 缓存,也就是指,一旦缓存被写满了,再有写请求来时,Redis 不再提供服务,而是直接返回错误。Redis 用作缓存时,实际的数据集通常都是大于缓存容...
Redis 并发控制深度解析
Redis 并发控制一、原子操作为了实现并发控制要求的临界区代码互斥执行,Redis 的原子操作采用了两种方法: 把多个操作在 Redis 中实现成一个操作,也就是单命令操作 把多个操作写到一个 Lua 脚本中,以原子性方式执行单个 Lua 脚本 1.1 单命令操作Redis 是使用单线程来串行处理客户端的请求操作命令的,所以,当 Redis 执行某个命令操作时,其他命令是无法执行的,这相当于命令操作是互斥执行的。当然,Redis 的快照生成、AOF 重写这些操作,可以使用后台线程或者是子进程执行,也就是和主线程的操作并行执行。不过,这些操作只是读取数据,不会修改数据,所以,我们并不需要对它们做并发控制。 虽然 Redis 的单个命令操作可以原子性地执行,但是在实际应用中,数据修改时可能包含多个操作,至少包括读数据、数据增减、写回数据三个操作,这显然就不是单个命令操作了。Redis 提供了 INCR/DECR 命令,把这三个操作转变为一个原子操作。INCR/DECR 命令可以对数据进行增值/减值操作,而且它们本身就是单个命令操作,Redis 在执行它们时,本身就具有...
Redis 持久化策略深度解析
Redis 持久化策略一、AOF(Append Only File)1.1 AOF 的写后日志机制说到日志,我们比较熟悉的是数据库的写前日志(Write Ahead Log, WAL),也就是说,在实际写数据前,先把修改的数据记到日志文件中,以便故障时进行恢复。不过,AOF 日志正好相反,它是写后日志,”写后”的意思是 Redis 是先执行命令,把数据写入内存,然后才记录日志。 1.1.1 为什么采用写后日志为了避免额外的检查开销,Redis 在向 AOF 里面记录日志的时候,并不会先去对这些命令进行语法检查。所以,如果先记日志再执行命令的话,日志中就有可能记录了错误的命令,Redis 在使用日志恢复数据时,就可能会出错。 而写后日志这种方式,就是先让系统执行命令,只有命令能执行成功,才会被记录到日志中,否则,系统就会直接向客户端报错。所以,Redis 使用写后日志这一方式的一大好处是,可以避免出现记录错误命令的情况。 除此之外,AOF 还有一个好处:它是在命令执行后才记录日志,所以不会阻塞当前的写操作。 1.1.2 AOF 的潜在风险AOF 也有两个潜在的风险: 风险一:数据丢...