ЁЯУМ рдзрдбрд╛ 05 тАФ Caching: рд╡рд╛рдЪрдгрд╛рд▒реНрдпрд╛рдЬрд╡рд│ рдкреНрд░рддреА
ЁЯУН рддреБрдореНрд╣реА рдЗрдереЗ рдЖрд╣рд╛рдд: 18 рдкреИрдХреА рдзрдбрд╛ 05 ┬╖ рдорд╛рдЧреЗ: lesson-04-data-model ┬╖ рдкреБрдвреЗ: lesson-06-load-balancing
ЁЯУж рдпрд╛ рдмреНрд░рдБрдЪрдордзреНрдпреЗ рдХрд╛рдп рдЖрд╣реЗ
рдзрдбреЗ 01тАУ04, рдЖрдгрд┐ рднрд╛рдЧ 2 рдЪрд╛ рдкрд╣рд┐рд▓рд╛ рдмрд╛рдВрдзрдгреАрдЪрд╛ рдареЛрдХрд│рд╛: cache. рдкреНрд░рддреА рдХреБрдареЗ рд░рд╛рд╣реВ рд╢рдХрддрд╛рдд (browser,
CDN, app, database), cache рдХрд┐рддреА рдореЛрдард╛ рд╣рд╡рд╛ (hit-ratio рд╡рдХреНрд░), рдЖрдгрд┐ рдкреНрд░рддреА рдкреБрд░реЗрд╢рд╛ рддрд╛рдЬреНрдпрд╛ рдХрд╢рд╛
рд░рд╛рд╣рддрд╛рдд (cache-aside, write-through, TTL, invalidation).
design/blocks.py рдордзреАрд▓ LRUCache рдЖрдгрд┐ zipf_stream() рд╡реЗрдЧрд╡реЗрдЧрд│реНрдпрд╛
рдЖрдХрд╛рд░рд╛рдВрдЪреНрдпрд╛ caches рдордзреВрди 20,000 feed reads рдЪрд╛рд▓рд╡рддрд╛рдд; design/demo.py рдордзреАрд▓
cache() рд╡рдХреНрд░ рдЫрд╛рдкрддреЗ.
ЁЯзТ 5 рд╡рд░реНрд╖рд╛рдВрдЪреНрдпрд╛ рдореБрд▓рд╛рд▓рд╛ рд╕рдордЬрд╛рд╡рд▓реНрдпрд╛рд╕рд╛рд░рдЦреЗ
рджрд░рд░реЛрдЬ рд╕рдХрд╛рд│реА рд╢реЗрдХрдбреЛ рдкрд╛рд▓рдХ рдХрд╛рд░реНрдпрд╛рд▓рдпрд╛рдд рдпреЗрддрд╛рдд рдЖрдгрд┐ рд╡рд┐рдЪрд╛рд░рддрд╛рдд: "рд╡рд░реНрдЧ 3A рдЪреНрдпрд╛ рд╕реВрдЪрдирд╛ рдХрд╛рдп рдЖрд╣реЗрдд?" рдХрд╛рд░рдХреВрди рдорд╛рдЧрдЪреНрдпрд╛ рдореЛрдареНрдпрд╛ рдиреЛрдВрджрд╡рд╣реАрдХрдбреЗ рдЬрд╛рддреЗ, 3A рдЪреА рдкрдЯреНрдЯреА рд╢реЛрдзрддреЗ, рдЖрдгрд┐ рддреНрдпрд╛ рд╡рд╛рдЪреВрди рджрд╛рдЦрд╡рддреЗ. рдкреБрдиреНрд╣рд╛. рдкреБрдиреНрд╣рд╛. рддреЗрдЪ рдЙрддреНрддрд░, рд╢реЗрдХрдбреЛ рд╡реЗрд│рд╛.
рдореНрд╣рдгреВрди рджреАрдкрд┐рдХрд╛ рдХрд╛рд░реНрдпрд╛рд▓рдпрд╛рдЪреНрдпрд╛ рджрд╛рд░рд╛рдЬрд╡рд│ рдПрдХ рдЫреЛрдЯрд╛ рд╕реВрдЪрдирд╛ рдлрд▓рдХ ЁЯУМ рд▓рд╛рд╡рддреЗ. рдХрд╛рд░рдХреВрди рд╕рд░реНрд╡рд╛рдд рдЬрд╛рд╕реНрдд рд╡рд┐рдЪрд╛рд░рд▓реНрдпрд╛ рдЬрд╛рдгрд╛рд▒реНрдпрд╛ рд╡рд░реНрдЧрд╛рдВрдЪреА рдкреНрд░рдд рддрд┐рдереЗ рд▓рд╛рд╡рддреЗ. рдЖрддрд╛ рдмрд╣реБрддреЗрдХ рдкрд╛рд▓рдХ рдлрд▓рдХ рд╡рд╛рдЪрддрд╛рдд рдЖрдгрд┐ рдирд┐рдШреВрди рдЬрд╛рддрд╛рдд. рдПрдЦрд╛рджрд╛ рд╡рд░реНрдЧ рдлрд▓рдХрд╛рд╡рд░ рдирд╕реЗрд▓ рддреЗрд╡реНрд╣рд╛рдЪ рдХрд╛рд░рдХреВрди рдиреЛрдВрджрд╡рд╣реАрдХрдбреЗ рдЬрд╛рддреЗ тАФ рдЖрдгрд┐ рдордЧ рддреЛрд╣реА рдлрд▓рдХрд╛рд╡рд░ рд▓рд╛рд╡рддреЗ.
рдлрд▓рдХ рд▓рд╣рд╛рди рдЖрд╣реЗ. рддреЛ рднрд░рд▓рд╛ рдХреА, рдЬрд╛рдЧрд╛ рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рдХрд╛рд░рдХреВрди рд╕рд░реНрд╡рд╛рдд рдЬрд╛рд╕реНрдд рдХрд╛рд│ рдХреЛрдгреАрд╣реА рди рдкрд╛рд╣рд┐рд▓реЗрд▓реА рдкреНрд░рдд (least recently used) рдХрд╛рдврддреЗ.
рджреАрдкрд┐рдХрд╛рд▓рд╛ рджреЛрди рдЕрдбрдЪрдгреАрдВрдЪреА рддрдпрд╛рд░реА рдХрд░рд╛рд╡реА рд▓рд╛рдЧрддреЗ:
- рдЬреБрдиреНрдпрд╛ рдкреНрд░рддреА. рд╢рд┐рдХреНрд╖рд┐рдХреЗрдиреЗ 3A рд╕рд╛рдареА рдирд╡реА рд╕реВрдЪрдирд╛ post рдХреЗрд▓реА рдХреА рдлрд▓рдХрд╛рд╡рд░рдЪреА рдкреНрд░рдд рдЬреБрдиреА рд╣реЛрддреЗ. рдореНрд╣рдгреВрди рдПрдХрддрд░ рдХрд╛рд░рдХреВрди рддреА рд▓рдЧреЗрдЪ рдХрд╛рдврддреЗ, рдХрд┐рдВрд╡рд╛ рдкреНрд░рддреНрдпреЗрдХ рдкреНрд░рддреАрд╡рд░ "8:05 рдкрд░реНрдпрдВрдд рд╡реИрдз" рдЕрд╢реА рдЯреАрдк (TTL) рдЕрд╕рддреЗ рдЖрдгрд┐ рддреНрдпрд╛рдирдВрддрд░ рддреА рдмрджрд▓рд▓реА рдЬрд╛рддреЗ.
- рдлрд▓рдХ рдХрд┐рддреА рдореЛрдард╛? рдХрд╛рд╣реА рдЦреВрдк рд▓реЛрдХрдкреНрд░рд┐рдп рд╡рд░реНрдЧрд╛рдВрдирд╛ рдмрд╣реБрддреЗрдХ рдкреНрд░рд╢реНрди рдпреЗрддрд╛рдд. рд▓рд╣рд╛рди рдлрд▓рдХрд╕реБрджреНрдзрд╛ рдмрд░реЗрдЪ рдкрдХрдбрддреЛ. рджреБрдкреНрдкрдЯ рдореЛрдард╛ рдлрд▓рдХ рдереЛрдбреЗрд╕реЗрдЪ рдЬрд╛рд╕реНрдд рдкрдХрдбрддреЛ.
ЁЯЧ║я╕П рдЖрдХреГрддреА
flowchart LR
ph["ЁЯУ▒ app<br/>browser / phone cache"] --> cdn["ЁЯМН CDN<br/>edge copies"]
cdn --> api["ЁЯФМ API servers"]
api -->|"1 get"| rc[("ЁЯУМ Redis<br/>cache-aside")]
rc -.->|"hit: answer"| api
api -->|"2 miss: read"| db[("ЁЯРШ database<br/>+ its buffer cache")]
api -->|"3 put, TTL 60 s"| rc
post["тЬНя╕П new notice"] -->|"delete key 'feed:3A'"| rc
curve["ЁЯУИ hit ratio<br/>1% of classes тЖТ 33.8%<br/>10% тЖТ 64.0% ┬╖ 50% тЖТ 83.1%"]
ЁЯЧ║я╕П рдХрд╛рдврд▓реЗрд▓реА рдЖрд╡реГрддреНрддреА + рдПрдХ lab: https://school-edh.pages.dev/system-design/lesson-diagrams.html#l05
тЭУ рдХрд╛рдп
- Cache тАФ рдПрдХ рдЬрд▓рдж, рд▓рд╣рд╛рди store, рдЬреЛ рдЬреНрдпрд╛рдВрдЪреЗ рдЦрд░реЗ рдШрд░ рд╣рд│реВ рдЖрд╣реЗ рдЕрд╢рд╛ data рдЪреНрдпрд╛ рдкреНрд░рддреА рдареЗрд╡рддреЛ (database, рджреБрд╕рд░реА service, рдЬрдб рдЖрдХрдбреЗрдореЛрдб).
- Hit / miss / hit ratio тАФ hit рдореНрд╣рдгрдЬреЗ cache рдордзреНрдпреЗ рд╕рд╛рдкрдбрд▓реЗ; miss рдЦрд▒реНрдпрд╛ рдШрд░реА рдЬрд╛рддреЛ. Hit ratio = hits ├╖ рд╕рдЧрд│реЗ reads. рдкреНрд░рддреНрдпреЗрдХ miss рдореНрд╣рдгрдЬреЗ рдПрдХ database read.
- Cache рдХреБрдареЗ рд░рд╛рд╣реВ рд╢рдХрддреЛ (рд╡рд╛рдЪрдгрд╛рд▒реНрдпрд╛рдЪреНрдпрд╛ рд╕рд░реНрд╡рд╛рдд рдЬрд╡рд│рдЪрд╛ рдЖрдзреА):
- browser / app тАФ
Cache-Control: max-age=30; рддреБрдореНрд╣рд╛рд▓рд╛ рдХрд╛рд╣реАрдЪ рдЦрд░реНрдЪ рдирд╛рд╣реА, рдкрдг рддреБрдореНрд╣реА рддреЛ delete рдХрд░реВ рд╢рдХрдд рдирд╛рд╣реА. - CDN (CloudFront) тАФ рд╡рд╛рдЪрдгрд╛рд▒реНрдпрд╛рдЬрд╡рд│ edge рд╡рд░ рдкреНрд░рддреА; pages, рдЪрд┐рддреНрд░реЗ, public рдпрд╛рджреНрдпрд╛рдВрд╕рд╛рдареА рд╕рд░реНрд╡реЛрддреНрддрдо.
- application cache (Redis, Memcached) тАФ рд╕рдЧрд│реЗ API servers рдорд┐рд│реВрди рд╡рд╛рдкрд░рддрд╛рдд; "рд╡рд░реНрдЧ 3A рдЪреНрдпрд╛ рд╕реВрдЪрдирд╛" рд╕рд╛рдареА рдиреЗрд╣рдореАрдЪреА рдЬрд╛рдЧрд╛.
- database buffer тАФ database рдЪреА рд╕реНрд╡рддрдГрдЪреА memory; рдореЛрдлрдд, рдкрдг рддреА рддреБрдореНрд╣рд╛рд▓рд╛ рд╣рд│реВ query рдкрд╛рд╕реВрди рд╡рд╛рдЪрд╡реВ рд╢рдХрдд рдирд╛рд╣реА.
- browser / app тАФ
- Hit-ratio рд╡рдХреНрд░ тАФ рдЦрд░рд╛ traffic рдПрдХрддрд░реНрдлреА (skewed) рдЕрд╕рддреЛ: рдХрд╛рд╣реА items рдирд╛ рдмрд╣реБрддреЗрдХ reads рдорд┐рд│рддрд╛рдд. рдореНрд╣рдгреВрди рд▓рд╣рд╛рди cache рдореЛрдард╛ рд╡рд╛рдЯрд╛ рдкрдХрдбрддреЛ, рдЖрдгрд┐ рдкреНрд░рддреНрдпреЗрдХ рдЬрд╛рд╕реНрддреАрдЪрд╛ gigabyte рдХрдореА рдкрдХрдбрддреЛ. рдЖрдХрд╛рд░ рдард░рд╡рдгреЗ рдореНрд╣рдгрдЬреЗ рдПрдХ рд╡рдХреНрд░ тАФ рддреЛ рдореЛрдЬрд╛, рдЖрдгрд┐ рдЬрд┐рдереЗ рдЬрд╛рд╕реНрдд memory рдЪрд╛ рдлрд╛рдпрджрд╛ рдерд╛рдВрдмрддреЛ рддреЛ рдмрд┐рдВрджреВ рдирд┐рд╡рдбрд╛.
- LRU (least recently used) тАФ рднрд░рд▓реНрдпрд╛рд╡рд░, рд╕рд░реНрд╡рд╛рдд рдЬрд╛рд╕реНрдд рдХрд╛рд│рд╛рдкреВрд░реНрд╡реА рд╡рд╛рдЪрд▓реЗрд▓реЗ рдХрд╛рдвреВрди рдЯрд╛рдХрд╛.
- Cache-aside (lazy loading) тАФ app cache рд╡рд╛рдЪрддреЛ; miss рдЭрд╛рд▓рд╛ рддрд░ database рд╡рд╛рдЪрддреЛ рдЖрдгрд┐ рдЙрддреНрддрд░ cache рдордзреНрдпреЗ рдареЗрд╡рддреЛ. рд╕рд░реНрд╡рд╛рдд рд╕рд╛рдорд╛рдиреНрдп pattern.
- Write-through тАФ рдкреНрд░рддреНрдпреЗрдХ write cache рдЖрдгрд┐ database рджреЛрдиреНрд╣реАрдХрдбреЗ рдЬрд╛рддреЛ, рдореНрд╣рдгреВрди рд▓рд┐рд╣рд┐рд▓реЗрд▓реНрдпрд╛ рдЧреЛрд╖реНрдЯреАрдВрд╕рд╛рдареА cache рдиреЗрд╣рдореА рдЧрд░рдо рдЕрд╕рддреЛ. рдХреЛрдгреАрд╣реА рди рд╡рд╛рдЪрдгрд╛рд▒реНрдпрд╛ data рд╕рд╛рдареА memory рдЦрд░реНрдЪ рд╣реЛрддреЗ.
- TTL (time to live) тАФ N рд╕реЗрдХрдВрджрд╛рдВрдирдВрддрд░ рдкреНрд░рдд рдХрд╛рд▓рдмрд╛рд╣реНрдп рд╣реЛрддреЗ. рддреБрдореНрд╣реА рд╕реНрд╡реАрдХрд╛рд░рддрд╛ рддреЛ рд╕рд░реНрд╡рд╛рдд рдЬрд╛рд╕реНрдд рдЬреБрдиреЗрдкрдгрд╛, рдЖрдХрдбреНрдпрд╛рдЪреНрдпрд╛ рд░реВрдкрд╛рдд рд▓рд┐рд╣рд┐рд▓реЗрд▓рд╛.
- Invalidation тАФ write рдЭрд╛рд▓реНрдпрд╛рд╡рд░ key (
feed:3A) delete рдХрд░рд╛, рдореНрд╣рдгрдЬреЗ рдкреБрдврдЪрд╛ read рдирд╡рд╛ data рдЖрдгрддреЛ. Delete рдХрд░рд╛, update рдирд╛рд╣реА: рдПрдХрдореЗрдХрд╛рдВрд╢реА рд╢рд░реНрдпрдд рд▓рд╛рд╡рдгрд╛рд░реЗ рджреЛрди updates рдЬреБрдиреА value рдареЗрд╡реВрди рдЬрд╛рдК рд╢рдХрддрд╛рдд.
ЁЯдФ рдХрд╛
рдХрд╛рд░рдг рдзрдбрд╛ 02 рдореНрд╣рдгрд╛рд▓рд╛ рдкреНрд░рддреНрдпреЗрдХ write рдорд╛рдЧреЗ 100 reads рдЖрдгрд┐ 3,507 req/s рдЪрд╛ peak. Cache рдЙрддреНрддрд░ рджреЗрддреЛ рддреЛ рдкреНрд░рддреНрдпреЗрдХ read рдореНрд╣рдгрдЬреЗ database рд▓рд╛ рди рдХрд░рд╛рд╡рд╛ рд▓рд╛рдЧрдгрд╛рд░рд╛ read, рдЖрдгрд┐ рддреНрдпрд╛рдЪреЗ рдЙрддреНрддрд░ рджрд╣рд╛рдРрд╡рдЬреА рд╕реБрдорд╛рд░реЗ рдПрдХрд╛ millisecond рдордзреНрдпреЗ рдорд┐рд│рддреЗ. Read-heavy system рд╕рд╛рдареА "read p99 < 200 ms" рдЧрд╛рдардгреНрдпрд╛рдЪрд╛ cache рд╣рд╛ рд╕рд░реНрд╡рд╛рдд рд╕реНрд╡рд╕реНрдд рдорд╛рд░реНрдЧ рдЖрд╣реЗ. рдкрдг рддреЛ рдПрдХ рджреБрд╕рд░реА рдкреНрд░рдд рдЬреЛрдбрддреЛ тАФ рдЖрдгрд┐ рджреЛрди рдкреНрд░рддреА рдПрдХрдореЗрдХрд╛рдВрд╢реА рдЬреБрд│рдд рдирд╛рд╣реАрдд рдЕрд╕реЗ рд╣реЛрдК рд╢рдХрддреЗ. рдореНрд╣рдгреВрди рд░рдЪрдиреЗрддрд▓реНрдпрд╛ рдкреНрд░рддреНрдпреЗрдХ cache рд╕рд╛рдареА рджреЛрди рд▓рд┐рд╣рд┐рд▓реЗрд▓реА рдЙрддреНрддрд░реЗ рд╣рд╡реАрдд: рддреА рдХрд┐рддреА рдЬреБрдиреА рдЕрд╕реВ рд╢рдХрддреЗ? рдЖрдгрд┐ рддреА рдХрд╢рд╛рдиреЗ delete рд╣реЛрддреЗ?
ЁЯФз рдХрд╕реЗ (рдпрд╛ repo рдордзреНрдпреЗ)
design/blocks.py рдордзреАрд▓ zipf_stream(n, items) reads рдЪреА рдПрдХ рдард░рд▓реЗрд▓реА
рдпрд╛рджреА рдмрдирд╡рддреЗ, рдЬрд┐рдереЗ item i рд╕рд░реНрд╡рд╛рдд рд▓реЛрдХрдкреНрд░рд┐рдп item рдЪреНрдпрд╛ рд╕реБрдорд╛рд░реЗ 1/(i+1) рдЗрддрдХреНрдпрд╛ рд╡реЗрд│рд╛ рд╡рд┐рдЪрд╛рд░рд▓рд╛ рдЬрд╛рддреЛ тАФ
рдХрд╛рд╣реА рд╡рд░реНрдЧ рдЦреВрдк рд▓реЛрдХрдкреНрд░рд┐рдп, рдмрд╣реБрддреЗрдХ рд╢рд╛рдВрдд. LRUCache(size) hits рдЖрдгрд┐ misses рдореЛрдЬрддреЛ рдЖрдгрд┐ рднрд░рд▓реНрдпрд╛рд╡рд░
least recently used рдиреЛрдВрдж рд╡рд┐рд╕рд░рддреЛ. design/demo.py рдордзреАрд▓ cache() 5,000
рд╡рд░реНрдЧрд╛рдВрд╡рд░рдЪреЗ 20,000 reads рддреНрдпрд╛рдВрдкреИрдХреА 1%, 10% рдЖрдгрд┐ 50% рдареЗрд╡рдгрд╛рд▒реНрдпрд╛ caches рдордзреВрди рдЪрд╛рд▓рд╡рддреЗ. Snippet рд╡рдХреНрд░рд╛рдЪреЗ
рдЖрдгрдЦреА рдмрд┐рдВрджреВ рдХрд╛рдврддреЛ.
ЁЯзк рдХрд░реВрди рдкрд╛рд╣рд╛
python3 design/demo.py cache
python3 - <<'EOF'
import sys; sys.path.insert(0, "design"); from blocks import LRUCache, zipf_stream
stream = zipf_stream(20_000, 5_000)
for size in (10, 50, 250, 500, 1_000, 2_500, 5_000):
c = LRUCache(size)
for k in stream: c.get(k)
print(f"cache {size:>5} classes тЖТ hit ratio {c.hit_ratio():6.1%} ┬╖ database reads {c.misses:>6,}")
top = sum(1 for k in stream if k < 50)
print(f"the 50 most popular classes get {top:,} of 20,000 reads ({top / 200:.1f}%)")
EOF
тЬЕ рддрдкрд╛рд╕рд╛ тАФ рддреБрдореНрд╣рд╛рд▓рд╛ рдХрд╛рдп рджрд┐рд╕рд╛рдпрд▓рд╛ рд╣рд╡реЗ
cache рдЫрд╛рдкрддреЗ:
тФАтФА 20,000 feed reads over 5,000 classes (a few classes are very popular) through an LRU cache
cache holds 50 classes (1% of them) тЖТ hit ratio 33.8%
cache holds 500 classes (10% of them) тЖТ hit ratio 64.0%
cache holds 2500 classes (50% of them) тЖТ hit ratio 83.1%
a cache holding 1% of the classes already catches a third of the reads тАФ sizing is a curve, measure it
where: browser ┬╖ CDN ┬╖ API (Redis) ┬╖ database buffer ┬╖ invalidate on write or use a short TTL
рддреБрдордЪрд╛ snippet рдЫрд╛рдкрддреЛ:
cache 10 classes тЖТ hit ratio 14.9% ┬╖ database reads 17,018
cache 50 classes тЖТ hit ratio 33.8% ┬╖ database reads 13,240
cache 250 classes тЖТ hit ratio 55.0% ┬╖ database reads 9,008
cache 500 classes тЖТ hit ratio 64.0% ┬╖ database reads 7,203
cache 1000 classes тЖТ hit ratio 73.1% ┬╖ database reads 5,382
cache 2500 classes тЖТ hit ratio 83.1% ┬╖ database reads 3,375
cache 5000 classes тЖТ hit ratio 83.9% ┬╖ database reads 3,212
the 50 most popular classes get 9,822 of 20,000 reads (49.1%)
ЁЯПБ рддреБрдореНрд╣реА рдЖрддреНрддрд╛рдЪ рдХрд╛рдп рд╕рд┐рджреНрдз рдХреЗрд▓реЗ
рд╡рдХреНрд░ рд╡рд╛рдХрддреЛ: 10 рд╡рд░реВрди 500 рд╡рд░реНрдЧрд╛рдВрд╡рд░ рдЧреЗрд▓реНрдпрд╛рдиреЗ database reads 17,018 рд╡рд░реВрди 7,203 рд╡рд░ рдпреЗрддрд╛рдд; 2,500 рд╡рд░реВрди рд╕рдЧрд│реНрдпрд╛ 5,000 рд╡рд░ рдЧреЗрд▓реНрдпрд╛рдиреЗ рдлрдХреНрдд рдЖрдгрдЦреА 163 рд╡рд╛рдЪрддрд╛рдд. рд╕рдЧрд│реЗ рдХрд╛рд╣реА рдареЗрд╡рдгрд╛рд░рд╛ cache рд╕реБрджреНрдзрд╛ 83.9% рд╡рд░ рдерд╛рдВрдмрддреЛ тАФ рдкреНрд░рддреНрдпреЗрдХ рд╡рд░реНрдЧрд╛рдЪрд╛ рдкрд╣рд┐рд▓рд╛ read рдиреЗрд╣рдореА miss рдЕрд╕рддреЛ. рдЖрдгрд┐ 50 рд╕рд░реНрд╡рд╛рдд рд▓реЛрдХрдкреНрд░рд┐рдп рд╡рд░реНрдЧрд╛рдВрдирд╛ 49.1% reads рдорд┐рд│рддрд╛рдд, рдкрдг 50 рдЬрд╛рдЧрд╛рдВрдЪрд╛ LRU рдлрдХреНрдд 33.8% рдкрдХрдбрддреЛ: рд╢рд╛рдВрдд рд╡рд░реНрдЧ рд▓реЛрдХрдкреНрд░рд┐рдп рд╡рд░реНрдЧрд╛рдВрдирд╛ рдмрд╛рд╣реЗрд░ рдврдХрд▓рдд рд░рд╛рд╣рддрд╛рдд. рдЖрдХрд╛рд░ рд╡рдХреНрд░рд╛рд╡рд░реВрди рдард░рд╡рд╛, "рдкрд░рд╡рдбреЗрд▓ рддрд┐рддрдХрд╛ рдореЛрдард╛" рдпрд╛рд╡рд░реВрди рдирд╛рд╣реА.
тЪая╕П рдиреЗрд╣рдореАрдЪреНрдпрд╛ рдЪреБрдХрд╛
- TTL рдирд╛рд╣реА рдЖрдгрд┐ invalidation рдирд╛рд╣реА рдЕрд╕рд╛ cache тАФ рд╡рд╛рдЪрдгрд╛рд▒реНрдпрд╛рдВрд╕рд╛рдареА рдХрдзреАрдЪ update рди рд╣реЛрдгрд╛рд░реА рд╕реВрдЪрдирд╛
- рдкреНрд░рддреНрдпреЗрдХ рдкрд╛рд▓рдХрд╛рдЪрд╛ data рд╕рд╛рдорд╛рдпрд┐рдХ key рдЦрд╛рд▓реА cache рдХрд░рдгреЗ тАФ рдПрдХрд╛ рдкрд╛рд▓рдХрд╛рд▓рд╛ рджреБрд╕рд▒реНрдпрд╛ рдкрд╛рд▓рдХрд╛рдЪреЗ feed рджрд┐рд╕рддреЗ
- write рд╡рд░ cache delete рдХрд░рдгреНрдпрд╛рдРрд╡рдЬреА update рдХрд░рдгреЗ (рд╢рд░реНрдпрддреАрдВрдореБрд│реЗ рдЬреБрдиреА value рд░рд╛рд╣рддреЗ)
- index рдирд╕рд▓реНрдпрд╛рдиреЗ рд╣рд│реВ рдЕрд╕рд▓реЗрд▓реНрдпрд╛ query рдкреБрдвреЗ cache тАФ рдЖрдзреА index рджреБрд░реБрд╕реНрдд рдХрд░рд╛ (рдзрдбрд╛ 04)
- рдЕрдиреЗрдХ рд╡рд╛рдЪрдгрд╛рд▒реНрдпрд╛рдВрдЪрд╛ рдПрдХрд╛рдЪ рдХрд╛рд▓рдмрд╛рд╣реНрдп key рд╡рд░ рдПрдХрджрдо miss рдЖрдгрд┐ рд╕рдЧрд│реЗ database рд╡рд░ рдЖрджрд│рддрд╛рдд (stampede) тАФ Scaling рд╢рд╛рд│рд╛ рдкрд╛рд╣рд╛
- cache рд╣реАрдЪ рдПрдХрдореЗрд╡ рдкреНрд░рдд рдорд╛рдирдгреЗ: Redis restart рд╣реЛрддреЛ; database рд╣реЗрдЪ рд╕рддреНрдп
ЁЯПн рдкреНрд░рддреНрдпрдХреНрд╖ рд╡рд╛рдкрд░рд╛рдд
рд╡рд░реНрдЧрд╛рдЪреНрдпрд╛ feed рд╕рд╛рдареА cache-aside, API рдордзреНрдпреЗ (Python рд╕рд╛рд░рдЦрд╛ pseudo-code):
def class_feed(class_id):
key = f"feed:{class_id}:v1"
hit = redis.get(key)
if hit: return json.loads(hit)
rows = db.query("SELECT тАж FROM notices WHERE class_id = %s ORDER BY created_at DESC LIMIT 20", class_id)
redis.set(key, json.dumps(rows), ex=60) # TTL 60 s: the longest staleness we accept
return rows
def post_notice(class_id, notice):
db.insert(notice) # the database first тАФ it is the truth
redis.delete(f"feed:{class_id}:v1") # then invalidate
On a real account тАФ рдХрд╛рд░реНрдпрд╛рд▓рдпрд╛рд╕рд╛рдареА рдПрдХ рд▓рд╣рд╛рди Redis (ElastiCache Serverless), рдЖрдгрд┐ рд▓рдХреНрд╖ рдареЗрд╡рд╛рдпрдЪрд╛ CloudWatch рдЖрдХрдбрд╛:
aws elasticache create-serverless-cache --serverless-cache-name notice-cache --engine redis
aws cloudwatch get-metric-statistics --namespace AWS/ElastiCache --metric-name CacheHitRate \
--dimensions Name=CacheClusterId,Value=notice-cache --statistics Average --period 300 \
--start-time 2026-09-21T00:00:00Z --end-time 2026-09-22T00:00:00Z
рдЕрдзрд┐рдХ рдЦреЛрд▓рд╛рдд: Scaling рд╢рд╛рд│рд╛, рдзрдбрд╛ 09 (Redis рд╕рд╣ cache-aside, TTLs рдЖрдгрд┐ stampede рдерд╛рдВрдмрд╡рдгреЗ), рдЖрдгрд┐ CDN caching рд╕рд╛рдареА рддрд┐рдерд▓реЗ рдзрдбреЗ 03тАУ04.
ЁЯПн рдкреНрд░рддреНрдпрдХреНрд╖ рд╡рд╛рдкрд░рд╛рдд рд╣реЗ рдХрд╛ рдорд╣рддреНрддреНрд╡рд╛рдЪреЗ: рдкреНрд░рддреНрдпреЗрдХ cache рд╕рд╛рдареА TTL рдЖрдгрд┐ invalidation рдЪрд╛ рдирд┐рдпрдо design doc рдордзреНрдпреЗ рд▓рд┐рд╣рд╛. "60 s рдкрд░реНрдпрдВрдд рдЬреБрдиреЗ" рд╣рд╛ product рдирд┐рд░реНрдгрдп рдЖрд╣реЗ тАФ рддрд╛рддрдбреАрдЪреНрдпрд╛ рд╕реВрдЪрдиреЗрд╕рд╛рдареА 60 s рдЪрд╛рд▓реЗрд▓ рдХрд╛ рддреЗ рд╢рд╛рд│реЗрд▓рд╛ рд╡рд┐рдЪрд╛рд░рд╛ (рдХрджрд╛рдЪрд┐рдд рдЪрд╛рд▓рдгрд╛рд░ рдирд╛рд╣реА; рддрд╛рддрдбреАрдЪреНрдпрд╛ рд╕реВрдЪрдирд╛ cache рд╡рдЧрд│реВ рд╢рдХрддрд╛рдд).
тПня╕П рдкреБрдвреЗ
Cache рдЖрдгрд┐ API рдЕрдиреЗрдХ servers рд╡рд░ рдЪрд╛рд▓рддрд╛рдд. рдкреНрд░рддреНрдпреЗрдХ request рдХреЛрдгрддреНрдпрд╛ server рд▓рд╛ рдЬрд╛рддреЛ тАФ рдЖрдгрд┐ рдХреЛрдгрддрд╛ cache server рдХреЛрдгрддрд╛ рд╡рд░реНрдЧ рдареЗрд╡рддреЛ тАФ рд╣реЗ рдХреЛрдг рдард░рд╡рддреЗ?
git checkout lesson-06-load-balancing