Узким местом всей пикодаты может стать рафт лидер. На нем лежит вся ответственность за рассылку AppendEntries всем остальным инстансам (и воутерам и лернерам). С увеличением размера кластра нагрузка растёт линейно.
В рамках данного тикета надо исследовать, с какой нагрузкой raft_propose_* может справиться лидер пока не упрется в cpu 100%, и как это значение зависит от размера кластера.
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information
Child items
...
Show closed items
Linked items
0
Link issues together to show that they're related.
Learn more.
luamod.set("raft_propose_bench",tlua::function1(|secs:u64|->Result<String,Error>{letstart_at=Instant::now();letdeadline=start_at+Duration::from_secs(secs);letnode=traft::node::global()?;letmutcounter=0;loop{ifInstant::now()>deadline{break;}node.propose(traft::Op::Nop,Duration::from_secs(1))?;counter=counter+1;}letstop_at=Instant::now();letelapsed=(stop_at-start_at).as_micros();Ok(format!("{:.0} iteration per sec",counterasf64/elapsedasf64*1000000.0))}),);
Загрузка CPU соответствовала предполагаемой - лидер утилизировал одно ядро на 100% и очевидно становился узким местом. Фолловеры тоже использовали CPU. При тесте кластера из 2х пиров CPU как лидера так и фолловера было одинаковым - 90%.
Моим ожиданиям это не соответствует. Бенчмарк использует вызов node.propose, который блокирует текущий файбер пока запись не закоммитится. Для 1 инстанса это происходит почти мгновенно, но в остальных случаях требует собирать кворум и ходить по сети. Результаты 1 и 2 инстансов отличаются в 3 раза, это намекает что из кластера можно выжать больше, оптимизировав нагружалку. Для 1 инстанса, я думаю, результат тоже мог бы быть лучше чем 3000 rps.
box.schema.space.create('bench', { if_not_exists = true, is_local = true, format = { {name = 'id', type = 'unsigned', is_nullable = false}, {name = 'value', type = 'unsigned', is_nullable = false} }})box.space.bench:create_index('pk', { if_not_exists = true, parts = {{'id'}}})clock=require('clock')fiber=require('fiber')function f(n) for i=1, n do box.space.bench:replace({1, i}) end endfunction bench_replace(n, c) do local fibers = {}; local t1 = clock.monotonic(); for i=1,c do fibers[i]=fiber.new(f, 1e5) end; for i=1,c do fibers[i]:set_joinable(true) end; for i=1,c do fibers[i]:join() end; local t2 = clock.monotonic(); return string.format("c=%s, n=%s, %.1f sec, %.0f rps", c, n*c, t2-t1, n*c/(t2-t1)) end endbench_replace(1e5, 10)
Может быть выполнен на ванильном тарантуле, на picodata tarantool, на picodata run
Сейчас показывает на моём железе
vanilla tarantool 2.8
350k
vanilla tarantool 2.10
330k
picodata tarantool на master cargo run -r -- tarantool