diff --git a/docs/index.md b/docs/index.md
index e7e61ef..15caced 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -30,7 +30,9 @@ hero:
- theme: alt
text: 我的Bilibili
link: https://space.bilibili.com/12764212
+
---
+
+
# 欢迎来到我的博客!
+
感谢大家一直以来的支持和关注!这个博客是基于 [VitePress](https://vitejs.cn/vitepress/) 构建的,旨在提供更高效的内容创作和管理体验。尽管我的旧博客曾承载了许多宝贵的学习记录与分享,但为了追求更好的技术体验,我决定将其迁移至新的平台。
# 为什么选择迁移?
+
随着时间的推移,我希望能在博客上进行更高效的内容创作和管理。虽然 [Hexo](https://hexo.io/zh-cn/) 是一个非常优秀的静态博客框架,提供了快速生成页面和丰富的主题支持,但在持续使用中,我遇到了以下一些问题:
1. 构建速度:随着博客文章的增多,Hexo 的构建速度变慢,尤其是在多次修改和发布时,这影响了我的开发体验
@@ -64,9 +69,9 @@ hero:
因此,我选择将博客迁移到 VitePress,一个以 Vue 3 为基础的现代文档生成器,不仅能更高效地管理内容,还能提升整体性能和可扩展性。
# 访问我的旧博客
+
如果你喜欢我的技术分享,或者希望了解更新、更丰富的内容,欢迎访问我的新博客:
旧博客:[花火の红玉宫](https://01petard.github.io/)
国内访问:[代码港湾](http://www.huangzexiao.top/)
-
diff --git "a/docs/\345\274\200\345\217\221/My Java Guide/My Java Guide - \345\210\206\345\270\203\345\274\217.md" "b/docs/\345\274\200\345\217\221/My Java Guide/My Java Guide - \345\210\206\345\270\203\345\274\217.md"
index 430fac8..3f547c1 100644
--- "a/docs/\345\274\200\345\217\221/My Java Guide/My Java Guide - \345\210\206\345\270\203\345\274\217.md"
+++ "b/docs/\345\274\200\345\217\221/My Java Guide/My Java Guide - \345\210\206\345\270\203\345\274\217.md"
@@ -1725,7 +1725,7 @@ AMQP 消息通常包含以下几个部分:
# Kafka的选择与实践
-基于上述分析,Kafka选择了**拉取模型**作为其核心数据传输机制。这一选择不仅符合大多数消息系统的传统设计,还特别适合于需要处理大量异构消费者的应用场景。通过实现长轮询功能,**Kafka有效地平衡了数据传输的即时性和系统的稳定性,使得即使在网络条件不稳定或消费者处理能力有限的情况下,也能保持高效的数据交换。**此外,Kafka还通过优化数据批处理和调整拉取请求的参数,进一步提高了系统的整体性能。
+基于上述推拉模式的分析,Kafka选择了**拉取模型**作为其核心数据传输机制。这一选择不仅符合大多数消息系统的传统设计,还特别适合于需要处理大量异构消费者的应用场景。通过实现长轮询功能,**Kafka有效地平衡了数据传输的即时性和系统的稳定性,使得即使在网络条件不稳定或消费者处理能力有限的情况下,也能保持高效的数据交换。**此外,Kafka还通过优化数据批处理和调整拉取请求的参数,进一步提高了系统的整体性能。
**Kafka的拉取模型更适合数据处理场景**,因为它允许消费者根据自身处理能力自主控制数据拉取的频率和数量,有效避免了消费者过载和资源浪费。**而在业务场景中,实时性和低延迟要求更高,推送模型能更好地满足这些需求。**
## 推拉结合(Push-Pull)模式
@@ -1846,66 +1846,45 @@ AMQP 消息通常包含以下几个部分:
# 高可用设计
-**RabbitMQ**:
-
-在生产环境下,使用集群来保证高可用性
-
-- 普通集群
+**RabbitMQ 高可用设计**
- - 会在集群的各个节点间共享部分数据,包括:交换机、队列元信息。不包含队列中的消息
- - 当访问集群某节点时,如果队列不在该节点,会从数据所在节点传递到当前节点并返回
- - 队列所在节点宕机,队列中的消息就会丢失
+1. **镜像队列(Mirrored Queues)**:
+ - 在RabbitMQ中,可以通过配置镜像队列来提高系统的可用性和可靠性。当一个队列被配置为镜像队列后,该队列中的所有消息不仅会存储在主节点上,还会复制到指定数量的从节点上。这样即使主节点发生故障,从节点也可以接管消息处理工作,保证服务的连续性。
+2. **高效ACK机制**:
+ - RabbitMQ支持消息确认机制,即消费者处理完一条消息后向RabbitMQ发送ACK确认信号,只有收到ACK后,RabbitMQ才会将该消息从队列中删除。这种机制可以有效避免因消费者故障导致的消息丢失问题。同时,为了提高性能,RabbitMQ还支持批量确认和预取计数等优化手段。
+3. **集群模式**:
+ - 通过构建RabbitMQ集群,可以进一步增强系统的高可用性和伸缩性。集群中的每个节点都可以接收客户端连接,并且队列可以在多个节点之间分布,以实现负载均衡。
-- **镜像集群**(本质是主从模式)
+**Kafka 高可用设计**
- - 交换机、队列、队列中的消息会在各个镜像节点之间同步备份。
- - 创建队列的节点被称为该队列的主节点,备份到的其它节点叫做该队列的镜像节点。
- - 一个队列的主节点可能是另一个队列的镜像节点
- - 所有操作都是主节点完成,然后同步给镜像节点
- - 主宕机后,镜像节点会替代成新的主节点
+1. **Leader-Follower机制(分区备份机制)**:
-- 仲裁队列(优化镜像集群)
+ Kafka中每个分区都有一个Leader副本和多个Follower副本。生产者发送的消息首先会被写入Leader副本,然后同步到所有的Follower副本。消费者只从Leader副本读取消息。如果Leader副本失效,Kafka会自动从现有的Follower副本中选举一个新的Leader。
- - 与镜像队列一样,都是主从模式,支持主从数据同步
- - 使用非常简单,没有复杂的配置
- - 主从同步基于Raft协议,**强一致性**
- - 代码实现:
+ 一个topic有多个分区,每个分区有多个副本,其中有一个leader,其余的是follower,副本存储在不同的broker中
- ```java
- @Bean
- public Queue quorumQueue() {
- return QueueBuilder
- .durable("quorum.queue") // 持久化
- .quorum() // 仲裁队列
- .build();
- }
- ```
-
-**Kafka**:
+ 所有的分区副本的内容是都是相同的,如果leader发生故障时,会自动将其中一个follower提升为leader
-- 集群模式
+
- - Kafka 的服务器端由被称为 Broker 的服务进程构成,即一个 Kafka 集群由多个 Broker 组成
- - 如果集群中某一台机器宕机,其他机器上的 Broker 也依然能够对外提供服务。这其实就是 Kafka 提供高可用的手段之一
+2. **ISR(In-Sync Replicas)同步机制(分区副本复制机制)**:
-
+ ISR是指与Leader副本保持同步的所有副本集合。当Follower副本与Leader副本之间的延迟超过一定阈值时,该Follower副本将从ISR中移除。只有ISR中的副本才有资格被选为新的Leader,这确保了副本间的数据一致性。
+ ISR(in-sync replica)分区是Leader分区**同步复制**保存的一个队列,普通分区是Leader分区**异步复制**保存的一个队列。
-- **分区备份机制**
+ 如果leader失效后,需要选出新的leader,选举的原则如下:
- - 一个topic有多个分区,每个分区有多个副本,其中有一个leader,其余的是follower,副本存储在不同的broker中
- - 所有的分区副本的内容是都是相同的,如果leader发生故障时,会自动将其中一个follower提升为leader
+ - 第一:选举时优先从ISR中选定,因为这个列表中follower的数据是与leader同步的
+ - 第二:如果ISR列表中的follower都不行了,就只能从其他follower中选取
-
+
-- **分区副本复制机制**
+3. **多副本策略**:
- - ISR(in-sync replica)分区是Leader分区**同步**复制保存的一个队列,普通分区是Leader分区**异步**复制保存的一个队列
- - 如果leader失效后,需要选出新的leader,选举的原则如下:
- - 第一:选举时优先从ISR中选定,因为这个列表中follower的数据是与leader同步的
- - 第二:如果ISR列表中的follower都不行了,就只能从其他follower中选取
+ Kafka允许为每个分区配置多个副本,这些副本分布在不同的Broker上。这样即使某个Broker出现故障,也不会影响整个集群的服务能力。此外,合理的副本分配策略还可以提高数据的安全性和系统的容错性。
-
+
# 保证消息不丢失
diff --git "a/docs/\345\274\200\345\217\221/My Java Guide/My Java Guide - \346\225\260\346\215\256\345\272\223.md" "b/docs/\345\274\200\345\217\221/My Java Guide/My Java Guide - \346\225\260\346\215\256\345\272\223.md"
index 72abfc3..fbbbc5e 100644
--- "a/docs/\345\274\200\345\217\221/My Java Guide/My Java Guide - \346\225\260\346\215\256\345\272\223.md"
+++ "b/docs/\345\274\200\345\217\221/My Java Guide/My Java Guide - \346\225\260\346\215\256\345\272\223.md"
@@ -932,6 +932,168 @@ ReadView是一个事务在开始时可见的数据快照。每当一个事务启
| max_trx_id | 预分配的事务ID,当前最大事务ID+1 |
| creator_trx_id | ReadView创建者的事务ID |
+# 数据库日志四剑客(redo、undo、bin、relay)
+
+## 总结
+
+| 类别 | Undo log | Redo log | binlog |
+| :------: | :-----------------------------------------------------: | :------------------------------------------: | :---------------------------------------------: |
+| 日志归属 | InnoDB引擎中的日志 | InnoDB引擎中的日志 | Server层实现,所有的引擎都可以使用 |
+| 日志类型 | 逻辑日志,记录事务操作的变化,数据修改前的信息 | 物理日志,记录在哪个数据页上进行更新后的信息 | 逻辑日志,记录原始的SQL语句或数据变更的前后内容 |
+| 写入方式 | 顺序写入磁盘 | 循环写,全部写满就从头开始 | 追加写,写满则创建一个新文件继续写 |
+| 适用场景 | 事务回滚和恢复原来数据,实现了事务中的原子性 | 掉电等崩溃恢复,实现了事务中的持久性 | 数据备份和主从复制 |
+| 写入时机 | 事务没提交之前,MySQL会先记录更新前的数据到undo log日志 | 更新内存记录时,会把修改记录在redo log | 事务提交的时候在Server层写入binlog |
+| 日志文件 | 表空间中ibdata共享表数据文件 | ib_logfile0和ib_logfile1 | mysql-bin.000001 bin-log日志文件 |
+
+## Undo Log
+
+UndoLog是数据库引擎层生成的一种回滚日志,主要用于确保事务的ACID特性中的原子性。它记录的是逻辑操作,即数据在被修改之前的状态。这些逻辑操作包括插入(INSERT)、删除(DELETE)和更新(UPDATE)。
+
+**主要功能**
+
+1. 事务回滚:当事务需要回滚时,通过执行undolog中记录的逆向操作来恢复到事务开始前的数据状态。
+2. 多版本并发控制(MVcC):结合ReadView机制,利用undoIog实现多版本并发控制,从而支持高并发读写操作。
+
+**记录内容**
+
+- INSERT操作:在undolog中记录新插入记录的主键ID。如果事务需要回滚,则根据该主键ID删除对应的记录。
+- UPDATE操作:对于每次更新操作,会记录一条与之相反的undolog条目。例如,如果原始操作是将某个字段从A更新为B,则undolog将记录一个从B更新回A的操作。这样,在事务回滚时可以通过执行这些逆向更新来恢复原值。
+- DELETE操作:在执行删除之前,undolog会保存即将被删除的数据副本。如果发生回滚,则重新插入这些已删除的数据。
+
+通过上述机制,即使在事务处理过程中出现错误,也可以确保数据库能够恢复至一致且正确的状态。
+
+
+
+### 事务回滚
+
+每条记录在进行更新操作时,所产生的undo日志均包含一个`trx_id`事务标识符和`roll_pointer`指针。其中:
+
+- `trx_id`用于识别对特定记录执行修改操作的具体事务;
+- `roll_pointer`则允许将一系列相关的undo日志链接起来形成所谓的“版本链”。
+
+当某一事务需要回滚时,并非通过逆向执行SQL语句来恢复数据状态,而是依据该事务中由`roll_pointer`指向的undo日志条目来进行数据复原。
+
+对于新增的数据项,系统会创建一条对应的insert undolog,同时设置该数据项的回滚指针指向这条新生成的日志。此外,undo日志还会详细记载如日志序列号、主键字段及其值等信息。
+
+多版本并发控制(MVCC)机制依赖于ReadView与undo日志共同作用实现。undo日志为数据库中的每一行记录保存了多个历史版本的状态信息。当MySQL处理快照读请求(例如普通SELECT查询)时,它会利用当前事务的ReadView中存储的信息,沿着undo日志构建的版本链条查找并返回符合可见性要求的历史版本记录。
+
+
+
+## Redo Log
+
+在lnnoDB中,RedoLog记录的是物理日志,即对特定数据页所进行的具体修改。那么,为何称其为“大部分”是物理日志呢?这主要是因为RedoLog系统由两大部分构成:
+
+- 一是位于内存中的重做日志缓冲区(RedoLogbuffer),这部分信息容易因断电等原因丢失;
+- 二是保存于磁盘上的重做日志文件(RedoLogfile),提供持久化存储。
+
+**引入RedoLog的必要性**
+
+尽管bufferpool确实极大地提升了数据库操作的性能,但由于其基于内存的特点,存在着固有的不稳定性,一旦遇到如电力中断等意外情况,未及时写入磁盘的数据(脏页)可能会永久丢失。正是为了解决这一问题,RedoLog机制被设计出来。通过与bufferpool及changebuffer协同工作,RedoLog负责记录所有尚未同步至磁盘的更改操作,确保即使发生故障重启后也能恢复这些更新,直至相关页面最终被安全地写入磁盘为止。这样做的目的是为了实现【数据持久化】,保障事务处理过程中的持久性特征不受影响。
+
+- 缓冲池(bufferpool)的主要功能在于缓存来自磁盘的数据页,以此减少频繁访问磁盘造成的l/O开销。
+- 变更缓冲(changebuffer)则用于暂时存放那些尚未加载到缓冲池中的待更新数据项,直到需要时才将其读入并执行相应的更新动作,之后再由后台进程异步刷新至磁盘上。
+
+**Redo Log与Undo Log之间的差异**
+
+从上述讨论中可以清晰地看出RedoLog与undolog之间存在显著区别:
+
+- **Redo Log**专注于记录事务完成后的新状态,即变更后的值;
+- **Undo Log**则用来追踪事务开始前的原始状态,保存的是变更前的旧值。
+
+### 写入过程
+
+
+
+
+
+**关于默认配置的原因**
+
+MySQl采用双文件形式(`ib_logfile0`与`ib_1ogfile1`)来构成一个循环式的日志系统,这种设计有利于实现高效的日志管理。这两个文件共同形成一个“环形”结构,允许MySQL在它们之间交替写入新的日志条目。此机制如下图所示:
+
+
+
+InnoDB采用双RedoLog文件的设计,默认命名为`ib_logfile0`和`ib_logfile1`。这些文件的大小是固定的,并且可以通过在配置文件(如`my.cnf`或`my.ini`)中设置`innodb_log_file_size`参数来进行调整。
+
+**循环写入策略:**
+
+日志记录首先在一个文件中进行,当该文件被写满后,系统自动切换到另一个文件继续记录。一旦第二个文件也被填满,写入操作将回退至第一个文件,覆盖最早的日志条目,从而实现一个持续的循环过程。
+
+InnoDB采用**双Redo Log文件**的设计,默认命名为`ib_logfile0`和`ib_logfile1`。这些文件的大小是固定的,并且可以通过在配置文件(如`my.cnf` 或`my.ini`)中设置`innodb_log_file_size`参数来进行调整。
+
+循环写入策略:
+
+日志记录首先在一个文件中进行,当该文件被写满后,系统自动切换到另一个文件继续记录。一旦第二个文件也被填满,写入操作将回退至第一个文件,覆盖最早的日志条目,从而实现一个持续的循环过程。
+
+**优点:**
+
+- 性能提升:
+ - 减少磁盘I/0开销:由于日志文件大小固定并采取循环使用的方式,避免了频繁地调整文件尺寸的需求,从而降低了磁盘I/O活动频率,进而提高了数据写入效率。
+ - 加速数据写入:鉴于日志是以顺序方式写入的特性,相比随机访问模式而言,这能够显著加快数据录入速率。
+- 简化恢复流程:
+ - 快速故障恢复:利用RedoLog,在数据库遭遇崩溃时可以迅速恢复未完成事务的状态。通过重新执行日志中的指令序列,可有效维护数据一致性。
+ - 缩短恢复周期:鉴于日志容量有限且定期循环更新,实际需要处理的日志信息量较小,因此能大幅缩短整个恢复所需时
+ 间。
+- 优化存储空间利用:
+ - 节省存储资源:通过限制和循环使用指定大小的日志文件,防止了无限制增长带来的空间浪费问题。
+ - 便于管理和监控:预设的日志文件尺寸使得对其管理变得更加简便直观,有助于系统管理员更好地预测及控制相关资源消耗情况。
+- 增强可用性和可靠性:
+ - 提高容错能力:双文件架构为系统提供了额外的安全保障;即使某个文件受损,仍可通过另一份副本完成数据恢复工作。
+ - 支持连续性操作:在从一个已满的日志文件切换至下一个期间,服务不会中断,保证了对新请求的持续响应与处理,确保了系统的高可用性。
+
+### 崩溃恢复
+
+MySQL的崩溃本质上是一次非预期的关闭过程,与正常关闭相比,它显得更为突然和快速。在正常的关闭过程中,MySQL会执行一系列清理操作,包括但不限于清除undo日志、合并changebuffer等。
+
+虽然在系统稳定运行时,undo日志可能被视为余信息,但在出现故障的情况下,这些日志成为宝贵资源,允许数据库在重启后恢复到崩溃前的状态。这一恢复过程主要包括以下几个关键步骤:
+
+1. **确定最近的一个存档点**:在读取Redo日志之前,首要任务是定位恢复操作的起始点。这个起点即为InnoDB存储引擎最后一次执行checkpoint操作时记录的日志序列号(LSN),被称为`last_checkpoint_lsn`。
+2. **修复损坏的数据页**:将两次写机制涉及的所有数据页加载至buff pool之后,使用截断(turncat)操作来修复系统表空间、独立表空间以及undo表空间中可能存在的任何损坏的数据页。
+3. **读取Redo日志**:基于已知的`last_checkpoint_lsn`作为起点,接下来的步骤是按顺序读取Redo日志中的记录。
+4. **应用Redo日志**:最后一步是根据从Redo日志中读取的信息对数据库状态进行更新,确保所有未完成但已被持久化的事务得到正确地重做,从而实现数据一致性恢复。
+
+通过上述流程,即使遇到意外情况导致服务中断,MySQL也能够有效地恢复到一个一致且可靠的状态。
+
+## Binlog
+
+二进制日志(Binlog)主要用于记录所有针对数据库表结构的变更以及表数据的修改操作,但不包括如`SELECT`、`SHOW`等读取类的操作。Binlog是在事务成功提交后,在服务层生成的日志文件,其主要功能体现在两个方面:
+
+1. **数据恢复**:通过详尽地记录所有影响数据状态的SQL命令,Binlog为从特定时间点或由于意外操作导致的数据丢失提供了恢复手段。一旦发生数据损坏或丢失事件,可以通过重放Binlog中的历史更改来恢复至先前的态。
+2. **主从复制**:对于需要跨多台服务器实现数据备份的应用场景,可以利用监听写入数据库的Binlog日志机制,将主数据库的所有更新同步到一个或多个从属数据库上,从而构建出高效的分布式数据库架构。
+
+### Binlog格式类型
+
+MySQL支持三种类型的Binlog格式:`STATEMENT`、`ROW`及`MIXED`。
+
+- **STATEMENT模式**:在此模式下,每一条引起数据变化的SQL语句都会被直接记录下来。这种方式的优点在于减少了日志大小并提高了处理速度;然而,如果使用了`SYSDATE()`、`NOW()`之类的非确定性函数,则可能导致在执行数据恢复或主从复制过程中产生一致性问题。
+- **ROW模式**:与记录整个SQL不同,ROW模式仅追踪实际受到影响的数据行的变化情况。这种方法避免了STATEMENT模式下的动态内容带来的挑战,但代价是增加了日志文件的体积。
+- **MIXED模式**:作为前两者的折衷方案,MIXED模式根据具体情况自动选择最合适的记录方式。当系统认为STATEMENT更优时采用之,否则切换到ROW模式以确保准确性。
+
+需要注意的是,默认的Binlog格式设置取决于所使用的MySQL版本:5.7.7以前默认为`STATEMENT`,之后改为`ROW`。用户可以通过调整`binlog-format`参数来自定义所需的行为。
+
+### 记录方式
+
+二进制日志(binlog)采用**追加模式**进行写入。通过配置`max_binlog_size`参数,可以设定单个binlog文件的最大尺寸。一旦某个binlog文件达到该预设值,系统将自动创建一个新的文件以继续记录后续的日志信息。
+
+这些日志文件按照顺序命名,形式如`mysql-bin.000001`、`mysql-bin.000002`,直至`mysql-bin.00000x`等。要查询当前存在的所有binlog文件列表,可使用SQL命令`SHOW BINARY LOGS;`。
+
+以上调整旨在提高文档的专业性和准确性,同时保持信息的清晰度与完整性。
+
+### 主从复制(relay log)
+
+主从复制机制主要依赖于二进制日志(binlog)。在此架构中,从库(slave)通过读取主库(master)的binlog来实现数据同步。MySQL的主从复制过程是异步且串行化的,这意味着主库上执行事务提交的操作不会等待binlog复制到从库的过程完成。该流程可概括为三个阶段:写入、同步与重做。
+
+- 写入:在这一阶段,主库首先将变更记录至其binlog中,随后提交相关事务,并更新本地数据库存储。
+- 同步:接下来,这些binlog被传输给所有配置好的从库,在每个从库上,接收到的binlog内容会被追加到一个称为中继日志(relaylog)的临时文件里。
+- 重做:最后一步是从库解析并应用中继日志中的事件,以此来更新自身的数据存储状态,从而达到与主库一致的目的。
+
+采用主从复制模式能够带来诸如读写分离(即所有的写操作都在主库进行,而读请求则可以分散到各个从库处理)、以及数据穴余备份等优势。不过,随着从库数量的增长,尤其是当大量I/O线程尝试连接到主库时,可能会导致主库资源紧张,进而引发主从之间的数据延迟问题。除此之外,网络状况不佳、带宽限制或是存在耗时较长的SQL查询等因素也都是引起延迟的常见原因。对于后者具体的分析和解决策略,建议进一步查阅相关资料或文献以获得更深入的理解。
+
+
+
+
+
+
+
#