Skip to content

Commit 8141e26

Browse files
author
wuxianrong
committed
The data backup and recovery functions have been added
1 parent 3e19283 commit 8141e26

27 files changed

Lines changed: 2254 additions & 91 deletions

.github/workflows/pika.yml

Lines changed: 53 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -12,83 +12,72 @@ env:
1212
ARTIFACT_PIKA_NAME: artifact-pika
1313

1414
jobs:
15+
1516
build_on_ubuntu:
16-
# The CMake configure and build commands are platform-agnostic and should work equally well on Windows or Mac.
17-
# You can convert this to a matrix build if you need cross-platform coverage.
18-
# See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix
19-
runs-on: ubuntu-latest
17+
runs-on: ubuntu-22.04
2018

2119
steps:
22-
- name: Free Disk Space (Ubuntu Host)
23-
run: |
24-
sudo rm -rf /usr/share/dotnet
25-
sudo rm -rf /usr/local/lib/android
26-
sudo rm -rf /opt/ghc
27-
sudo rm -rf /opt/hostedtoolcache/CodeQL
28-
sudo docker system prune -af
2920
- uses: actions/checkout@v4
3021

31-
- name: Set up Go
32-
uses: actions/setup-go@v5
33-
with:
34-
go-version: 1.19
35-
36-
- name: ccache
37-
uses: hendrikmuhs/[email protected]
38-
with:
39-
key: ubuntu-latest
40-
41-
- name: Install Deps
22+
- name: Build Docker image
4223
run: |
43-
sudo apt-get update
44-
sudo apt-get install -y autoconf libprotobuf-dev protobuf-compiler clang-tidy
45-
46-
- name: Configure CMake
47-
# Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
48-
# See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
49-
run: cmake -B build -DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} -DUSE_PIKA_TOOLS=ON -DCMAKE_CXX_FLAGS_DEBUG=-fsanitize=address -D CMAKE_C_COMPILER_LAUNCHER=ccache -D CMAKE_CXX_COMPILER_LAUNCHER=ccache
50-
51-
- name: Build
52-
# Build your program with the given configuration
53-
run: cmake --build build --config ${{ env.BUILD_TYPE }}
24+
docker build -t pika-ci -f ci/Dockerfile .
5425
55-
- name: Cleanup
26+
- name: Build Pika inside Docker
5627
run: |
57-
rm -rf ./buildtrees
58-
59-
- uses: actions/upload-artifact@v4
60-
with:
61-
name: ${{ env.ARTIFACT_PIKA_NAME }}
62-
path: ${{ github.workspace }}/build/pika
63-
64-
- name: Test
65-
working-directory: ${{ github.workspace }}/build
66-
# Execute tests defined by the CMake configuration.
67-
# See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
68-
run: ctest -C ${{ env.BUILD_TYPE }}
28+
docker run --rm \
29+
-v ${{ github.workspace }}:/work \
30+
-w /work \
31+
pika-ci \
32+
bash -c "rm -rf build buildtrees && \
33+
cmake -B build -DCMAKE_BUILD_TYPE=Release -DUSE_PIKA_TOOLS=ON && \
34+
cmake --build build -j2"
35+
36+
- name: Run CTest
37+
run: |
38+
docker run --rm \
39+
-v ${{ github.workspace }}:/work \
40+
-w /work/build \
41+
pika-ci \
42+
ctest --output-on-failure
6943
70-
- name: Unit Test
71-
working-directory: ${{ github.workspace }}
72-
run: ./pikatests.sh all clean
44+
- name: Run Unit Tests
45+
run: |
46+
docker run --rm \
47+
-v ${{ github.workspace }}:/work \
48+
-w /work \
49+
pika-ci \
50+
./pikatests.sh all clean
7351
74-
# master on port 9221, slave on port 9231, all with 2 db
75-
- name: Start codis, pika master and pika slave
76-
working-directory: ${{ github.workspace }}/build
52+
- name: Start Codis and Pika Integration
7753
run: |
78-
chmod +x ../tests/integration/start_master_and_slave.sh
79-
../tests/integration/start_master_and_slave.sh
80-
chmod +x ../tests/integration/start_codis.sh
81-
../tests/integration/start_codis.sh
54+
docker run --rm \
55+
-v ${{ github.workspace }}:/work \
56+
-w /work/build \
57+
pika-ci \
58+
bash -c "
59+
chmod +x ../tests/integration/start_master_and_slave.sh &&
60+
../tests/integration/start_master_and_slave.sh &&
61+
chmod +x ../tests/integration/start_codis.sh &&
62+
../tests/integration/start_codis.sh
63+
"
8264
8365
- name: Run Go E2E Tests
84-
working-directory: ${{ github.workspace }}/build
8566
run: |
86-
cd ../tools/pika_keys_analysis/
87-
go test -v ./...
88-
cd ../../tests/integration/
89-
chmod +x integrate_test.sh
90-
sh integrate_test.sh
91-
67+
docker run --rm \
68+
-v ${{ github.workspace }}:/work \
69+
-w /work/build \
70+
pika-ci \
71+
bash -c "
72+
find . -name 'pika.conf' -exec sed -i 's/loglevel : info/loglevel : error/g' {} + &&
73+
find . -name 'pika.conf' -exec sed -i 's/loglevel : debug/loglevel : error/g' {} + &&
74+
cd ../tools/pika_keys_analysis/ &&
75+
go test -v ./... &&
76+
cd ../../tests/integration/ &&
77+
chmod +x integrate_test.sh &&
78+
sh integrate_test.sh
79+
"
80+
9281
build_on_rocky:
9382
runs-on: ubuntu-latest
9483
container:
@@ -272,6 +261,7 @@ jobs:
272261
chmod +x integrate_test.sh
273262
sh integrate_test.sh
274263
264+
275265
build_on_macos:
276266

277267
runs-on: macos-14

CMakeLists.txt

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,18 @@ set(INSTALL_LIBDIR ${STAGED_INSTALL_PREFIX}/lib)
8989
set(INSTALL_LIBDIR_64 ${STAGED_INSTALL_PREFIX}/lib64)
9090
set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} ${STAGED_INSTALL_PREFIX})
9191

92+
# Fix __const__ macro conflict with GCC 13+/glibc 2.38+ in existing brpc headers
93+
# This must run during CMake configuration to fix cached/existing headers
94+
if(EXISTS "${INSTALL_INCLUDEDIR}/butil/errno.h")
95+
file(READ "${INSTALL_INCLUDEDIR}/butil/errno.h" ERRNO_H_CONTENT)
96+
string(FIND "${ERRNO_H_CONTENT}" "#ifndef __const__" HAS_CONST_MACRO)
97+
if(NOT HAS_CONST_MACRO EQUAL -1)
98+
message(STATUS "Patching existing brpc errno.h for GCC 13+ compatibility")
99+
string(REPLACE "#ifndef __const__" "#if 0 /* disabled for GCC 13+ compatibility */" ERRNO_H_CONTENT "${ERRNO_H_CONTENT}")
100+
file(WRITE "${INSTALL_INCLUDEDIR}/butil/errno.h" "${ERRNO_H_CONTENT}")
101+
endif()
102+
endif()
103+
92104
execute_process(COMMAND sh ${CMAKE_UTILS_DIR}/Get_OS_Version.sh
93105
OUTPUT_VARIABLE OS_VERSION)
94106

@@ -664,6 +676,12 @@ ExternalProject_Add(brpc
664676
1
665677
UPDATE_COMMAND
666678
""
679+
# Patch to fix __const__ macro conflict with GCC 13+/glibc 2.38+
680+
# The issue is that brpc defines __const__ as __unused__ which conflicts with
681+
# glibc's __glibc_has_attribute(__const__) macro in sys/cdefs.h
682+
# We replace '#ifndef __const__' with '#if 0' to disable the problematic macro
683+
PATCH_COMMAND
684+
sh -c "sed -i.bak 's/#ifndef __const__/#if 0 /' src/butil/errno.h && cat src/butil/errno.h | head -35"
667685
LOG_CONFIGURE
668686
1
669687
LOG_BUILD
@@ -677,16 +695,29 @@ ExternalProject_Add(brpc
677695
-DCMAKE_INSTALL_PREFIX=${STAGED_INSTALL_PREFIX}
678696
-DCMAKE_BUILD_TYPE=${LIB_BUILD_TYPE}
679697
-DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH}
698+
-DCMAKE_FIND_ROOT_PATH=${STAGED_INSTALL_PREFIX}
699+
-DCMAKE_INCLUDE_PATH=${INSTALL_INCLUDEDIR}
700+
-DCMAKE_LIBRARY_PATH=${INSTALL_LIBDIR}
680701
-DWITH_GLOG=ON
681702
-DWITH_SNAPPY=ON
682703
-DBUILD_SHARED_LIBS=OFF
683704
-DDOWNLOAD_GTEST=OFF
705+
-DCMAKE_EXE_LINKER_FLAGS=-L${INSTALL_LIBDIR}\ -L${INSTALL_LIBDIR_64}
684706
BUILD_ALWAYS
685707
1
686708
BUILD_COMMAND
687709
make -j${CPU_CORE}
688710
)
689711

712+
# Fix the installed header file after brpc installation
713+
# This is needed because braft uses the installed headers, not the patched source
714+
# The __const__ macro in butil/errno.h conflicts with glibc 2.38+ / GCC 13+
715+
ExternalProject_Add_Step(brpc fix_installed_headers
716+
COMMAND sh -c "sed -i.bak 's/#ifndef __const__/#if 0 /' ${INSTALL_INCLUDEDIR}/butil/errno.h && cat ${INSTALL_INCLUDEDIR}/butil/errno.h | head -35"
717+
DEPENDEES install
718+
COMMENT "Patching installed brpc headers for GCC 13+ compatibility"
719+
)
720+
690721
if(${OS_VERSION} MATCHES "Rocky" OR ${OS_VERSION} MATCHES "CentOS")
691722
set(BRPC_LIBRARY ${INSTALL_LIBDIR_64}/libbrpc.a)
692723
else()

ci/Dockerfile

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,43 @@
1-
FROM ubuntu:22.04
1+
FROM ubuntu:20.04
22

3+
ENV DEBIAN_FRONTEND=noninteractive
4+
ENV TZ=Asia/Shanghai
5+
6+
# 设置 TMPDIR 到工作目录,避免 /tmp 空间不足
7+
ENV TMPDIR=/work/tmp
8+
RUN mkdir -p $TMPDIR
9+
10+
# 安装基础工具 + gcc-9 + protobuf + cmake
311
RUN apt-get update && apt-get install -y \
12+
build-essential \
13+
gcc-9 g++-9 \
14+
git \
15+
autoconf \
16+
libssl-dev \
17+
libprotobuf-dev \
18+
libgflags-dev \
19+
protobuf-compiler \
20+
curl \
421
ca-certificates \
5-
rsync && \
6-
apt-get clean && \
7-
rm -rf /var/lib/apt/lists /var/cache/apt/archives
8-
9-
ENV PIKA=/pika \
10-
PATH=${PIKA}:${PIKA}/bin:${PATH}
22+
python3 \
23+
&& rm -rf /var/lib/apt/lists/*
1124

12-
WORKDIR ${PIKA}
25+
# 安装新版 CMake >= 3.18
26+
RUN curl -fsSL https://github.com/Kitware/CMake/releases/download/v3.27.9/cmake-3.27.9-linux-x86_64.tar.gz \
27+
| tar -xz -C /opt && \
28+
ln -s /opt/cmake-3.27.9-linux-x86_64/bin/cmake /usr/local/bin/cmake
1329

14-
COPY artifact/pika ${PIKA}/bin/pika
15-
COPY entrypoint.sh /entrypoint.sh
16-
COPY conf/pika.conf ${PIKA}/conf/pika.conf
30+
# Go 1.19
31+
RUN curl -fsSL https://go.dev/dl/go1.19.linux-amd64.tar.gz | tar -C /usr/local -xz
32+
ENV PATH=/usr/local/go/bin:$PATH
1733

18-
ENTRYPOINT ["/entrypoint.sh"]
34+
ENV CC=gcc-9
35+
ENV CXX=g++-9
1936

20-
EXPOSE 9221
37+
WORKDIR /work
38+
COPY . /work
2139

22-
CMD ["/pika/bin/pika", "-c", "/pika/conf/pika.conf"]
40+
# 构建 Pika + braft
41+
RUN mkdir -p build && cd build && \
42+
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="-g0" && \
43+
make -j2

docs/raft_implementation_review.md

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
# Pika Raft 模式实现 Review 文档
2+
3+
## 1. 概述
4+
5+
Pika 的 Raft 模式基于 [braft](https://github.com/baidu/braft) 实现分布式一致性,使用 brpc 进行节点间通信。
6+
7+
**核心特性**
8+
- 强一致性保证
9+
- 自动 Leader 选举
10+
- 基于 RocksDB Checkpoint 的快照机制
11+
12+
## 2. 架构概览
13+
14+
```
15+
┌─────────────────────────────────────────────────────┐
16+
│ Pika Server │
17+
├─────────────────────────────────────────────────────┤
18+
│ Client Request → RaftManager → PikaRaftNode │
19+
│ ↓ │
20+
│ braft::Node │
21+
│ ↓ │
22+
│ PikaStateMachine │
23+
│ ↓ │
24+
│ Storage::OnBinlogWrite() │
25+
│ ↓ │
26+
│ RocksDB │
27+
└─────────────────────────────────────────────────────┘
28+
```
29+
30+
## 3. 核心组件
31+
32+
| 组件 | 文件 | 职责 |
33+
|------|------|------|
34+
| `RaftManager` | [praft.h](../src/praft/include/praft/praft.h) | 管理多个 Raft 节点(每个 DB 一个) |
35+
| `PikaRaftNode` | [praft.h](../src/praft/include/praft/praft.h) | 封装 braft::Node,提供日志追加接口 |
36+
| `PikaStateMachine` | [praft.cc](../src/praft/src/praft.cc) | 实现状态机,处理日志应用和快照 |
37+
| `PPosixFileSystemAdaptor` | [psnapshot.cc](../src/praft/src/psnapshot.cc) | 快照文件系统适配器 |
38+
39+
## 4. 数据流
40+
41+
### 写入流程
42+
1. 客户端发送写命令
43+
2. Storage 层构建 Binlog(Protobuf 格式)
44+
3. 通过 `PikaRaftNode::AppendLog()` 提交到 Raft
45+
4. braft 复制日志到多数节点
46+
5. 提交后 `PikaStateMachine::on_apply()` 被调用
47+
6. 调用 `Storage::OnBinlogWrite()` 写入 RocksDB
48+
49+
### Binlog 格式
50+
51+
定义在 [binlog.proto](../src/praft/src/binlog.proto)
52+
- 支持数据类型:Strings, Hashes, Lists, Sets, ZSets, Streams
53+
- 操作类型:Put, Delete
54+
55+
## 5. 快照机制
56+
57+
- 使用 RocksDB Checkpoint 创建快照
58+
- 快照恢复点基于 `GetSmallestFlushedLogIndex()`
59+
- 通过 `LogIndexOfColumnFamilies` 追踪各 CF 的日志应用进度
60+
61+
## 6. 配置选项
62+
63+
| 配置项 | 默认值 | 说明 |
64+
|--------|--------|------|
65+
| `raft_enabled` | false | 是否启用 Raft |
66+
| `raft_group_id` | "" | Raft Group ID |
67+
| `raft_election_timeout_ms` | 1000 | 选举超时(ms) |
68+
| `raft_snapshot_interval_s` | 3600 | 快照间隔(s) |
69+
70+
## 7. Review 重点
71+
72+
### 正确性
73+
- **日志幂等性**: `IsApplied()` 检查是否已应用,防止重复应用
74+
- **快照一致性**: 使用最小 flushed_log_index 确定快照点
75+
- **WAL 禁用**: Raft 日志提供持久性保证,RocksDB WAL 被禁用
76+
77+
### 性能
78+
- 同步写入等待 Raft 提交(可优化为批量提交)
79+
- Binlog 使用 Protobuf 序列化
80+
81+
### 线程安全
82+
- `LogIndexOfColumnFamilies` 使用 mutex 保护
83+
- braft 保证 `on_apply()` 顺序调用
84+
85+
## 8. 关键代码位置
86+
87+
| 功能 | 文件 |
88+
|------|------|
89+
| 日志应用 | [praft.cc](../src/praft/src/praft.cc) - `on_apply()` |
90+
| Binlog 处理 | [storage.cc](../src/storage/src/storage.cc) - `OnBinlogWrite()` |
91+
| Log Index 追踪 | [log_index.cc](../src/storage/src/log_index.cc) |
92+
| 快照创建 | [psnapshot.cc](../src/praft/src/psnapshot.cc) |
93+
| Raft 命令 | [pika_raft.cc](../src/pika_raft.cc) |

include/pika_db.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ class DB : public std::enable_shared_from_this<DB>, public pstd::noncopyable {
9494
std::shared_ptr<storage::Storage> storage() const;
9595
void GetBgSaveMetaData(std::vector<std::string>* fileNames, std::string* snapshot_uuid);
9696
void BgSaveDB();
97+
pstd::Status CreateCheckpoint(const std::string& checkpoint_dir);
98+
pstd::Status LoadDBFromCheckpoint(const std::string& checkpoint_dir);
9799
void SetBinlogIoError();
98100
void SetBinlogIoErrorrelieve();
99101
bool IsBinlogIoError();

include/pika_server.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ enum TaskType {
7171
kCompactRangeSets,
7272
kCompactRangeZSets,
7373
kCompactRangeList,
74+
kLoadDBFromCheckpoint,
75+
kCreateCheckpoint,
7476
};
7577

7678
struct TaskArg {

0 commit comments

Comments
 (0)