-
Notifications
You must be signed in to change notification settings - Fork 480
[过时资料]ProxyBuffer设计之一
jamie12221 edited this page Nov 18, 2020
·
1 revision
mycat2.0 设计前后端读写共享同一个buffer。该buffer是可重用的,连续读或者写,当空间不够时compact擦除之前用过的空间。 当前buffer设计是基于单工模式的,即:要么读,要么写.不会存在同时读写的情况。只有数据被操作完成(读完或者写完)后state才能被改变。
对buffer的操作分为以下三个场景
- 从 channel 向 buffer 写入数据。
- 从 buffer 中读取数据 进行逻辑处理。 以mycat 为例,会从buffer中读取出mysql报文数据,进行逻辑处理。
- channel 从 buffer 中读取数据。
注: 以上三个场景区分前端和后端。即:当前buffer 是前端操作还是后端操作。
为满足以上三个场景,设计了ProxyBuffer. ProxyBuffer 共有三个指针,一个状态。
注:第二个指针 readMark 指针存在的目的在于 减少 compact 的次数。
# | 字段 | 默认值 | 说明 |
---|---|---|---|
1 | writeIndex | 0 | 从channel 向 buffer 写入数据的开始位置。 |
2 | readMark | 0 | 从buffer 向 channel 写入数据的开始位置。 |
3 | readIndex | 0 | 从buffer 向 channel 写入数据的结束位置。 |
# | 字段 | 默认值 | 说明 |
---|---|---|---|
1 | inReading | false | 当前buffer 的读写状态。有两个状态 false 代表写入状态;true 代表读取状态。 |
# | 场景 | 状态 | 数据范围 | 变化指针 |
---|---|---|---|---|
1 | 从channel 向 buffer 写入数据 | 写入 | writeIndex---capacity | writeIndex 增加 |
2 | 从buffer 读取数据 进行逻辑处理 | 可读 | readIndex---writeIndex | readIndex 增加 |
3 | 将buffer数据写入到channel中 | 可读 | readMark --- readIndex | readMark 增加 |
1. proxybuffer 读写状态。
从channel 读取数据写入到 ProxyBuffer时, channel 为可读状态,
proxyBuffer 处于写入状态,即 inReading= false;
2. 写入的开始结束位置。
始终是从 writeIndex 开始向proxyBuffer 中写入数据。
写入结束位置始终是buffer 的capacity。
3. writeIndex 指针的移动。
本次写入多少数据writeIndex 就移动相应的长度。
4. proxybuffer 压缩。
每次开始向proxybuffer 写入数据前,
判断当前proxybuffer 容量是否大于总容量的1/3(writeIndex > buffer.capacity() * 1 / 3).
如果大于 1/3 进行一次 compact。
注: 在遇到半包不参与透传时, 会出现数据就已经全部读取完成后, readIndex < writeIndex 的情况。
1. proxybuffer 读写状态。
从 channel 中读取数据到proxybuffer后,proxybuffer 进入可读状态,即 inReading = true;
2. 读取数据的开始结束位置。
数据始终从 readIndex 开始读取数据。
读取结束位置为 writeIndex。
即程序从buffer 中读取数据的范围是 readIndex -- writeIndex 之间的数据。
3. readIndex 指针的移动
每读取一次数据,readIndex就增加相应的长度。
当 readIndex == writeIndex 时,代表本次写入到proxybuffer中的数据,全部读取完成。
注: 在遇到网络阻塞等情况时, 会出现数据一次传不完的情况,即: readMark < readIndex。这时注册可写事件,下次写readMark-readIndex 之间的数据
1. proxybuffer 读写状态。
向 channel 写入数据时,当前proxybuffer 需要确保进入可读状态,即 inReading = true;
2. 写入到channel中数据的开始结束位置。
channel 始终从 readMark 开始 读取数据,到 readIndex 结束。
即:写入到 channel中的数据范围是 readMark---readIndex 之间的数据。
3. readMark 指针的移动
将数据写出到channel中后,readMark 对应写出了多少数据。即: writed = channel.write(buffer);
每次写出数据后,readMark 增加写出数据的长度。即: readMark += writed ;
readMark默认值为0. 有可能存在 要写出的数据 writed 没有写出去,或者只写出去了一部分的情况。
下次channel 可写时(通常可写事件被触发),接着从readMark 开始写出数据到channel中。
当readMark==readIndex 时,代表 数据全部写完。
4. 读写状态转换
数据全部写完后,proxybuffer 状态 转换为 可写状态。即 inReading = false;
5. proxybuffer 压缩。
每次从proxybuffer读取数据写入到channel后,
判断当前proxybuffer 已读是否大于总容量的2/3(readIndex > buffer.capacity() * 2 / 3).
如果大于 2/3 进行一次 compact。