Skip to content

Commit 4e86422

Browse files
committed
docs: update documents
1 parent 2d4ee6f commit 4e86422

File tree

8 files changed

+30
-51
lines changed

8 files changed

+30
-51
lines changed

.github/workflows/prettier.yml

Lines changed: 0 additions & 25 deletions
This file was deleted.

README.md

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -279,10 +279,10 @@
279279
- [RocketMQ 生产者启动流程](docs/rocketmq/rocketmq-producer-start.md)
280280
- [RocketMQ 消息发送流程](docs/rocketmq/rocketmq-send-message.md)
281281
- [RocketMQ 消息发送存储流程](docs/rocketmq/rocketmq-send-store.md)
282-
- [RocketMQ MappedFile内存映射文件详解](docs/rocketmq/rocketmq-mappedfile-detail.md)
283-
- [RocketMQ ConsumeQueue详解](docs/rocketmq/rocketmq-consumequeue.md)
284-
- [RocketMQ CommitLog详解](docs/rocketmq/rocketmq-commitlog.md)
285-
- [RocketMQ IndexFile详解](docs/rocketmq/rocketmq-indexfile.md)
282+
- [RocketMQ MappedFile 内存映射文件详解](docs/rocketmq/rocketmq-mappedfile-detail.md)
283+
- [RocketMQ ConsumeQueue 详解](docs/rocketmq/rocketmq-consumequeue.md)
284+
- [RocketMQ CommitLog 详解](docs/rocketmq/rocketmq-commitlog.md)
285+
- [RocketMQ IndexFile 详解](docs/rocketmq/rocketmq-indexfile.md)
286286
- [RocketMQ 消费者启动流程](docs/rocketmq/rocketmq-consumer-start.md)
287287
- [RocketMQ 消息拉取流程](docs/rocketmq/rocketmq-pullmessage.md)
288288
- [RocketMQ Broker 处理拉取消息请求流程](docs/rocketmq/rocketmq-pullmessage-processor.md)
@@ -387,6 +387,10 @@ GitHub 技术社区 [Doocs](https://github.com/doocs),致力于打造一个内
387387
</tr>
388388
</table>
389389

390+
<<<<<<< HEAD
390391
关注公众号「**Doocs**」,回复 **PDF**,即可获取 [互联网 Java 工程师进阶知识完全扫盲](https://github.com/doocs/advanced-java) 项目离线 PDF 文档(283 页精华),学习更加方便!
392+
=======
393+
关注「**Doocs**」公众号,回复 **PDF**,即可获取 [互联网 Java 工程师进阶知识完全扫盲](https://github.com/doocs/advanced-java) 项目离线 PDF 文档(283 页精华),学习更加方便!
394+
>>>>>>> d309ac0 (docs: update documents)
391395
392396
![](./images/pdf.png)

docs/Netty/Netty技术细节源码分析/ByteBuf的内存泄漏原因与检测原理.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
## Netty 中的 ByteBuf 为什么会发生内存泄漏
44

5-
在 Netty 中,ByetBuf 并不是只采用可达性分析来对 ByteBuf 底层的 `byte[]` 数组来进行垃圾回收,而同时采用引用计数法来进行回收,来保证堆外内存的准确时机的释放。
5+
在 Netty 中,ByetBuf 并不是只采用可达性分析来对 ByteBuf 底层的 `byte[]` 数组来进行垃圾回收,而同时采用引用计数法来进行回收,来保证堆外内存的准确时机的释放。
66

77
在每个 ByteBuf 中都维护着一个 refCnt 用来对 ByteBuf 的被引用数进行记录,当 ByteBuf 的 `retain()` 方法被调用时,将会增加 refCnt 的计数,而其 `release()` 方法被调用时将会减少其被引用数计数。
88

@@ -24,7 +24,7 @@ private boolean release0(int decrement) {
2424
}
2525
```
2626

27-
当调用了 ByteBuf 的 `release()` 方法的时候,最后在上方的 `release0()` 方法中将会为 ByteBuf 的引用计数减一,当引用计数归于 0 的时候,将会调用 `deallocate()` 方法对其对应的底层存储数组进行释放(在池化的 ByteBuf 中,在 `deallocate()` 方法里会把该 ByteBuf 的 `byte[]` 回收到底层内存池中,以确保 `byte[]` 可以重复利用)。
27+
当调用了 ByteBuf 的 `release()` 方法的时候,最后在上方的 `release0()` 方法中将会为 ByteBuf 的引用计数减一,当引用计数归于 0 的时候,将会调用 `deallocate()` 方法对其对应的底层存储数组进行释放(在池化的 ByteBuf 中,在 `deallocate()` 方法里会把该 ByteBuf 的 `byte[]` 回收到底层内存池中,以确保 `byte[]` 可以重复利用)。
2828

2929
由于 Netty 中的 ByteBuf 并不是随着申请之后会马上使其引用计数归 0 而进行释放,往往在这两个操作之间还有许多操作,如果在这其中如果发生异常抛出导致引用没有及时释放,在使用池化 ByetBuffer 的情况下内存泄漏的问题就会产生。
3030

docs/Redis/redis-sds.md

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ sds sdsnewlen(const void *init, size_t initlen) {
112112
unsigned char *fp;
113113

114114
// 检查长度是否溢出
115-
assert(initlen + hdrlen + 1 > initlen);
115+
assert(initlen + hdrlen + 1 > initlen);
116116

117117
// 创建字符串,+1是因为 `\0` 结束符
118118
// sh指向header首字节
@@ -131,7 +131,7 @@ sds sdsnewlen(const void *init, size_t initlen) {
131131

132132
// 赋值len, alloc, flags
133133
...
134-
134+
135135

136136
// 赋值buf[]
137137
if (initlen && init)
@@ -145,7 +145,7 @@ sds sdsnewlen(const void *init, size_t initlen) {
145145
}
146146
```
147147
148-
创建 SDS 的大致流程是这样的:首先根据字符串长度计算得到 type,根据 type 计算头部所需长度,然后动态分配内存空间。通过计算出指向header的指针sh,指向buf的指针s,对结构体各字段进行赋值。
148+
创建 SDS 的大致流程是这样的:首先根据字符串长度计算得到 type,根据 type 计算头部所需长度,然后动态分配内存空间。通过计算出指向 header 的指针 sh,指向 buf 的指针 s,对结构体各字段进行赋值。
149149
150150
注意:
151151
@@ -180,11 +180,11 @@ void sdsclear(sds s) {
180180
}
181181
```
182182
183-
### 3. 更新len
183+
### 3. 更新 len
184+
185+
因为 sdsnewlen 函数返回的是 char\* 类型的 buf,所以兼容了 c 语言操作字符串的函数,
186+
那么当 `s = ['a', 'b', 'c', '\0']` 时, 再操作`s[2] = '\0'`, 这个时候`sdslen(s)`得到的结果是 3,因为 len 字段没有更新,如果直接更新`'\0'`,需要调用以下函数更新 len
184187
185-
因为sdsnewlen函数返回的是char* 类型的buf,所以兼容了c语言操作字符串的函数,
186-
那么当 `s = ['a', 'b', 'c', '\0']` 时, 再操作`s[2] = '\0'`, 这个时候`sdslen(s)`得到的结果是3,因为len字段没有更新,如果直接更新`'\0'`,需要调用以下函数更新len
187-
188188
```c
189189
void sdsupdatelen(sds s) {
190190
size_t reallen = strlen(s);
@@ -256,7 +256,7 @@ sds sdsMakeRoomFor(sds s, size_t addlen) {
256256
newlen = (len+addlen);
257257

258258
// 检查长度是否溢出
259-
assert(newlen > len);
259+
assert(newlen > len);
260260

261261
// 新长度<1MB,按新长度的2倍扩容
262262
if (newlen < SDS_MAX_PREALLOC)
@@ -274,7 +274,7 @@ sds sdsMakeRoomFor(sds s, size_t addlen) {
274274
hdrlen = sdsHdrSize(type);
275275

276276
// 检查长度是否溢出
277-
assert(hdrlen + newlen + 1 > len);
277+
assert(hdrlen + newlen + 1 > len);
278278

279279
if (oldtype==type) {
280280
// 类型没变,直接通过realloc扩大动态数组即可。
@@ -310,4 +310,4 @@ sds sdsMakeRoomFor(sds s, size_t addlen) {
310310
311311
1. SDS 返回的是指向 buf 的指针,同时以`\0`结尾,所以兼容了 C 语言操作字符串的函数,读取内容时,通过 len 属性来限制读取的长度,不受 `\0` 影响,从而保证二进制安全;
312312
2. Redis 根据字符串长度的不同,定义了多种数据结构,包括:sdshdr5/sdshdr8/sdshdr16/sdshdr32/sdshdr64。
313-
3. SDS 在设计字符串修改出会调用 `sdsMakeRoomFor` 函数进行检查,根据不同情况进行扩容。
313+
3. SDS 在设计字符串修改出会调用 `sdsMakeRoomFor` 函数进行检查,根据不同情况进行扩容。

docs/Sentinel/Sentinel时间窗口的实现.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
1. 时间窗口还未建立,那么将会为此次流量的进入建立一个新的时间窗口返回,并且接下来这个时间窗口内的获取请求都将返回该窗口。
99
2. 时间窗口已经建立的情况下,将会直接获取已经存在的符合条件的时间窗口。
1010
3. 时间窗口可能已经存在,但是当前获取的时间窗口已经过期,需要加锁,并重置当前时间窗口。
11-
4. 当前进入的时间已经远远落后当前的时间,目标时间窗口已经被 reset 更新成更新的时间窗口,那么将不会返回目标时间窗口,而是返回一个新的空的时间窗口进行统计,这个时间窗口不会再被重复利用。
11+
4. 当前进入的时间已经远远落后当前的时间,目标时间窗口已经被 reset 更新成更新的时间窗口,那么将不会返回目标时间窗口,而是返回一个新的空的时间窗口进行统计,这个时间窗口不会再被重复利用。
1212

1313
其中的第四个情况表明,sentinel 的滑动时间窗口是有时间范围的,这也是为了尽量减少 sentinel 的所占用的内存,默认情况下 sentinel 的采取的时间长度为 1 分钟和 1 秒钟。这里的实现与 LeapArray 类的结构非常有关系。
1414

@@ -22,7 +22,7 @@ protected final AtomicReferenceArray<WindowWrap<T>> array;
2222
private final ReentrantLock updateLock = new ReentrantLock();
2323
```
2424

25-
此处的 updateLock 是专门在上述的第三个情况来进行加锁的,只有成功得到锁的线程才会对过期的时间窗口进行 reset 操作,其他没有成功获取的线程将不会挂起等待,而是通过 `yield()` 方法回到就绪态,在下一次的循环尝试重新获取该位置的时间窗口。在下一次获取该锁的线程可能已经完成了,那么将会执行上述第二步,否则继续回到就绪态等待下一次循环中再次获取该时间窗口。
25+
此处的 updateLock 是专门在上述的第三个情况来进行加锁的,只有成功得到锁的线程才会对过期的时间窗口进行 reset 操作,其他没有成功获取的线程将不会挂起等待,而是通过 `yield()` 方法回到就绪态,在下一次的循环尝试重新获取该位置的时间窗口。在下一次获取该锁的线程可能已经完成了,那么将会执行上述第二步,否则继续回到就绪态等待下一次循环中再次获取该时间窗口。
2626

2727
以上两个数据结构是 LeapArray 类实现时间窗口在高并发下准确获取时间窗口并更新的关键。
2828

docs/nacos/nacos-discovery.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,7 @@ class BeatTask implements Runnable {
378378
} else {
379379
Random random = new Random(System.currentTimeMillis());
380380
int index = random.nextInt(servers.size());
381-
381+
382382
for (int i = 0; i < servers.size(); i++) {
383383
String server = servers.get(index);
384384
try {
@@ -392,10 +392,10 @@ class BeatTask implements Runnable {
392392
index = (index + 1) % servers.size();
393393
}
394394
}
395-
395+
396396
NAMING_LOGGER.error("request: {} failed, servers: {}, code: {}, msg: {}", api, servers, exception.getErrCode(),
397397
exception.getErrMsg());
398-
398+
399399
throw new NacosException(exception.getErrCode(),
400400
"failed to req API:" + api + " after all servers(" + servers + ") tried: " + exception.getMessage());
401401
```

docs/rocketmq/rocketmq-consumer-start.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ if (group.length() >CHARACTER_MAX_LENGTH) {
1818
}
1919
```
2020

21-
消费组名称只能包含数字、字母、%、-、_、|
21+
消费组名称只能包含数字、字母、%、-、\_、|
2222

2323
```java
2424
// regex: ^[%|a-zA-Z0-9_-]+$
@@ -129,7 +129,7 @@ private void copySubscription() throws MQClientException {
129129

130130
`3、初始化MqClientInstance、RebalanceImpl、PullApiWrapper`
131131

132-
创建`MqClientInstance`, 无论在生产者端还是消费者端都是一个很重要的类, 封装了Topic信息、broker信息,当然还有生产者和消费者的信息。
132+
创建`MqClientInstance`, 无论在生产者端还是消费者端都是一个很重要的类, 封装了 Topic 信息、broker 信息,当然还有生产者和消费者的信息。
133133

134134
```java
135135
public MQClientInstance getOrCreateMQClientInstance(final ClientConfig clientConfig, RPCHook rpcHook) {

docs/rocketmq/rocketmq-indexfile.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ org.apache.rocketmq.store.index.IndexFile#putKey
2828

2929
如果当前 Index 文件未满,则根据 key 计算出哈希码,然后对槽数量取余定位到某一个哈希槽位置,
3030

31-
哈希槽的物理偏移量 = IndexHeader 的大小(默认 40Byte) + 哈希槽位置 * 每个哈希槽的大小(4 字节)
31+
哈希槽的物理偏移量 = IndexHeader 的大小(默认 40Byte) + 哈希槽位置 \* 每个哈希槽的大小(4 字节)
3232

3333
```java
3434
int keyHash = indexKeyHashMethod(key);
@@ -61,7 +61,7 @@ if (this.indexHeader.getBeginTimestamp() <= 0) {
6161
}
6262
```
6363

64-
新添加的消息 index 的物理偏移量 = IndexHeader 大小(40Byte) + Index 文件哈希槽的数量 * 哈希槽的大小(4Byte ) + Index 文件索引数量 * 索引大小(20Byte)
64+
新添加的消息 index 的物理偏移量 = IndexHeader 大小(40Byte) + Index 文件哈希槽的数量 _ 哈希槽的大小(4Byte ) + Index 文件索引数量 _ 索引大小(20Byte)
6565

6666
将消息哈希码、消息物理偏移量、消息存储时间戳与 Index 文件第一条消息的时间戳的差值、当前哈希槽的值、当前 Indexfile 的索引个数存入 mappedByteBuffer
6767

@@ -115,7 +115,7 @@ long end: 结束时间戳
115115

116116
根据 key 计算哈希码,哈希码与哈希槽的数量取余得到哈希槽的索引
117117

118-
哈希槽的物理地址 = IndexHeader(40byte) + 哈希槽索引 * 每个哈希槽的大小(4byte)
118+
哈希槽的物理地址 = IndexHeader(40byte) + 哈希槽索引 \* 每个哈希槽的大小(4byte)
119119

120120
```java
121121
int keyHash = indexKeyHashMethod(key);

0 commit comments

Comments
 (0)