Closed Pyolar closed 6 months ago
Persister类里面的 long long m_raftStateSize; 其他函数里面没有及时更新,导致kvserver类里面的IfNeedToSendSnapShotCommand一直没被触发,是不是会导致不能生成快照,我本地跑起来,快照的txt文件也确实是空的,这个有什么考虑吗?
@Pyolar
在原来的设计中m_raftStateSize这块确实存在问题,目前已经修改了相关的逻辑,应该是可以正常更新m_raftStateSize的值了,更新pr:#56
关于“是不是会导致不能生成快照,我本地跑起来,快照的txt文件也确实是空的,这个有什么考虑吗?”,这块其实没有太多的考虑,出于两点: a. 快照是对于算法保存内容的压缩优化,在学习中重要些不是特别高。 b. 在mit课程中也没有对这块有强制性的设计要求,本仓库代码为了正确性还是“翻译”mit为主,因此这块也没有太多设计考量。
感谢您抽出时间来回答我的问题,不胜感激。但还有个问题需要向您请教: 1.考虑到raft.cpp中,persist高频持久化raftstate,是否会导致raftstate文件中的m_raftStateSize值一直清空,增加,但是增加的很小,导致不能触发快照(快照文件为空),而且raftstatePersist文件也一直为空。快照以及状态文件 2.clearRaftState(); 是否应该是由生成快照后来操作,也就是Save中
56 @578223592 感谢您抽出时间来回答我的问题,不胜感激。但还有个问题需要向您请教: 1.考虑到raft.cpp中,persist高频持久化raftstate,是否会导致raftstate文件中的m_raftStateSize值一直清空,增加,但是增加的很小,导致不能触发快照(快照文件为空),而且raftstatePersist文件也一直为空。快照以及状态文件 2.clearRaftState(); 是否应该是由生成快照后来操作,也就是Save中
不必客气,本仓库的主要目的是学习raft算法,所以细节设计确实很可能会有很不合理的地方,欢迎指正。
void KvServer::IfNeedToSendSnapShotCommand(int raftIndex, int proportion) {
if (m_raftNode->GetRaftStateSize() > m_maxRaftState / 10.0) {
// Send SnapShot Command
auto snapshot = MakeSnapShot();
m_raftNode->Snapshot(raftIndex, snapshot);
}
}
即快照的生成是由raftServer层来负责检测,如果满足生成快照的条件(数据库的数据量达到一定阈值),那么就往下生成快照并保存。 如果文件一直为空,那么应该是数据量还没满足到m_maxRaftState 这个阈值。
@578223592
我之前表述可能不太清楚,我换一种表述:
1.是否存在下述问题:
void Persister::SaveRaftState(const std::string &data) { std::lock_guard<std::mutex> lg(m_mtx); // 将raftstate和snapshot写入本地文件 clearRaftState(); m_raftStateOutStream << data; m_raftStateSize += data.size(); }
Persister类中SaveRaftState的这段代码在raft.cpp中会被persist函数频繁的调用,而persist函数的调用就会清空文件,导致持久化层m_raftStateSize值一直达不到阈值,便不会触发生成快照
2.是否可以这么改:
每次持久化的时候并不一定要重置m_raftStateSize值,而是等生成快照的时候再重置m_raftStateSize值,因为生成快照是和m_raftStateSize值息息相关的。
以上表述如有不对请指出,我理解的也不一定完全正确。
@Pyolar
调用SaveRaftState
函数的是:
void Raft::persist() {
// Your code here (2C).
auto data = persistData();
m_persister->SaveRaftState(data);
// fmt.Printf("RaftNode[%d] persist starts, currentTerm[%d] voteFor[%d] log[%v]\n", rf.me, rf.currentTerm,
// rf.votedFor, rf.logs) fmt.Printf("%v\n", string(data))
}
由于该函数Raft::persist()
每次都是全量生成数据,因此持久化的m_raftStateSize 会在持久化的时候赋值为初始值0。
@578223592 ’全量数据‘ ,瞬间就明白了,谢谢。
@Pyolar 非常高兴哈哈哈,也欢迎对仓库改进pr或者提出更多的问题issue
Persister类里面的 long long m_raftStateSize; 其他函数里面没有及时更新,导致kvserver类里面的IfNeedToSendSnapShotCommand一直没被触发,是不是会导致不能生成快照,我本地跑起来,快照的txt文件也确实是空的,这个有什么考虑吗?