Skip to content

Commit 3bdbe0a

Browse files
20241013
1 parent bd3afc4 commit 3bdbe0a

File tree

7 files changed

+78
-18
lines changed

7 files changed

+78
-18
lines changed

_posts/2022-06-21-java.md

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -131,17 +131,19 @@ Java的SPI:SPI 的本质是将接口实现类的全限定名配置在文件中
131131
## 对象的创建过程
132132
1. 类加载检查
133133
2. 分配内存:指针碰撞或空闲列表
134-
- 当多个对象并发争抢空间时,有两种解决办法:CAS 和本地线程分配缓冲(TLAB,默认方式)
134+
- 当多个对象并发争抢空间时,有两种解决办法:CAS 和本地线程分配缓冲(TLAB,默认方式)
135135
3. 初始化零值
136136
4. 设置对象头
137137
5. 执行构造方法
138138

139139
## 对象的内存布局
140+
140141
1. 对象头,两部分组成:存储自身运行时数据如哈希码,GC分代年龄;指向类的类型指针
141142
2. 实例数据,真正存储有效信息的部分
142143
3. 对齐填充,起占位作用
143144

144-
[对象的定位访问(针对JVM虚拟机栈中的局部变量表)](https://javaguide.cn/java/jvm/memory-area.html#%E5%AF%B9%E8%B1%A1%E7%9A%84%E8%AE%BF%E9%97%AE%E5%AE%9A%E4%BD%8D)
145+
## [对象的定位访问(针对JVM虚拟机栈中的局部变量表)](https://javaguide.cn/java/jvm/memory-area.html#%E5%AF%B9%E8%B1%A1%E7%9A%84%E8%AE%BF%E9%97%AE%E5%AE%9A%E4%BD%8D)
146+
145147
1. 句柄,Java 堆中将会划分出一块内存来作为句柄池,局部变量表 reference 中存储的就是对象的句柄地址,而句柄中包含了对象实例数据与对象类型数据各自的具体地址信息。
146148
2. 直接指针,局部变量表里 reference 中存储的直接就是对象的地址。
147149

@@ -463,11 +465,12 @@ ThreadLocal: 提供线程内的局部变量,在多线程的环境中保证各
463465
线程工厂用于创建新线程。线程工厂提供了创建线程的方法,可以自定义线程的名称、优先级等属性。
464466

465467
7. 拒绝策略(rejectedExecutionHandler):
466-
拒绝策略定义了当线程池无法接受新任务时的处理策略。当工作队列已满且线程池中的线程数已达到最大线程数时,新任务将被拒绝执行。常见的拒绝策略有丢弃、丢弃最旧的任务、抛出异常等。
467-
1. AbortPolicy 拒绝任务并抛出一个异常 RejectedExecutionException
468-
2. DiscardPolicy 拒绝任务,不抛出异常。
469-
3. DiscardOldestPolicy 把老的任务丢掉,执行新任务。
470-
4. CallerRunsPolicy 直接调用线程处理该任务。
468+
拒绝策略定义了当线程池无法接受新任务时的处理策略。当工作队列已满且线程池中的线程数已达到最大线程数时,新任务将被拒绝执行。常见的拒绝策略有丢弃、丢弃最旧的任务、抛出异常等。
469+
1. AbortPolicy 拒绝任务并抛出一个异常 RejectedExecutionException
470+
2. DiscardPolicy 拒绝任务,不抛出异常。
471+
3. DiscardOldestPolicy 把老的任务丢掉,执行新任务。
472+
4. CallerRunsPolicy 直接调用线程处理该任务。
473+
471474

472475

473476

@@ -521,7 +524,7 @@ JDK四种线程池:
521524
- 非公平锁,每个线程获取锁的顺序是随机的,并不会遵循先来先得的规则,所有线程会竞争获取锁。
522525

523526
5. 可重入锁(递归锁),非可重入锁:ReentrantLock和synchronized都是可重入锁,**NonReentrantLock是非可重入锁**
524-
- 可重入锁,指在同一个线程在外层方法获取锁的时候,再进入该线程的内层方法会自动获取锁(前提锁对象得是同一个对象或者class),不会因为之前已经获取过还没释放而阻塞。好处是一定程度避免死锁
527+
- 可重入锁,指在同一个线程在外层方法获取锁的时候,再进入该线程的内层方法可以再次获取锁(前提锁对象得是同一个对象或者class),不会因为之前已经获取过还没释放而阻塞。好处是避免死锁
525528
- 非可重入锁,如果一个方法中获取锁并调用另外方法,那么在调用另外方法前需要释放锁。
526529

527530
6. 独享锁(排它锁),共享锁

_posts/2022-06-22-mysql.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ pin: true
1212
单机 QPS 为 4k 左右。
1313

1414
# MySQL select语句执行
15-
- prepare 阶段,检查查询语句中的表活字段是否存在,将 `*` 拓展为表上的所有列。
15+
- prepare 阶段,检查查询语句中的表或字段是否存在,将 `*` 拓展为表上的所有列。
1616
- optimize 阶段,优化器决定使用哪个索引。
1717
- execute 阶段,执行器,索引下推。
1818

@@ -282,10 +282,15 @@ Binlog 的持久化:
282282

283283
#### Redolog
284284

285+
写入流程:
286+
1. 写入 redo log buffer
287+
2. 写入(write)到 page cache
288+
3. 持久化(fsync)到磁盘中
289+
285290
刷盘时机:
286291
1. MySQL 正常关闭
287-
2. redo log buffer 的写入量大于 redo log buffer 内存空间的一半时
288-
3. 后台线程每隔一秒将 redo log buffer 持久化到磁盘
292+
2. redo log buffer 的写入量大于 redo log buffer 内存空间(默认8MB)的一半时,write 到 page cache 中。
293+
3. 后台线程每隔一秒调用 write 将 redo log buffer 写到 page cache,然后 fsync 持久化到磁盘
289294
4. innodb_flush_log_at_trx_commit 参数
290295
1. 当innodb_flush_log_at_trx_commit=0时,InnoDB会**每秒钟**将log buffer的数据**write**到文件系统缓存中,并调用**fsync**操作将数据缓存更新至磁盘中,与事务的执行与否无关。因此,在实例崩溃恢复场景中,可能会出现丢失1秒钟的事务。
291296
2. 当innodb_flush_log_at_trx_commit=1时,InnoDB将在**每次事务提交**时将log buffer的数据**write**到文件系统缓存中,并调用**fsync**操作将数据缓存更新至磁盘中。此种方式下,数据库完全遵守ACID特性,安全性较高。

_posts/2023-07-06-redis.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ Redis的删除策略是**惰性删除+定期删除**。定期删除如果检查
291291
2. 进行数据淘汰
292292
1. 在设置了过期时间的数据中进行淘汰
293293
- volatile-random: 随机淘汰设置了过期时间的任意键值;
294-
- volatile-ttl:优先淘汰更早过期的键值。
294+
- volatile-ttl:优先淘汰离过期时间最近的键值;
295295
- volatile-lru:淘汰所有设置了过期时间的键值中,最久未使用的键值;
296296
- volatile-lfu:淘汰所有设置了过期时间的键值中,最少使用的键值;
297297
2. 在所有数据范围内进行淘汰

_posts/2023-08-11-springboot.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,8 @@ Prototype(原型)对象和单例对象的区别:
110110
- @SpringBootApplication 包含三个注解:
111111
1. @SpringBootConfiguration, 继承@Configuration,标注当前类是配置类,并会将当前类内声明的一个或多个以@Bean注解标记的方法的实例注册到spring容器中,并且实例名就是方法名。
112112
2. [@EnableAutoConfiguration](https://www.cnblogs.com/kevin-yuan/p/13583269.html),主要由 @AutoConfigurationPackage@Import(EnableAutoConfigurationImportSelector.class)这两个注解组成的。
113-
- @AutoConfigurationPackage 内部是 @({Registrar.class}),用于将启动类所在的包里面的所有组件注册到spring容器。扫描 @Entity, @Mapper 等第三方依赖注解。
114-
- @Import(EnableAutoConfigurationImportSelector.class) 是将特定路径(META-INF/spring.factories)中所有符合自动配置条件(@ConditionalOnClass)的类加载到Ioc容器,例如mybatis-spring-boot-starter。`AutoConfigurationImportSelector.java` 中可以看到所有自动配置类的名称。[自动配置类原理](https://juejin.cn/post/7101477895331135495)
113+
1. @AutoConfigurationPackage 内部是 @({Registrar.class}),用于将启动类所在的包里面的所有组件注册到spring容器。扫描 @Entity, @Mapper 等第三方依赖注解。
114+
2. @Import(EnableAutoConfigurationImportSelector.class) 是将特定路径(META-INF/spring.factories)中所有符合自动配置条件(@ConditionalOnClass)的类加载到Ioc容器,例如mybatis-spring-boot-starter。`AutoConfigurationImportSelector.java` 中可以看到所有自动配置类的名称。[自动配置类原理](https://juejin.cn/post/7101477895331135495)
115115
3. @ComponentScan,自动扫描并加载被@Component@Repository修饰的组件,最终将这些组件加载到容器中,默认路径是该注解所在类的package。
116116

117117

_posts/2023-08-25-kafka-vs-rocketmq.md

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ Page Cache(页面缓存)从内存中划出一块区域缓存文件页,如
9696

9797
- Broker: 同步刷盘;设置主从模式,配置副本
9898

99-
- Consumer: At least Once 的消费机制;消费重试;ACK机制;手动提交位移(Kafka)
99+
- Consumer: At least Once 的消费机制;消费重试;手动提交偏移量(Kafka)
100100

101101

102102
## 零拷贝
@@ -299,6 +299,23 @@ RocketMQ/Kafka 使用 Consumer Group 机制,实现了传统两大消息引擎
299299

300300
一个Topic分为多个Partition,一个Partition分为多个Segment。每个Segment对应三个文件:偏移量索引文件、时间戳索引文件、消息存储文件
301301

302+
## 根据偏移量/时间戳查找消息
303+
304+
![](https://raw.githubusercontent.com/CompetitiveLin/ImageHostingService/picgo/imgs/202410121820230.png)
305+
306+
偏移量文件中记录的是**稀疏索引**
307+
308+
### 偏移量 offset = x
309+
1. 根据偏移量索引文件名和 offset 的值,进行二分查找,找到小于 x 的最大 offset 文件
310+
2. 在该偏移量索引文件(.index)中,找到改 offset 对应的 position 位置
311+
3. 在消息存储文件(.log)中,找到该 position 所对应的消息内容
312+
313+
314+
### 时间戳 timestamp = t
315+
1. 在时间戳索引文件(.timeindex)中,找到比 t 大的最小时间戳,与其所对应的 offset 值
316+
2. 在偏移量索引文件(.index)中,找到该 offset 值对应的 position 位置
317+
3. 在消息存储文件(.log)中,找到该 position 所对应的消息内容
318+
302319
## Producer 生产消息的流程
303320
在消息发送的过程中,涉及到两个线程,main线程和sender线程,其中main线程是消息的生产线程,而sender线程是jvm单例的线程,专门用于消息的发送。在jvm的内存中开辟了一块缓存空间叫RecordAccumulator(消息累加器),用于将多条消息合并成一个批次,然后由sender线程发送给kafka集群。
304321

@@ -347,3 +364,14 @@ Controller 用于在 ZK 的帮助下管理和协调整个 Kafka 集群。集群
347364
3. 集群 Broker 管理
348365
4. 数据服务,保存最完整的元数据信息
349366

367+
## 手动/自动提交偏移量区别
368+
369+
![](https://raw.githubusercontent.com/CompetitiveLin/ImageHostingService/picgo/imgs/202410121609254.png)
370+
371+
发生 Rebalance 时,自动提交偏移量有可能出现消息丢失/消息重复消费的问题,而手动提交偏移量则不会
372+
1. 消息丢失:提交的偏移量**大于**消费者处理的最后一个消息的偏移量
373+
2. 消费重复消费:提交的偏移量**小于**消费者处理的最后一个信息的偏移量
374+
375+
376+
377+

_posts/2023-09-07-note-from-work.md

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,13 @@ SSL 加密是绝对安全的,但是 HTTPS 并不是绝对安全的,可以通
330330

331331
## 进程和线程
332332

333+
### 进程拥有的资源
334+
1. 进程控制块
335+
2. 文件描述符
336+
3. 网络连接
337+
4. 设备
338+
339+
333340
区别:
334341
1. 进程是系统资源分配的最小单位,实现了操作系统的并发;线程是CPU调度的最小单位,实现了进程内部的并发。
335342
2. 进程在执行过程中拥有独立的内存单元,而多个线程共享进程的内存。
@@ -466,7 +473,7 @@ DNS 在进行区域传输的时候使用 TCP,其他情况使用 UDP。
466473
7. 流量控制:滑动窗口实现
467474

468475
## OSI 七层模型和 TCP/IP 四层模型
469-
1. 应用层:HTTP,DNS,FTP;网关
476+
1. 应用层:HTTP,DNS,FTP,WebSocket;网关
470477
1. 应用层
471478
2. 表示层
472479
3. 会话层
@@ -546,4 +553,14 @@ CPU 占用排查:使用 `top` 和 `top -Hp xxx` 命令定位占用率最高的
546553
# 缓存 IO,直接 IO,裸 IO
547554
- 缓存IO:读数据时先从内核空间的缓冲区读,如果没有则从磁盘中读并缓存到缓冲区;写数据将用户空间的数据复制到内核空间的缓冲区,并标记为脏页,操作系统后台将脏页写入磁盘中,一般用于频繁读写的小文件;
548555
- 直接IO:直接读写文件,而不经过内核缓冲区,目的是减少一次内核缓冲区到用户程序缓存的数据复制,一般用于不需要频繁读写的大文件;
549-
- 裸IO:绕过文件系统,直接读写磁盘块设备数据,一般用于数据库;
556+
- 裸IO:绕过文件系统,直接读写磁盘块设备数据,一般用于数据库;
557+
558+
# Base64 和 Base62 的区别
559+
560+
## 编码
561+
1. Base64:26 个大写字母 + 26 个小写字母 + 10 个数字 + `+` + `/`;并不适合直接放在URL里传输,因为URL编码器会把标准Base64中的「/」和「+」字符变为形如「%XX」的形式。
562+
2. Base62:26 个大写字母 + 26 个小写字母 + 10 个数字。
563+
564+
## 实现
565+
1. Base64:将输入字符串按字节切分,取得每个字节对应的二进制值(若不足 8 比特则高位补 0),然后将这些二进制数值串联起来,再按照 6 比特一组进行切分(因为 2^6=64),最后一组若不足 6 比特则末尾补 0。若原字节序列数据长度不是 3 的倍数时且剩下 1 个输入数据,则在编码结果后加 2 个 =;若剩下 2 个输入数据,则在编码结果后加 1 个 =。将每组二进制值转换成十进制,然后找到对应的符号并串联起来就是 Base64 编码结果。
566+
2. Base62:将输入字符串哈希后转成长整型,再用**62进制**编码成Base62格式。

_posts/2024-02-27-go.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,4 +283,11 @@ func main() {
283283
## Byte 和 Rune 类型
284284

285285
- byte是uint8的别称,一个值就是一个ASICII码的值,占 1 个字节的英文类字符,使用 byte
286-
- rune是int32的别称,一个值就是一个Unicode字符,占 1 ~ 4 个字节的其他字符,可以使用rune(或者int32),如中文、特殊符号等。
286+
- rune是int32的别称,一个值就是一个Unicode字符,占 1 ~ 4 个字节的其他字符,可以使用rune(或者int32),如中文、特殊符号等。
287+
288+
## 内存对齐
289+
290+
### 好处
291+
1. 平台原因:不是所有的硬件平台都能访问任意地址上的任意数据的,某些硬件平台只能在某些地址处取某些特定类型的数据
292+
2. [提高访问效率](https://www.cnblogs.com/zongqingmeng/p/14620740.html):考虑到 CPU 是分块读取数据的,假设一次性读取4字节的数据,如果不进行内存对齐,则需要多次读取内存中的数据,再进行剔除等操作,极大降低CPU性能。
293+

0 commit comments

Comments
 (0)