Skip to content

Commit 8cbe5b8

Browse files
committed
Solve the lock-free concurrency problem of ob_skiplist
1 parent 895d3b6 commit 8cbe5b8

File tree

3 files changed

+628
-427
lines changed

3 files changed

+628
-427
lines changed

src/oblsm/memtable/ob_memtable.cpp

Lines changed: 87 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,20 @@ EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
88
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
99
See the Mulan PSL v2 for more details. */
1010

11+
12+
// MemTable 将插入的 Key-Value 编码为如下的记录存储。
13+
// ┌───────────┬──────────────┬───────┬──────────────┬──────────────────┐
14+
// │ │ │ │ │ │
15+
// │key_size(8)│ key(key_size)│ seq(8)│ value_size(8)│ value(value_size)│
16+
// │ │ │ │ │ │
17+
// └───────────┴──────────────┴───────┴──────────────┴──────────────────┘
18+
// 其中,key_size 和 value_size 分别表示 key+seq 和 value 的长度,seq 表示记录的时间戳。括号中表示占用字节数。
19+
// MemTable 的实现位于:src/oblsm/memtable/,在代码中,
20+
// 我们将上图中的key 称为 user_key,
21+
// 将 key + seq 称为 internal_key,
22+
// 将key_size + key + seq 称为 lookup_key。
23+
24+
1125
#include "oblsm/memtable/ob_memtable.h"
1226
#include "common/lang/string.h"
1327
#include "common/lang/memory.h"
@@ -16,8 +30,21 @@ See the Mulan PSL v2 for more details. */
1630

1731
namespace oceanbase {
1832

33+
// 将一个 (key, value) 以及版本号 seq 插入到内存表 MemTable 中。
34+
// 示例:
35+
// key = "apple" // 长度 = 5
36+
// value = "red fruit" // 长度 = 9
37+
// seq = 123456789ULL // 一个版本号
38+
// [key_size (8 bytes)] [key (user_key)] [seq (8 bytes)] [value_size (8 bytes)] [value]
39+
// [ 5 ] [apple ] [123456789 ] [9 ] [red fruit]
40+
// 8字节 5字节 8字节 8字节 9字节
41+
// 8+5 apple 123456789 9 red fruit
42+
// 表示这些数据需要占据的长度
43+
// encoded_len = sizeof(size_t) + 8+5 + sizeof(size_t) + 9;
44+
1945
void ObMemTable::put(uint64_t seq, const string_view &key, const string_view &value)
2046
{
47+
std::lock_guard<std::mutex> lock(table_mutex_); // 保护整个put操作
2148
// TODO: add lookup_key, internal_key, user_key relationship and format in memtable/sstable/block
2249
// TODO: unify the encode/decode logic in separate file.
2350
// Format of an entry is concatenation of:
@@ -32,13 +59,13 @@ void ObMemTable::put(uint64_t seq, const string_view &key, const string_view &va
3259
const size_t encoded_len = sizeof(size_t) + internal_key_size + sizeof(size_t) + val_size;
3360
char * buf = reinterpret_cast<char *>(arena_.alloc(encoded_len));
3461
char * p = buf;
35-
memcpy(p, &internal_key_size, sizeof(size_t));
62+
memcpy(p, &internal_key_size, sizeof(size_t)); // 8 字节
3663
p += sizeof(size_t);
3764
memcpy(p, key.data(), user_key_size);
3865
p += user_key_size;
39-
memcpy(p, &seq, sizeof(uint64_t));
66+
memcpy(p, &seq, sizeof(uint64_t)); // 8 字节
4067
p += sizeof(uint64_t);
41-
memcpy(p, &val_size, sizeof(size_t));
68+
memcpy(p, &val_size, sizeof(size_t)); // 8 字节
4269
p += sizeof(size_t);
4370
memcpy(p, value.data(), val_size);
4471
table_.insert(buf);
@@ -68,4 +95,60 @@ void ObMemTableIterator::seek(const string_view &k)
6895
iter_.seek(k.data());
6996
}
7097

71-
} // namespace oceanbase
98+
} // namespace oceanbase
99+
100+
101+
102+
103+
// 📦 SSTable 的存储结构详解
104+
// 我们来拆解你贴的结构图,帮助你理解 SSTable 是如何组织数据的:
105+
106+
// scss
107+
// 复制代码
108+
// ┌─────────────────┐
109+
// │ block 1 │◄──┐
110+
// ├─────────────────┤ │
111+
// │ block 2 │ │
112+
// ├─────────────────┤ │
113+
// │ .. │ │
114+
// ├─────────────────┤ │
115+
// │ block n │◄┐ │
116+
// ├─────────────────┤ │ │
117+
// ┌─►│ meta size(n) │ │ │
118+
// │ ├─────────────────┤ │ │
119+
// │ │block meta 1 size│ │ │
120+
// │ ├─────────────────┤ │ │
121+
// │ │ block meta 1 ┼─┼─┘
122+
// │ ├─────────────────┤ │
123+
// │ │ .. │ │
124+
// │ ├─────────────────┤ │
125+
// │ │block meta n size│ │
126+
// │ ├─────────────────┤ │
127+
// │ │ block meta n ┼─┘
128+
// │ ├─────────────────┤
129+
// └──┼ │
130+
// └─────────────────┘
131+
// 我们从上到下看:
132+
133+
// 1. Block 区域(数据部分)
134+
// │ block 1 │
135+
// │ block 2 │
136+
// │ ... │
137+
// │ block n │
138+
// 2. Meta 信息区域(索引/元信息)
139+
// 紧跟在所有 block 后面,是描述这些 block 的元信息区域:
140+
// │ meta size(n) │
141+
// │ block meta 1 size │
142+
// │ block meta 1 │
143+
// │ block meta 2 size │
144+
// │ block meta 2 │
145+
// │ ... │
146+
// │ block meta n size │
147+
// │ block meta n │
148+
// 这些是描述 block 的"目录",类似于书的目录页:
149+
// meta size(n):说明一共有多少个 block。
150+
// block meta i size:说明第 i 个 block 的元信息有多大。
151+
// block meta i:包含该 block 的各种元数据,例如:
152+
// block 在 SSTable 文件中的起始偏移(offset)
153+
// block 的大小
154+
// block 中 key 的范围(起始 key、结束 key)

src/oblsm/memtable/ob_memtable.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ See the Mulan PSL v2 for more details. */
1818
#include "oblsm/util/ob_comparator.h"
1919
#include "oblsm/util/ob_arena.h"
2020
#include "oblsm/include/ob_lsm_iterator.h"
21+
#include <mutex>
2122

2223
namespace oceanbase {
2324

@@ -131,6 +132,9 @@ class ObMemTable : public enable_shared_from_this<ObMemTable>
131132
* components of the memtable.
132133
*/
133134
ObArena arena_;
135+
136+
// 用于保护ObMemTable::put(uint64_t seq, const string_view &key, const string_view &value) 函数的锁
137+
std::mutex table_mutex_;
134138
};
135139

136140
/**

0 commit comments

Comments
 (0)