ЁЯЪ░ рдзрдбрд╛ 09 тАФ Queueing, Little рдЖрдгрд┐ Amdahl: рдкрд╛рдгреНрдпрд╛рдЪреНрдпрд╛ рдЯреЗрдмрд▓рд╛рд╡рд░рдЪреА рд░рд╛рдВрдЧ
ЁЯУН рддреБрдореНрд╣реА рдЗрдереЗ рдЖрд╣рд╛рдд: 12 рдкреИрдХреА рдзрдбрд╛ 09 ┬╖ рдорд╛рдЧреЗ: lesson-08-concurrency ┬╖ рдкреБрдвреЗ: lesson-10-database-queries
ЁЯУж рдпрд╛ рдмреНрд░рдБрдЪрдордзреНрдпреЗ рдХрд╛рдп рдЖрд╣реЗ
рдзрдбреЗ 01тАУ08, рдЖрдгрд┐ busy service рд╕рдордЬрд╛рд╡рдгрд╛рд░реЗ рддреАрди рдирд┐рдпрдо: queueing (server рдЬрд╕рд╛ рдЕрдзрд┐рдХ busy рд╣реЛрддреЛ, рддрд╕реЗ
рдерд╛рдВрдмрдгреЗ рдЖрдзреА рд╣рд│реВ рд╡рд╛рдврддреЗ, рдордЧ рд╕реНрдлреЛрдЯ рд╣реЛрддреЛ), Little's law (рдПрдХрд╛ рд╡реЗрд│реА system рдордзреНрдпреЗ рдХрд┐рддреА requests рдЖрд╣реЗрдд) рдЖрдгрд┐
Amdahl's law (рдЬреЛ рднрд╛рдЧ рд╡рд╛рдЯреВрди рджреЗрддрд╛ рдпреЗрдд рдирд╛рд╣реА рддреЛ speed-up рд▓рд╛ рдорд░реНрдпрд╛рджрд╛ рдШрд╛рд▓рддреЛ).
perf/demo.py рдордзреАрд▓ queueing() рдЖрдгрд┐ perf/sim.py рдордзреАрд▓
mm1_wait_ms, simulate_queue, littles_law рдЖрдгрд┐ amdahl.
ЁЯзТ 5 рд╡рд░реНрд╖рд╛рдВрдЪреНрдпрд╛ рдореБрд▓рд╛рд▓рд╛ рд╕рдордЬрд╛рд╡рд▓реНрдпрд╛рд╕рд╛рд░рдЦреЗ
рдкрд╛рдгреНрдпрд╛рдЪреЗ рдЯреЗрдмрд▓ рдПрдХрдЪ рдЖрд╣реЗ ЁЯЪ░, рдЖрдгрд┐ рдРрд╢реНрд╡рд░реНрдпрд╛рд▓рд╛ рдПрдХ рдХрдк рднрд░рд╛рдпрд▓рд╛ 10 рд╕реЗрдХрдВрдж рд▓рд╛рдЧрддрд╛рдд.
- рдзрд╛рд╡рдкрдЯреВ рдЕрдзреВрдирдордзреВрди рдпреЗрддрд╛рдд рддреЗрд╡реНрд╣рд╛ рдЯреЗрдмрд▓ рдЕрд░реНрдзрд╛ рд╡реЗрд│ рдореЛрдХрд│реЗ рдЕрд╕рддреЗ. рдзрд╛рд╡рдкрдЯреВ рдереЛрдбреЗрдЪ рдерд╛рдВрдмрддреЗ: рдХрдкрд╛рд╕рд╣ рд╕реБрдорд╛рд░реЗ 20 рд╕реЗрдХрдВрдж.
- рдзрд╛рд╡рдкрдЯреВ рд╡рд╛рд░рдВрд╡рд╛рд░ рдпреЗрддрд╛рдд, рдЖрдгрд┐ рдЯреЗрдмрд▓ 90% рд╡реЗрд│ busy рдЕрд╕рддреЗ, рддреЗрд╡реНрд╣рд╛ рдзрд╛рд╡рдкрдЯреВ рд╕реБрдорд╛рд░реЗ 100 рд╕реЗрдХрдВрдж рдерд╛рдВрдмрддреЗ.
- 99% busy рдЕрд╕рддрд╛рдирд╛: рд╕реБрдорд╛рд░реЗ 1000. ЁЯШ▒
рдЗрддрдХреЗ рд╡рд╛рдИрдЯ, рдЗрддрдХреНрдпрд╛ рд▓рд╡рдХрд░ рдХрд╛ рд╣реЛрддреЗ? рдХрд╛рд░рдг рдзрд╛рд╡рдкрдЯреВ рд╕рдорд╛рди рдЕрдВрддрд░рд╛рдиреЗ рдпреЗрдд рдирд╛рд╣реАрдд. рдХрдзреА рдХрдзреА рддрд┐рдШреА рдПрдХрджрдо рдпреЗрддрд╛рдд. рдЯреЗрдмрд▓ рдЬрд╡рд│рдЬрд╡рд│ рдиреЗрд╣рдореА busy рдЕрд╕реЗрд▓ рддрд░ рддреНрдпрд╛ рдЧрд░реНрджреА рднрд░реВрди рдХрд╛рдврдгреНрдпрд╛рд╕рд╛рдареА рддреНрдпрд╛рд▓рд╛ рдХрдзреАрдЪ рд╢рд╛рдВрдд рдХреНрд╖рдг рдорд┐рд│рдд рдирд╛рд╣реА.
рдХреНрд░реАрдбрд╛ рджрд┐рдирд╛рдЪреЗ рдЖрдгрдЦреА рджреЛрди рдирд┐рдпрдо:
- Little рдЪрд╛ рдирд┐рдпрдо: рджрд░ рд╕реЗрдХрдВрджрд╛рд▓рд╛ 80 рдзрд╛рд╡рдкрдЯреВ рдпреЗрдд рдЕрд╕рддреАрд▓ рдЖрдгрд┐ рдкреНрд░рддреНрдпреЗрдХ рдЬрдг рдЯреЗрдмрд▓рд╛рдЬрд╡рд│ 0.05 рд╕реЗрдХрдВрдж рдШрд╛рд▓рд╡рдд рдЕрд╕реЗрд▓, рддрд░ рд╕рд░рд╛рд╕рд░реА 4 рдзрд╛рд╡рдкрдЯреВ рдЯреЗрдмрд▓рд╛рдЬрд╡рд│ рдЕрд╕рддрд╛рдд.
- рд╕рд░реНрд╡рд╛рдд рд╣рд│реВ рдЯрдкреНрдкреНрдпрд╛рдЪрд╛ рдирд┐рдпрдо (Amdahl): рд░рд┐рд▓реЗрдордзреНрдпреЗ рд╢рд░реНрдпрддреАрдЪрд╛ 90% рднрд╛рдЧ рдЕрдиреЗрдХ рдзрд╛рд╡рдкрдЯреВрдВрдордзреНрдпреЗ рд╡рд╛рдЯрддрд╛ рдпреЗрддреЛ, рдкрдг 10% рд╣рд╛ рдЕрд╕рд╛ рдПрдХ рдЯрдкреНрдкрд╛ рдЖрд╣реЗ рдЬреЛ рдлрдХреНрдд рдПрдХрдЪ рдзрд╛рд╡рдкрдЯреВ рдзрд╛рд╡реВ рд╢рдХрддреЗ. рдЕрдЧрдгрд┐рдд рдзрд╛рд╡рдкрдЯреВ рдЕрд╕рд▓реНрдпрд╛ рддрд░реА рд╕рдВрдШ рдЬрд╛рд╕реНрддреАрдд рдЬрд╛рд╕реНрдд 10 рдкрдЯ рд╡реЗрдЧрд╡рд╛рди рд╣реЛрдК рд╢рдХрддреЛ, рдХрд╛рд░рдг рддреЛ рдПрдХ рдЯрдкреНрдкрд╛ рдХрдзреАрдЪ рд▓рд╣рд╛рди рд╣реЛрдд рдирд╛рд╣реА.
ЁЯЧ║я╕П рдЖрдХреГрддреА
flowchart LR
arr["ЁЯПГ runners arrive<br/>at random"] --> q["ЁЯЪ╢ЁЯЪ╢ЁЯЪ╢ the queue"] --> t["ЁЯЪ░ one table<br/>10 ms a cup"]
u50["50% busy тЖТ 20 ms"] --> u90["90% busy тЖТ 100 ms"] --> u99["99% busy тЖТ 1000 ms"]
little["Little: L = ╬╗W<br/>80/s ├Ч 50 ms = 4"]
amd["Amdahl, 90% parallel:<br/>8 runners 4.71├Ч ┬╖ endless 10├Ч"]
ЁЯЧ║я╕П рд░реЗрдЦрд╛рдЯрд▓реЗрд▓реА рдЖрд╡реГрддреНрддреА + рдПрдХ lab: https://school-edh.pages.dev/performance/lesson-diagrams.html#l09
тЭУ рдХрд╛рдп
- Utilisation (╧Б, "rho") тАФ server busy рдЕрд╕рд▓реЗрд▓реНрдпрд╛ рд╡реЗрд│реЗрдЪрд╛ рд╡рд╛рдЯрд╛: arrival rate ├Ч service time. 80 requests/s ├Ч 10 ms = 0.8 = 80%.
- M/M/1 тАФ рд╕рд░реНрд╡рд╛рдд рд╕реЛрдкреЗ queueing model: random (Poisson) arrivals, random (exponential) service times, рдПрдХ server, рдЖрдзреА рдпреЗрдИрд▓ рддреНрдпрд╛рд▓рд╛ рдЖрдзреА рд╕реЗрд╡рд╛. рддреНрдпрд╛рдЪрд╛ system рдордзрд▓рд╛ рд╕рд░рд╛рд╕рд░реА рд╡реЗрд│ W = S / (1 тИТ ╧Б) (S = service time); рдлрдХреНрдд рдерд╛рдВрдмрдгреНрдпрд╛рдЪрд╛ рднрд╛рдЧ ╧Б┬╖S / (1 тИТ ╧Б) рдЖрд╣реЗ. рд╣реЗ рдПрдХ рдЕрдВрджрд╛рдЬреЗ рдореЛрдЬрдорд╛рдк (approximation) рдЖрд╣реЗ тАФ рдЦрд░реЗ traffic рдЕрдзрд┐рдХ рдЭрдЯрдХреЗрджрд╛рд░ рдХрд┐рдВрд╡рд╛ рдЕрдзрд┐рдХ рд╕реБрд░рд│реАрдд рдЕрд╕рддреЗ тАФ рдкрдг рддреНрдпрд╛рдЪрд╛ рдЖрдХрд╛рд░ рд╣рд╛рдЪ рдзрдбрд╛ рдЖрд╣реЗ: 50% busy рд╡рд░ W = 2S; 90% рд╡рд░ 10S; 99% рд╡рд░ 100S.
- рдмрджрд▓рддреНрдпрд╛ рд╕реНрд╡рд░реВрдкрд╛рд▓рд╛ (variability) рдорд╣рддреНрддреНрд╡ рдЖрд╣реЗ тАФ рдЗрддрд░ arrival рдЖрдгрд┐ service patterns рд╕рд╛рдареА, Kingman рдЪреЗ рд╕реВрддреНрд░ (рдЖрдгрдЦреА рдПрдХ approximation) рд╕рд╛рдВрдЧрддреЗ рдХреА рдкреНрд░рддреАрдХреНрд╖рд╛ ╧Б / (1 тИТ ╧Б) рд╕реЛрдмрдд рдЖрдгрд┐ arrivals рд╡ service times рдХрд┐рддреА рдмрджрд▓рддрд╛рдд рддреНрдпрд╛рд╕реЛрдмрдд рд╡рд╛рдврддреЗ. рд╕реБрд░рд│реАрдд traffic рдЖрдгрд┐ рд╕реНрдерд┐рд░ service рдореНрд╣рдгрдЬреЗ рддреНрдпрд╛рдЪ utilisation рд╡рд░ рд▓рд╣рд╛рди рд░рд╛рдВрдЧрд╛.
- Little's law: L = ╬╗ W тАФ system рдордзреАрд▓ рд╕рд░рд╛рд╕рд░реА рд╕рдВрдЦреНрдпрд╛ (L) = arrival rate (╬╗) ├Ч рдкреНрд░рддреНрдпреЗрдХрд╛рдиреЗ рддрд┐рдереЗ рдШрд╛рд▓рд╡рд▓реЗрд▓рд╛ рд╕рд░рд╛рд╕рд░реА рд╡реЗрд│ (W). рдХреЛрдгрддреНрдпрд╛рд╣реА рд╕реНрдерд┐рд░ system рд╕рд╛рдареА, рдкреБрд░реЗрд╢рд╛ рджреАрд░реНрдШ рдХрд╛рд│рд╛рдЪреА рд╕рд░рд╛рд╕рд░реА рдШреЗрддрд▓реНрдпрд╛рд╕, arrivals рдЪрд╛ pattern рдХрд╕рд╛рд╣реА рдЕрд╕рд▓рд╛ рддрд░реА рд╣реЗ рд▓рд╛рдЧреВ рд╣реЛрддреЗ. Connection pools, thread pools рдЖрдгрд┐ queues рдЪрд╛ рдЖрдХрд╛рд░ рдард░рд╡рдгреНрдпрд╛рд╕рд╛рдареА рд╣реЗ рд╡рд╛рдкрд░рд╛.
- Amdahl's law тАФ рдХрд╛рдорд╛рдЪрд╛ p рдЗрддрдХрд╛ рднрд╛рдЧ n workers рд╡рд╛рдкрд░реВ рд╢рдХрдд рдЕрд╕реЗрд▓ рдЖрдгрд┐ рдЙрд░рд▓реЗрд▓рд╛ рдирд╛рд╣реА, рддрд░ рд╕рд░реНрд╡реЛрддреНрддрдо speed-up 1 / ((1 тИТ p) + p / n) рдЕрд╕рддреЛ, рдЖрдгрд┐ 1 / (1 тИТ p) рдкреЗрдХреНрд╖рд╛ рдХрдзреАрдЪ рдЬрд╛рд╕реНрдд рдирд╛рд╣реА. Serial рднрд╛рдЧ тАФ рдПрдХ lock, рд╕рдЧрд│реЗ update рдХрд░рддрд╛рдд рдЕрд╢реА database рдЪреА рдПрдХрдЪ row, рдХреНрд░рдорд╛рдиреЗрдЪ рдЪрд╛рд▓рд╛рд╡реА рд▓рд╛рдЧрдгрд╛рд░реА рдкрд╛рдпрд░реА тАФ рд╣рд╛ рд░рд┐рд▓реЗрддреАрд▓ рд╕рд░реНрд╡рд╛рдд рд╣рд│реВ рдзрд╛рд╡рдкрдЯреВ рдЖрд╣реЗ.
- Amdahl рдЪреНрдпрд╛ рдкрд▓реАрдХрдбреЗ тАФ workers рдирд╛ рд╕рдордиреНрд╡рдп рдХрд░рд╛рд╡рд╛ рд▓рд╛рдЧрдд рдЕрд╕реЗрд▓ (locks, cores рджрд░рдореНрдпрд╛рди cache traffic) рддрд░ workers рд╡рд╛рдврд╡рд▓реНрдпрд╛рдиреЗ рдЧреЛрд╖реНрдЯреА рдЕрдзрд┐рдХ рд╣рд│реВрд╣реА рд╣реЛрдК рд╢рдХрддрд╛рдд. Neil Gunther рдЪрд╛ Universal Scalability Law рд╣рд╛ рдЦрд░реНрдЪ рдЬреЛрдбрддреЛ. рдЕрдиреЗрдХ machines рд╡рд░ scale out рдХрд░рдгреЗ рд╣рд╛ Scaling school рдЪрд╛ рд╡рд┐рд╖рдп рдЖрд╣реЗ.
ЁЯдФ рдХрд╛
рдХрд╛рд░рдг "server рдлрдХреНрдд 90% CPU рд╡рд░ рдЖрд╣реЗ, рдЕрдЬреВрди рдЬрд╛рдЧрд╛ рдЖрд╣реЗ" рдЕрд╢рд╛рдиреЗрдЪ outages рд╕реБрд░реВ рд╣реЛрддрд╛рдд. 90% busy рд╡рд░ рд╕рд░рд╛рд╕рд░реА request рдЖрдзреАрдЪ 10 service times рдерд╛рдВрдмрддреЗ, рдЖрдгрд┐ рдЫреЛрдЯрд╛рд╕рд╛ burst рддреА рдЦреВрдк рд╡рд░ рдврдХрд▓рддреЛ. Latency-sensitive service рд╕рд╛рдареА рд╕реБрд░рдХреНрд╖рд┐рдд рдЬрд╛рдЧрд╛ 100% busy рдЪреНрдпрд╛ рдмрд▒реНрдпрд╛рдЪ рдЦрд╛рд▓реА рдЖрд╣реЗ. рдЖрдгрд┐ 16 рд╡рд╛ worker рдЬреЛрдбрд▓реНрдпрд╛рдиреЗ рдлрд╛рд░рд╢реА рдорджрдд рдХрд╛ рдЭрд╛рд▓реА рдирд╛рд╣реА рд╣реЗ Amdahl рд╕рдордЬрд╛рд╡рддреЛ: serial рднрд╛рдЧрдЪ рдЖрдзреАрдкрд╛рд╕реВрди рдмрд╣реБрддреЗрдХ рд╡реЗрд│ рдШреЗрдд рд╣реЛрддрд╛.
ЁЯФз рдХрд╕реЗ (рдпрд╛ repo рдордзреНрдпреЗ)
perf/sim.py рдордзреАрд▓ mm1_wait_ms(service_ms, util) рд╣реЗ M/M/1 рд╕реВрддреНрд░
S / (1 тИТ ╧Б) рдЖрд╣реЗ. simulate_queue(rate, service_ms, n, seed) рдПрдХрд╛ first-come first-served server
рдЪреЗ simulation рдХрд░рддреЗ, arrivals рдордзреАрд▓ seeded random (exponential) рдЕрдВрддрд░реЗ рдЖрдгрд┐ random service times рд╕рд╣, рдЖрдгрд┐
рдкреНрд░рддреНрдпреЗрдХ request рдЪрд╛ system рдордзреАрд▓ рд╡реЗрд│ рдкрд░рдд рджреЗрддреЗ. littles_law(rate, wait_ms) рдореНрд╣рдгрдЬреЗ ╬╗W;
amdahl(p, n) рдореНрд╣рдгрдЬреЗ speed-up рдЪреЗ рд╕реВрддреНрд░. perf/demo.py рдордзреАрд▓ queueing() рд╕реВрддреНрд░рд╛рдЪреА
20,000 simulated рдзрд╛рд╡рдкрдЯреВрдВрд╢реА рддреБрд▓рдирд╛ рдХрд░рддреЗ.
ЁЯзк рдХрд░реВрди рдкрд╛рд╣рд╛
python3 perf/demo.py queueing
python3 - <<'EOF'
import sys; sys.path.insert(0, "perf"); from sim import mm1_wait_ms, littles_law, amdahl
for s in (10, 5):
print(f"service {s:>2} ms: " + " ┬╖ ".join(f"{u:.0%} busy тЖТ {mm1_wait_ms(s, u):.0f} ms" for u in (0.5, 0.7, 0.9)))
print("Little: 200 req/s ├Ч 250 ms =", littles_law(200, 250), "requests in flight")
for p in (0.5, 0.9, 0.99):
print(f"parallel share {p:.0%}: 8 workers тЖТ {amdahl(p, 8):.2f}├Ч ┬╖ the limit {1 / (1 - p):.0f}├Ч")
EOF
тЬЕ рддрдкрд╛рд╕рд╛ тАФ рддреБрдореНрд╣рд╛рд▓рд╛ рдХрд╛рдп рджрд┐рд╕рд╛рдпрд▓рд╛ рд╣рд╡реЗ
queueing рд╣реЗ рдЫрд╛рдкрддреЗ:
тФАтФА one water table, 10 ms to serve a runner ┬╖ M/M/1 approximation: time at the table = 10 ms ├╖ (1 тИТ utilisation)
utilisation 50% тЖТ formula 20 ms ┬╖ simulated (20,000 runners) 20 ms
utilisation 80% тЖТ formula 50 ms ┬╖ simulated (20,000 runners) 49 ms
utilisation 90% тЖТ formula 100 ms ┬╖ simulated (20,000 runners) 104 ms
utilisation 95% тЖТ formula 200 ms ┬╖ simulated (20,000 runners) 186 ms
utilisation 99% тЖТ formula 1000 ms ┬╖ simulated (20,000 runners) 519 ms
near 100% busy, the wait explodes (and a short simulation has not caught up with it yet)
тФАтФА Little's law L = ╬╗W: 80 runners/s ├Ч 50 ms = 4 runners at the table on average
тФАтФА Amdahl's law: 90% of the relay can be shared out, 10% is one runner's leg that nobody can help with
2 runners тЖТ 1.82├Ч ┬╖ 4 runners тЖТ 3.08├Ч ┬╖ 8 runners тЖТ 4.71├Ч ┬╖ 16 runners тЖТ 6.40├Ч ┬╖ endless runners тЖТ 10.00├Ч
рддреБрдордЪрд╛ snippet рд╣реЗ рдЫрд╛рдкрддреЛ:
service 10 ms: 50% busy тЖТ 20 ms ┬╖ 70% busy тЖТ 33 ms ┬╖ 90% busy тЖТ 100 ms
service 5 ms: 50% busy тЖТ 10 ms ┬╖ 70% busy тЖТ 17 ms ┬╖ 90% busy тЖТ 50 ms
Little: 200 req/s ├Ч 250 ms = 50.0 requests in flight
parallel share 50%: 8 workers тЖТ 1.78├Ч ┬╖ the limit 2├Ч
parallel share 90%: 8 workers тЖТ 4.71├Ч ┬╖ the limit 10├Ч
parallel share 99%: 8 workers тЖТ 7.48├Ч ┬╖ the limit 100├Ч
ЁЯПБ рддреБрдореНрд╣реА рдЖрддреНрддрд╛рдЪ рдХрд╛рдп рд╕рд┐рджреНрдз рдХреЗрд▓реЗ
50тАУ90% busy рд╡рд░ simulation рд╕реВрддреНрд░рд╛рд╢реА рдЬреБрд│рд▓реЗ (20, 49, 104 ms). 99% рд╡рд░ рддреЗ рдлрдХреНрдд 519 ms рджрд╛рдЦрд╡рд▓реЗ, 1000 рдирд╡реНрд╣реЗ тАФ рдЗрддрдХреА busy рд░рд╛рдВрдЧ рддрд┐рдЪреНрдпрд╛ рд╕рд░рд╛рд╕рд░реАрдкрд░реНрдпрдВрдд рдкреЛрд╣реЛрдЪрд╛рдпрд▓рд╛ рдЦреВрдк рд╡реЗрд│ рдШреЗрддреЗ, рдЖрдгрд┐ рд╣реАрдЪ рдПрдХ рдзреЛрдХреНрдпрд╛рдЪреА рд╕реВрдЪрдирд╛ рдЖрд╣реЗ: 100% рдЬрд╡рд│ рдкреНрд░рддреАрдХреНрд╖рд╛ рдлрдХреНрдд рд▓рд╛рдВрдм рдирд╕рддреЗ, рддреА рдЕрдирд┐рд╢реНрдЪрд┐рдд рдЕрд╕рддреЗ. Service time рдЕрд░реНрдзрд╛ рдХреЗрд▓реНрдпрд╛рдиреЗ (рдзрдбрд╛ 03 рд╕рд╛рд░рдЦрд╛ рдЙрдкрд╛рдп) рддреНрдпрд╛рдЪ utilisation рд╡рд░ рдкреНрд░рддреНрдпреЗрдХ рдкреНрд░рддреАрдХреНрд╖рд╛ рдЕрд░реНрдзреА рдЭрд╛рд▓реА. рдЖрдгрд┐ 50% serial рднрд╛рдЧ рдЕрд╕рддрд╛рдирд╛ 8 workers рдиреА рдлрдХреНрдд 1.78├Ч рджрд┐рд▓реЗ.
тЪая╕П рдиреЗрд╣рдореАрдЪреНрдпрд╛ рдЪреБрдХрд╛
- latency-sensitive service рд╕рд╛рдареА 90тАУ100% utilisation рдЧреГрд╣реАрдд рдзрд░реВрди capacity рдЪрд╛ рдЖрд░рд╛рдЦрдбрд╛ рдХрд░рдгреЗ
- Little's law (rate ├Ч pool рдордзреАрд▓ рд╡реЗрд│) рдРрд╡рдЬреА рдЕрдВрджрд╛рдЬрд╛рдиреЗ pool рдЪрд╛ рдЖрдХрд╛рд░ рдард░рд╡рдгреЗ
- рд╡реЗрд│ serial рднрд╛рдЧрд╛рдд (рдПрдХ lock, рдПрдХ hot row, рдПрдХ leader) рдЬрд╛рдд рдЕрд╕рддрд╛рдирд╛ workers рд╡рд╛рдврд╡рдгреЗ
- рдкреВрд░реНрдгрдкрдгреЗ рд╕рдорд╛рди traffic рдиреЗ test рдХрд░рдгреЗ, рдЬреНрдпрд╛рдореБрд│реЗ рд░рд╛рдВрдЧрд╛ рдирд┐рд░реНрдорд╛рдг рдХрд░рдгрд╛рд░реЗ bursts рд▓рдкрддрд╛рдд
- рддрд╛рд╕рд╛рднрд░рд╛рдЪреНрдпрд╛ utilisation рдЪреА рд╕рд░рд╛рд╕рд░реА рдШреЗрдгреЗ, рдЬреНрдпрд╛рдореБрд│реЗ 100% рд╡рд░рдЪреА рдорд┐рдирд┐рдЯреЗ рд▓рдкрддрд╛рдд
ЁЯПн рдкреНрд░рддреНрдпрдХреНрд╖ рд╡рд╛рдкрд░рд╛рдд
Database connection pool рдЪрд╛ рдЖрдХрд╛рд░ Little's law рдиреЗ рдард░рд╡рд╛. 200 requests/s рд╡рд░, рдкреНрд░рддреНрдпреЗрдХ request 25 ms connection рдзрд░реВрди рдареЗрд╡рдд рдЕрд╕реЗрд▓ рддрд░: 200 ├Ч 0.025 = рд╕рд░рд╛рд╕рд░реА 5 connections busy тАФ bursts рд╕рд╛рдареА рдЬрд╛рджрд╛ рдЬрд╛рдЧрд╛ рдареЗрд╡рд╛, рдЖрдгрд┐ рд▓рдХреНрд╖рд╛рдд рдареЗрд╡рд╛ рдХреА рдкреНрд░рддреНрдпреЗрдХ app instance рдЪрд╛ рд╕реНрд╡рддрдГрдЪрд╛ pool рдЕрд╕рддреЛ. рдЦрд▒реНрдпрд╛ account рд╡рд░, SQLAlchemy:
engine = create_engine(DB_URL, pool_size=10, max_overflow=5, pool_timeout=2)
рдлрдХреНрдд CPU рдирд╡реНрд╣реЗ, рддрд░ utilisation рдЖрдгрд┐ queue length рд╡рд░ рд▓рдХреНрд╖ рдареЗрд╡рд╛. Linux рд╡рд░:
vmstat 1 # r = runnable threads waiting for a CPU; above the core count means a queue
iostat -x 1 # %util and aqu-sz (average queue size) for each disk
Prometheus рдордзреНрдпреЗ, worker pool рдЪрд╛ busy рд╡рд╛рдЯрд╛ (metric рдЪреА рдирд╛рд╡реЗ рддреБрдордЪреНрдпрд╛ exporter рд╡рд░ рдЕрд╡рд▓рдВрдмреВрди рдЕрд╕рддрд╛рдд):
sum(rate(worker_busy_seconds_total[5m])) / count(worker_up)
ЁЯПн рдкреНрд░рддреНрдпрдХреНрд╖ рд╡рд╛рдкрд░рд╛рдд рд╣реЗ рдХрд╛ рдорд╣рддреНрддреНрд╡рд╛рдЪреЗ: рдкреНрд░рддреНрдпреЗрдХ latency-sensitive service рд▓рд╛ рдПрдХ utilisation target рджреНрдпрд╛ (рдЙрджрд╛рд╣рд░рдгрд╛рд░реНрде "60тАУ70% busy рдЪреНрдпрд╛ рд╡рд░ рдЧреЗрд▓реНрдпрд╛рд╕ scale out рдХрд░рд╛"), queue length рд╡рд░ alert рд▓рд╛рд╡рд╛, рдЖрдгрд┐ workers рд╡рд╛рдврд╡рдгреНрдпрд╛рдЖрдзреА serial рднрд╛рдЧ рд╢реЛрдзрд╛.
тПня╕П рдкреБрдвреЗ
Requests рд╕рд░реНрд╡рд╛рдзрд┐рдХ рд░рд╛рдВрдЧреЗрдд рдерд╛рдВрдмрддрд╛рдд рддреА рдЬрд╛рдЧрд╛ рдореНрд╣рдгрдЬреЗ database. рдкреБрдвреЗ: рдкреНрд░рддреНрдпреЗрдХ рдкрддреНрд░рдХ рд╡рд╛рдЪреВрди, рдХреА index
рд╡рд╛рдкрд░реВрди, рдПрдХрд╛ рдзрд╛рд╡рдкрдЯреВрдЪреЗ laps рд╢реЛрдзрдгреЗ тАФ EXPLAIN QUERY PLAN.
git checkout lesson-10-database-queries