mirror of https://github.com/facebook/rocksdb.git
BlobDB: is_fifo=true also evict non-TTL blob files (#4049)
Summary: Previously with is_fifo=true we only evict TTL file. Changing it to also evict non-TTL files from oldest to newest, after exhausted TTL files. Closes https://github.com/facebook/rocksdb/pull/4049 Differential Revision: D8604597 Pulled By: yiwu-arbug fbshipit-source-id: bc4209ee27c1528ce4b72833e6f1e1bff80082c1
This commit is contained in:
parent
189f0c27aa
commit
6d454d7376
|
@ -38,9 +38,7 @@ struct BlobDBOptions {
|
||||||
|
|
||||||
// When max_db_size is reached, evict blob files to free up space
|
// When max_db_size is reached, evict blob files to free up space
|
||||||
// instead of returnning NoSpace error on write. Blob files will be
|
// instead of returnning NoSpace error on write. Blob files will be
|
||||||
// evicted in this order until enough space is free up:
|
// evicted from oldest to newest, based on file creation time.
|
||||||
// * the TTL blob file cloeset to expire,
|
|
||||||
// * the oldest non-TTL blob file.
|
|
||||||
bool is_fifo = false;
|
bool is_fifo = false;
|
||||||
|
|
||||||
// Maximum size of the database (including SST files and blob files).
|
// Maximum size of the database (including SST files and blob files).
|
||||||
|
|
|
@ -52,7 +52,14 @@ WalFilter::WalProcessingOption BlobReconcileWalFilter::LogRecordFound(
|
||||||
return WalFilter::WalProcessingOption::kContinueProcessing;
|
return WalFilter::WalProcessingOption::kContinueProcessing;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool blobf_compare_ttl::operator()(const std::shared_ptr<BlobFile>& lhs,
|
bool BlobFileComparator::operator()(
|
||||||
|
const std::shared_ptr<BlobFile>& lhs,
|
||||||
|
const std::shared_ptr<BlobFile>& rhs) const {
|
||||||
|
return lhs->BlobFileNumber() > rhs->BlobFileNumber();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BlobFileComparatorTTL::operator()(
|
||||||
|
const std::shared_ptr<BlobFile>& lhs,
|
||||||
const std::shared_ptr<BlobFile>& rhs) const {
|
const std::shared_ptr<BlobFile>& rhs) const {
|
||||||
assert(lhs->HasTTL() && rhs->HasTTL());
|
assert(lhs->HasTTL() && rhs->HasTTL());
|
||||||
if (lhs->expiration_range_.first < rhs->expiration_range_.first) {
|
if (lhs->expiration_range_.first < rhs->expiration_range_.first) {
|
||||||
|
@ -852,14 +859,9 @@ Status BlobDBImpl::CheckSizeAndEvictBlobFiles(uint64_t blob_size,
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::shared_ptr<BlobFile>> candidate_files;
|
std::vector<std::shared_ptr<BlobFile>> candidate_files;
|
||||||
CopyBlobFiles(&candidate_files,
|
CopyBlobFiles(&candidate_files);
|
||||||
[&](const std::shared_ptr<BlobFile>& blob_file) {
|
|
||||||
// Only evict TTL files
|
|
||||||
return blob_file->HasTTL();
|
|
||||||
});
|
|
||||||
std::sort(candidate_files.begin(), candidate_files.end(),
|
std::sort(candidate_files.begin(), candidate_files.end(),
|
||||||
blobf_compare_ttl());
|
BlobFileComparator());
|
||||||
std::reverse(candidate_files.begin(), candidate_files.end());
|
|
||||||
fifo_eviction_seq_ = GetLatestSequenceNumber();
|
fifo_eviction_seq_ = GetLatestSequenceNumber();
|
||||||
|
|
||||||
WriteLock l(&mutex_);
|
WriteLock l(&mutex_);
|
||||||
|
@ -887,10 +889,9 @@ Status BlobDBImpl::CheckSizeAndEvictBlobFiles(uint64_t blob_size,
|
||||||
"Evict oldest blob file since DB out of space. Current "
|
"Evict oldest blob file since DB out of space. Current "
|
||||||
"live SST file size: %" PRIu64 ", total blob size: %" PRIu64
|
"live SST file size: %" PRIu64 ", total blob size: %" PRIu64
|
||||||
", max db size: %" PRIu64 ", evicted blob file #%" PRIu64
|
", max db size: %" PRIu64 ", evicted blob file #%" PRIu64
|
||||||
" with expiration range (%" PRIu64 ", %" PRIu64 ").",
|
".",
|
||||||
live_sst_size, total_blob_size_.load(),
|
live_sst_size, total_blob_size_.load(),
|
||||||
bdb_options_.max_db_size, blob_file->BlobFileNumber(),
|
bdb_options_.max_db_size, blob_file->BlobFileNumber());
|
||||||
expiration_range.first, expiration_range.second);
|
|
||||||
ObsoleteBlobFile(blob_file, fifo_eviction_seq_, true /*update_size*/);
|
ObsoleteBlobFile(blob_file, fifo_eviction_seq_, true /*update_size*/);
|
||||||
evict_expiration_up_to_ = expiration_range.first;
|
evict_expiration_up_to_ = expiration_range.first;
|
||||||
RecordTick(statistics_, BLOB_DB_FIFO_NUM_FILES_EVICTED);
|
RecordTick(statistics_, BLOB_DB_FIFO_NUM_FILES_EVICTED);
|
||||||
|
@ -1741,19 +1742,11 @@ std::pair<bool, int64_t> BlobDBImpl::DeleteObsoleteFiles(bool aborted) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlobDBImpl::CopyBlobFiles(
|
void BlobDBImpl::CopyBlobFiles(
|
||||||
std::vector<std::shared_ptr<BlobFile>>* bfiles_copy,
|
std::vector<std::shared_ptr<BlobFile>>* bfiles_copy) {
|
||||||
std::function<bool(const std::shared_ptr<BlobFile>&)> predicate) {
|
|
||||||
ReadLock rl(&mutex_);
|
ReadLock rl(&mutex_);
|
||||||
|
|
||||||
for (auto const& p : blob_files_) {
|
for (auto const& p : blob_files_) {
|
||||||
bool pred_value = true;
|
|
||||||
if (predicate) {
|
|
||||||
pred_value = predicate(p.second);
|
|
||||||
}
|
|
||||||
if (pred_value) {
|
|
||||||
bfiles_copy->push_back(p.second);
|
bfiles_copy->push_back(p.second);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<bool, int64_t> BlobDBImpl::RunGC(bool aborted) {
|
std::pair<bool, int64_t> BlobDBImpl::RunGC(bool aborted) {
|
||||||
|
|
|
@ -64,7 +64,12 @@ class BlobReconcileWalFilter : public WalFilter {
|
||||||
|
|
||||||
// Comparator to sort "TTL" aware Blob files based on the lower value of
|
// Comparator to sort "TTL" aware Blob files based on the lower value of
|
||||||
// TTL range.
|
// TTL range.
|
||||||
struct blobf_compare_ttl {
|
struct BlobFileComparatorTTL {
|
||||||
|
bool operator()(const std::shared_ptr<BlobFile>& lhs,
|
||||||
|
const std::shared_ptr<BlobFile>& rhs) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BlobFileComparator {
|
||||||
bool operator()(const std::shared_ptr<BlobFile>& lhs,
|
bool operator()(const std::shared_ptr<BlobFile>& lhs,
|
||||||
const std::shared_ptr<BlobFile>& rhs) const;
|
const std::shared_ptr<BlobFile>& rhs) const;
|
||||||
};
|
};
|
||||||
|
@ -315,9 +320,7 @@ class BlobDBImpl : public BlobDB {
|
||||||
bool VisibleToActiveSnapshot(const std::shared_ptr<BlobFile>& file);
|
bool VisibleToActiveSnapshot(const std::shared_ptr<BlobFile>& file);
|
||||||
bool FileDeleteOk_SnapshotCheckLocked(const std::shared_ptr<BlobFile>& bfile);
|
bool FileDeleteOk_SnapshotCheckLocked(const std::shared_ptr<BlobFile>& bfile);
|
||||||
|
|
||||||
void CopyBlobFiles(
|
void CopyBlobFiles(std::vector<std::shared_ptr<BlobFile>>* bfiles_copy);
|
||||||
std::vector<std::shared_ptr<BlobFile>>* bfiles_copy,
|
|
||||||
std::function<bool(const std::shared_ptr<BlobFile>&)> predicate = {});
|
|
||||||
|
|
||||||
uint64_t EpochNow() { return env_->NowMicros() / 1000000; }
|
uint64_t EpochNow() { return env_->NowMicros() / 1000000; }
|
||||||
|
|
||||||
|
@ -373,7 +376,7 @@ class BlobDBImpl : public BlobDB {
|
||||||
|
|
||||||
// all the blob files which are currently being appended to based
|
// all the blob files which are currently being appended to based
|
||||||
// on variety of incoming TTL's
|
// on variety of incoming TTL's
|
||||||
std::set<std::shared_ptr<BlobFile>, blobf_compare_ttl> open_ttl_files_;
|
std::set<std::shared_ptr<BlobFile>, BlobFileComparatorTTL> open_ttl_files_;
|
||||||
|
|
||||||
// Flag to check whether Close() has been called on this DB
|
// Flag to check whether Close() has been called on this DB
|
||||||
bool closed_;
|
bool closed_;
|
||||||
|
|
|
@ -1120,7 +1120,7 @@ TEST_F(BlobDBTest, FIFOEviction) {
|
||||||
|
|
||||||
ASSERT_EQ(1, blob_db_impl()->TEST_GetBlobFiles().size());
|
ASSERT_EQ(1, blob_db_impl()->TEST_GetBlobFiles().size());
|
||||||
|
|
||||||
// Adding another 100 byte blob would take the total size to 264 bytes
|
// Adding another 100 bytes blob would take the total size to 264 bytes
|
||||||
// (2*132). max_db_size will be exceeded
|
// (2*132). max_db_size will be exceeded
|
||||||
// than max_db_size and trigger FIFO eviction.
|
// than max_db_size and trigger FIFO eviction.
|
||||||
ASSERT_OK(blob_db_->PutWithTTL(WriteOptions(), "key2", value, 60));
|
ASSERT_OK(blob_db_->PutWithTTL(WriteOptions(), "key2", value, 60));
|
||||||
|
@ -1128,18 +1128,34 @@ TEST_F(BlobDBTest, FIFOEviction) {
|
||||||
// key1 will exist until corresponding file be deleted.
|
// key1 will exist until corresponding file be deleted.
|
||||||
VerifyDB({{"key1", value}, {"key2", value}});
|
VerifyDB({{"key1", value}, {"key2", value}});
|
||||||
|
|
||||||
|
// Adding another 100 bytes blob without TTL.
|
||||||
|
ASSERT_OK(blob_db_->Put(WriteOptions(), "key3", value));
|
||||||
|
ASSERT_EQ(2, evict_count);
|
||||||
|
// key1 and key2 will exist until corresponding file be deleted.
|
||||||
|
VerifyDB({{"key1", value}, {"key2", value}, {"key3", value}});
|
||||||
|
|
||||||
|
// The fourth blob file, without TTL.
|
||||||
|
ASSERT_OK(blob_db_->Put(WriteOptions(), "key4", value));
|
||||||
|
ASSERT_EQ(3, evict_count);
|
||||||
|
VerifyDB(
|
||||||
|
{{"key1", value}, {"key2", value}, {"key3", value}, {"key4", value}});
|
||||||
|
|
||||||
auto blob_files = blob_db_impl()->TEST_GetBlobFiles();
|
auto blob_files = blob_db_impl()->TEST_GetBlobFiles();
|
||||||
ASSERT_EQ(2, blob_files.size());
|
ASSERT_EQ(4, blob_files.size());
|
||||||
ASSERT_TRUE(blob_files[0]->Obsolete());
|
ASSERT_TRUE(blob_files[0]->Obsolete());
|
||||||
ASSERT_FALSE(blob_files[1]->Obsolete());
|
ASSERT_TRUE(blob_files[1]->Obsolete());
|
||||||
|
ASSERT_TRUE(blob_files[2]->Obsolete());
|
||||||
|
ASSERT_FALSE(blob_files[3]->Obsolete());
|
||||||
auto obsolete_files = blob_db_impl()->TEST_GetObsoleteFiles();
|
auto obsolete_files = blob_db_impl()->TEST_GetObsoleteFiles();
|
||||||
ASSERT_EQ(1, obsolete_files.size());
|
ASSERT_EQ(3, obsolete_files.size());
|
||||||
ASSERT_EQ(blob_files[0], obsolete_files[0]);
|
ASSERT_EQ(blob_files[0], obsolete_files[0]);
|
||||||
|
ASSERT_EQ(blob_files[1], obsolete_files[1]);
|
||||||
|
ASSERT_EQ(blob_files[2], obsolete_files[2]);
|
||||||
|
|
||||||
blob_db_impl()->TEST_DeleteObsoleteFiles();
|
blob_db_impl()->TEST_DeleteObsoleteFiles();
|
||||||
obsolete_files = blob_db_impl()->TEST_GetObsoleteFiles();
|
obsolete_files = blob_db_impl()->TEST_GetObsoleteFiles();
|
||||||
ASSERT_TRUE(obsolete_files.empty());
|
ASSERT_TRUE(obsolete_files.empty());
|
||||||
VerifyDB({{"key2", value}});
|
VerifyDB({{"key4", value}});
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(BlobDBTest, FIFOEviction_NoOldestFileToEvict) {
|
TEST_F(BlobDBTest, FIFOEviction_NoOldestFileToEvict) {
|
||||||
|
|
|
@ -23,7 +23,8 @@ class BlobDBImpl;
|
||||||
|
|
||||||
class BlobFile {
|
class BlobFile {
|
||||||
friend class BlobDBImpl;
|
friend class BlobDBImpl;
|
||||||
friend struct blobf_compare_ttl;
|
friend struct BlobFileComparator;
|
||||||
|
friend struct BlobFileComparatorTTL;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// access to parent
|
// access to parent
|
||||||
|
|
Loading…
Reference in New Issue