mirror of
https://github.com/facebook/rocksdb.git
synced 2026-07-07 14:47:40 +08:00
5ba6eb5497
Summary: Introduces the "blog" file format (portmanteau of "blob" + "log"), a new unified file format for WAL and blob files in RocksDB. This change makes the new format an opt-in option for blob files ONLY. An immediate follow-up will add WAL support. This format is intended to be the future default for both WAL and blob files, and likely also manifest files. The impetus for this new file format was an apparent convergence in requirements for interesting and useful future directions for RocksDB, along with some tech debt: * Supporting blob "direct write" (key-value separation in the memtable) with WAL enabled and at least the option to have all the WAL+blob data go into one file to reduce overheads in some cases like WAL sync write with blob direct write. (In other cases, separating WAL WriteBatches and blobs into distinct files would likely be the better choice.) The "preamble start" marker record is intended to support this case so that WriteBatches can carry external values in a "preamble" in memory and the WriteBatch doesn't need to be rewritten on storage to a single blog file serving both WAL and blob functions. (Details in later work.) * Preserve the continuity of each blob value for efficient reads (NOTE: WAL/Manifest format often breaks up payloads), and extend this continuity to WriteBatches so that keys/values with known checksums could be carried and extended to the WriteBatch and its contiguous encoding in the blog-as-WAL file. (The goal is to leverage checksums across layers as much as possible rather than computing new ones at each layer; only CRC checksums are "extendable.") * Support some "linear log" workloads with monotonically increasing keys and FIFO pruning of old data. A CF could be configured to use its own blog-as-WAL files writing this data, and those files could get indexing information written to them as each file is sealed. This would enable moderately efficient read queries that process WriteBatch records for results, and no WAL->SST write amplification. * Modernize blog and WAL formats with features like explicit versioning and extensibility, configurable and context-aware checksums, debugging and statistical information, customizable compression (CompressionManager aware), and more. New DB options: use_blog_format_for_blobs, blog_checksum. Other public API changes: * ChecksumType moved to include/rocksdb/checksum_type.h. * kStreamingCompressionSentinel (0x7F) added to CompressionType enum. Some included refactoring: * BlobLogWriter::log_number_ removed (was unused). * BlobLogWriter::AppendFooter renamed to LegacyAppendFooterAndClose. Test Plan: TODO
96 lines
3.8 KiB
C++
96 lines
3.8 KiB
C++
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
// This source code is licensed under both the GPLv2 (found in the
|
|
// COPYING file in the root directory) and Apache 2.0 License
|
|
// (found in the LICENSE.Apache file in the root directory).
|
|
|
|
#pragma once
|
|
|
|
#include <cstdint>
|
|
#include <memory>
|
|
#include <string>
|
|
|
|
#include "db/blog/blog_format.h"
|
|
#include "file/writable_file_writer.h"
|
|
#include "rocksdb/io_status.h"
|
|
#include "rocksdb/options.h"
|
|
|
|
namespace ROCKSDB_NAMESPACE {
|
|
|
|
// Writes blog-format files (WAL or blob). The caller constructs a
|
|
// BlogFileHeader, calls WriteHeader(), then adds records via
|
|
// AddBlobRecord/AddWriteBatchRecord, and optionally appends footer records
|
|
// before closing.
|
|
//
|
|
// Format selection (compact vs full) is automatic based on payload size and
|
|
// record type. See blog_format.h for the wire format details.
|
|
class BlogFileWriter {
|
|
public:
|
|
BlogFileWriter(std::unique_ptr<WritableFileWriter>&& dest,
|
|
const BlogFileHeader& header, bool manual_flush = false);
|
|
~BlogFileWriter();
|
|
|
|
// Write the file header. Must be called exactly once, before any records.
|
|
IOStatus WriteHeader(const WriteOptions& wo);
|
|
|
|
// Write a blob record. Selects compact or full format automatically.
|
|
// On success, *blob_offset is the file offset of the payload start.
|
|
IOStatus AddBlobRecord(const WriteOptions& wo, const Slice& payload,
|
|
CompressionType comp_type, uint64_t* blob_offset);
|
|
|
|
// Write a WriteBatch record. Selects compact or full format automatically.
|
|
IOStatus AddWriteBatchRecord(const WriteOptions& wo, const Slice& wb_data,
|
|
CompressionType comp_type = kNoCompression);
|
|
|
|
// Write a preamble-start record (stub). Uses full format with length=0.
|
|
IOStatus AddPreambleStartRecord(const WriteOptions& wo);
|
|
|
|
// Write a footer index record (full format).
|
|
IOStatus AddFooterIndexRecord(const WriteOptions& wo,
|
|
const Slice& index_data);
|
|
|
|
// Write a footer properties record (full format).
|
|
IOStatus AddFooterPropertiesRecord(const WriteOptions& wo,
|
|
const BlogFileFooterProperties& props);
|
|
|
|
// Write a footer locator record (full format). Must be the last record.
|
|
IOStatus AddFooterLocatorRecord(const WriteOptions& wo,
|
|
const BlogFileFooterLocator& locator);
|
|
|
|
IOStatus WriteBuffer(const WriteOptions& wo);
|
|
IOStatus Sync(const WriteOptions& wo, bool use_fsync = false);
|
|
IOStatus Close(const WriteOptions& wo);
|
|
|
|
uint64_t current_offset() const { return offset_; }
|
|
WritableFileWriter* file() { return dest_.get(); }
|
|
const BlogFileHeader& header() const { return header_; }
|
|
|
|
private:
|
|
// Write a record. Chooses compact format when varint fits in <= 3 bytes
|
|
// and type matches compact_record_type, unless force_full is true.
|
|
IOStatus AddRecord(const WriteOptions& wo, BlogRecordType type,
|
|
const Slice& payload, CompressionType comp_type,
|
|
uint64_t* payload_offset, bool force_full = false);
|
|
|
|
// Emit a compact-format record.
|
|
IOStatus EmitCompactRecord(const WriteOptions& wo, const Slice& payload,
|
|
CompressionType comp_type,
|
|
uint64_t* payload_offset);
|
|
|
|
// Emit a full-format record.
|
|
IOStatus EmitFullRecord(const WriteOptions& wo, BlogRecordType type,
|
|
const Slice& payload, CompressionType comp_type,
|
|
uint64_t* payload_offset);
|
|
|
|
// Append raw bytes to the file and advance offset_.
|
|
IOStatus EmitBytes(const WriteOptions& wo, const Slice& data);
|
|
IOStatus EmitBytes(const WriteOptions& wo, const char* data, size_t len);
|
|
|
|
std::unique_ptr<WritableFileWriter> dest_;
|
|
BlogFileHeader header_;
|
|
uint64_t offset_ = 0;
|
|
bool manual_flush_;
|
|
bool header_written_ = false;
|
|
};
|
|
|
|
} // namespace ROCKSDB_NAMESPACE
|