mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-10-26 15:00:48 +01:00
rust volume: group-commit fsync uploads on the direct write path (#11860)
* rust volume: group-commit fsync uploads on the direct write path Each fsync=true upload used to run its own .dat/.idx sync when the write queue was off, which is the default. Route durable uploads through the per-volume write workers so a batch shares one sync, matching Go's writeNeedle2: non-fsync writes, and writes while the server is stopping, stay on the synchronous path. The queue is now always constructed and SEAWEED_WRITE_QUEUE is gone. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> * rust volume: document post_handler write routing Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> --------- Co-authored-by: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
1 parent
8d2b417c69
commit
1144bf15d4
8 files changed
+103
-25
No files matched your search
@@ -1,7 +1,8 @@
|
||||
//! Async batched write processing for the volume server.
|
||||
//!
|
||||
//! Instead of each upload handler directly calling `write_needle`, writes are
|
||||
//! submitted to a queue. Each volume gets its own FIFO worker (Go's
|
||||
//! Durable (fsync) uploads are submitted here instead of each handler calling
|
||||
//! `write_needle` directly — Go's `writeNeedle2` makes the same split, so the
|
||||
//! queue is always constructed. Each volume gets its own FIFO worker (Go's
|
||||
//! volume_write.go keeps one batching worker per volume), which drains its
|
||||
//! channel in batches of up to 128 entries or 4 MiB and shares the .dat/.idx
|
||||
//! flushes across durable writes (see `Volume::write_needles_grouped`).
|
||||
@@ -66,6 +67,9 @@ pub struct WriteQueue {
|
||||
/// alone would multiply the old single queue's capacity by volume count.
|
||||
queue_permits: Arc<Semaphore>,
|
||||
workers: Arc<Mutex<HashMap<VolumeId, mpsc::Sender<WriteRequest>>>>,
|
||||
/// Submissions accepted, for tests asserting which writes route here.
|
||||
#[cfg(test)]
|
||||
submits: Arc<std::sync::atomic::AtomicU64>,
|
||||
}
|
||||
|
||||
impl WriteQueue {
|
||||
@@ -78,9 +82,17 @@ impl WriteQueue {
|
||||
io_permits: Arc::new(Semaphore::new(MAX_CONCURRENT_VOLUME_WRITES)),
|
||||
queue_permits: Arc::new(Semaphore::new(capacity)),
|
||||
workers: Arc::new(Mutex::new(HashMap::new())),
|
||||
#[cfg(test)]
|
||||
submits: Arc::new(std::sync::atomic::AtomicU64::new(0)),
|
||||
}
|
||||
}
|
||||
|
||||
/// How many writes were submitted, for tests asserting upload routing.
|
||||
#[cfg(test)]
|
||||
pub fn submits_for_test(&self) -> u64 {
|
||||
self.submits.load(std::sync::atomic::Ordering::Relaxed)
|
||||
}
|
||||
|
||||
/// Sender for the volume's worker, spawning one on first use.
|
||||
fn worker_for(&self, volume_id: VolumeId) -> mpsc::Sender<WriteRequest> {
|
||||
let mut workers = self.workers.lock().unwrap();
|
||||
@@ -110,6 +122,9 @@ impl WriteQueue {
|
||||
pub async fn submit(&self, volume_id: VolumeId, needle: Needle, fsync: bool) -> WriteResult {
|
||||
// Workers spawn only for mounted volumes — a bogus id never creates
|
||||
// a channel, so volume-id sprays can't grow the worker map.
|
||||
#[cfg(test)]
|
||||
self.submits
|
||||
.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
|
||||
{
|
||||
let store = self.state.store.read().unwrap();
|
||||
if store.find_volume(volume_id).is_none() {
|
||||
|
||||
Reference in new issue
Block a user