背景
Pika 实例硬盘容量满,清理数据后,Pika 仍然保持错误的状态,需要重启才能恢复
解决方案
由于 RocksDB 在磁盘满了之后会进入写保护状态,此时不接受任何写请求,所以这种情况下如果 Pika 在清理掉磁盘空间进行接收写请求时,由于 RocksDB 还是处于写保护状态,这时候依然不能进行写响应,我们之前的一个方案是为 Pika 新增加一个线程,每过 5s 对磁盘进行检测,如果在预计容量内,则遍历整个 slot 对写请求状态进行恢复,但是由于这种操作每次需要遍历整个 DB 和 整个 slot,有上锁解锁操作,我们后面决定以一个命令的形式对这一情况进行解决,Diskcovery 命令,这个命令用于恢复对 RocksDB 的写保护状态,同时恢复 Pika 中写 binlog 错误的状态,在当前磁盘容量小于 write-buffer-size 的时候不进行恢复,只有在当前磁盘容量大于 write-buffer-size 的时候进行恢复,这里的 write-buffer-size 指 Memtable 的大小,设置为 256M. 以下是设计方案的代码:
复现方式
我们首先创建一个 1GB 大小的虚拟磁盘 (Centos环境),并查看是否成功
dd if=/dev/zero of=my_virtual_disk.img bs=1G count=1
ls -lh my_virtual_disk.img
- 然后执行命令来对文件进行格式化为特定的文件系统(ext4)
mkfs.ext4 my_virtual_disk.img
- 把虚拟文件系统挂载到目录
/mnt/vfs
sudo mkdir -p /mnt/my_disk
sudo mount -o loop my_virtual_disk.img /mnt/my_disk
df -h
- 我们对 pika.conf 里面的 log-path 和 db-path 进行修改,改成我们创建的虚拟文件系统路径
- 启动 Pika 并进行压测,我们先记录一下压测前磁盘的使用情况
- 等到压测到磁盘上限时我们可以发现此时执行 set 操作(写操作)时已经不能正常执行,我们调用 Diskrecovery 命令可以看到此时的磁盘使用情况(此时这种情况是不能恢复的,因为磁盘 free 的大小小于 write-buffter-size)
- 我们继续更改 pika.conf 的 log-path 和 db-path 然后把 之前的一个 db 文件删掉,继续启动 Pika 进行测试
- 在磁盘再次被打满时,我们依然不能执行 set 操作,此时我们把之前的 db 文件夹删掉,然后执行一次 Diskrecovery 命令,发现再次执行 set 操作时已经可以正常执行了
相关 PR: #1843
相关 Issue: #1150