1602 lines
49 KiB
HTML
1602 lines
49 KiB
HTML
|
|
<!doctype html>
|
|
<html lang="en" class="no-js">
|
|
<head>
|
|
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
|
|
|
|
|
|
|
|
<link rel="prev" href="../../preface/">
|
|
|
|
|
|
<link rel="next" href="../chapter2/">
|
|
|
|
|
|
|
|
|
|
|
|
<link rel="icon" href="../../../../assets/images/favicon.png">
|
|
<meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.7.6">
|
|
|
|
|
|
|
|
<title>Chapter 1. Reliable, Scalable and Maintainable Applications - Notes</title>
|
|
|
|
|
|
|
|
<link rel="stylesheet" href="../../../../assets/stylesheets/main.484c7ddc.min.css">
|
|
|
|
|
|
<link rel="stylesheet" href="../../../../assets/stylesheets/palette.ab4e12ef.min.css">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback">
|
|
<style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
|
|
|
|
|
|
|
|
<script>__md_scope=new URL("../../../..",location),__md_hash=e=>[...e].reduce(((e,_)=>(e<<5)-e+_.charCodeAt(0)),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
|
|
|
|
|
|
|
|
|
|
|
|
</head>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<body dir="ltr" data-md-color-scheme="default" data-md-color-primary="indigo" data-md-color-accent="indigo">
|
|
|
|
|
|
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
|
|
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
|
|
<label class="md-overlay" for="__drawer"></label>
|
|
<div data-md-component="skip">
|
|
|
|
|
|
<a href="#chapter-1-reliable-scalable-and-maintainable-applications" class="md-skip">
|
|
Skip to content
|
|
</a>
|
|
|
|
</div>
|
|
<div data-md-component="announce">
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<header class="md-header" data-md-component="header">
|
|
<nav class="md-header__inner md-grid" aria-label="Header">
|
|
<a href="../../../.." title="Notes" class="md-header__button md-logo" aria-label="Notes" data-md-component="logo">
|
|
|
|
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54"/></svg>
|
|
|
|
</a>
|
|
<label class="md-header__button md-icon" for="__drawer">
|
|
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z"/></svg>
|
|
</label>
|
|
<div class="md-header__title" data-md-component="header-title">
|
|
<div class="md-header__ellipsis">
|
|
<div class="md-header__topic">
|
|
<span class="md-ellipsis">
|
|
Notes
|
|
</span>
|
|
</div>
|
|
<div class="md-header__topic" data-md-component="header-topic">
|
|
<span class="md-ellipsis">
|
|
|
|
Chapter 1. Reliable, Scalable and Maintainable Applications
|
|
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<form class="md-header__option" data-md-component="palette">
|
|
|
|
|
|
|
|
|
|
<input class="md-option" data-md-color-media="" data-md-color-scheme="default" data-md-color-primary="indigo" data-md-color-accent="indigo" aria-label="Switch to dark mode" type="radio" name="__palette" id="__palette_0">
|
|
|
|
<label class="md-header__button md-icon" title="Switch to dark mode" for="__palette_1" hidden>
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="m17.75 4.09-2.53 1.94.91 3.06-2.63-1.81-2.63 1.81.91-3.06-2.53-1.94L12.44 4l1.06-3 1.06 3zm3.5 6.91-1.64 1.25.59 1.98-1.7-1.17-1.7 1.17.59-1.98L15.75 11l2.06-.05L18.5 9l.69 1.95zm-2.28 4.95c.83-.08 1.72 1.1 1.19 1.85-.32.45-.66.87-1.08 1.27C15.17 23 8.84 23 4.94 19.07c-3.91-3.9-3.91-10.24 0-14.14.4-.4.82-.76 1.27-1.08.75-.53 1.93.36 1.85 1.19-.27 2.86.69 5.83 2.89 8.02a9.96 9.96 0 0 0 8.02 2.89m-1.64 2.02a12.08 12.08 0 0 1-7.8-3.47c-2.17-2.19-3.33-5-3.49-7.82-2.81 3.14-2.7 7.96.31 10.98 3.02 3.01 7.84 3.12 10.98.31"/></svg>
|
|
</label>
|
|
|
|
|
|
|
|
|
|
|
|
<input class="md-option" data-md-color-media="" data-md-color-scheme="slate" data-md-color-primary="indigo" data-md-color-accent="indigo" aria-label="Switch to light mode" type="radio" name="__palette" id="__palette_1">
|
|
|
|
<label class="md-header__button md-icon" title="Switch to light mode" for="__palette_0" hidden>
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 7a5 5 0 0 1 5 5 5 5 0 0 1-5 5 5 5 0 0 1-5-5 5 5 0 0 1 5-5m0 2a3 3 0 0 0-3 3 3 3 0 0 0 3 3 3 3 0 0 0 3-3 3 3 0 0 0-3-3m0-7 2.39 3.42C13.65 5.15 12.84 5 12 5s-1.65.15-2.39.42zM3.34 7l4.16-.35A7.2 7.2 0 0 0 5.94 8.5c-.44.74-.69 1.5-.83 2.29zm.02 10 1.76-3.77a7.131 7.131 0 0 0 2.38 4.14zM20.65 7l-1.77 3.79a7.02 7.02 0 0 0-2.38-4.15zm-.01 10-4.14.36c.59-.51 1.12-1.14 1.54-1.86.42-.73.69-1.5.83-2.29zM12 22l-2.41-3.44c.74.27 1.55.44 2.41.44.82 0 1.63-.17 2.37-.44z"/></svg>
|
|
</label>
|
|
|
|
|
|
</form>
|
|
|
|
|
|
|
|
<script>var palette=__md_get("__palette");if(palette&&palette.color){if("(prefers-color-scheme)"===palette.color.media){var media=matchMedia("(prefers-color-scheme: light)"),input=document.querySelector(media.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']");palette.color.media=input.getAttribute("data-md-color-media"),palette.color.scheme=input.getAttribute("data-md-color-scheme"),palette.color.primary=input.getAttribute("data-md-color-primary"),palette.color.accent=input.getAttribute("data-md-color-accent")}for(var[key,value]of Object.entries(palette.color))document.body.setAttribute("data-md-color-"+key,value)}</script>
|
|
|
|
|
|
|
|
|
|
|
|
<label class="md-header__button md-icon" for="__search">
|
|
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
|
|
</label>
|
|
<div class="md-search" data-md-component="search" role="dialog">
|
|
<label class="md-search__overlay" for="__search"></label>
|
|
<div class="md-search__inner" role="search">
|
|
<form class="md-search__form" name="search">
|
|
<input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required>
|
|
<label class="md-search__icon md-icon" for="__search">
|
|
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
|
|
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"/></svg>
|
|
</label>
|
|
<nav class="md-search__options" aria-label="Search">
|
|
|
|
<a href="javascript:void(0)" class="md-search__icon md-icon" title="Share" aria-label="Share" data-clipboard data-clipboard-text="" data-md-component="search-share" tabindex="-1">
|
|
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7s-.04-.47-.09-.7l7.05-4.11c.54.5 1.25.81 2.04.81a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3c0 .24.04.47.09.7L8.04 9.81C7.5 9.31 6.79 9 6 9a3 3 0 0 0-3 3 3 3 0 0 0 3 3c.79 0 1.5-.31 2.04-.81l7.12 4.15c-.05.21-.08.43-.08.66 0 1.61 1.31 2.91 2.92 2.91s2.92-1.3 2.92-2.91A2.92 2.92 0 0 0 18 16.08"/></svg>
|
|
</a>
|
|
|
|
<button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">
|
|
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg>
|
|
</button>
|
|
</nav>
|
|
|
|
<div class="md-search__suggest" data-md-component="search-suggest"></div>
|
|
|
|
</form>
|
|
<div class="md-search__output">
|
|
<div class="md-search__scrollwrap" tabindex="0" data-md-scrollfix>
|
|
<div class="md-search-result" data-md-component="search-result">
|
|
<div class="md-search-result__meta">
|
|
Initializing search
|
|
</div>
|
|
<ol class="md-search-result__list" role="presentation"></ol>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
</nav>
|
|
|
|
</header>
|
|
|
|
<div class="md-container" data-md-component="container">
|
|
|
|
|
|
|
|
|
|
|
|
<nav class="md-tabs" aria-label="Tabs" data-md-component="tabs">
|
|
<div class="md-grid">
|
|
<ul class="md-tabs__list">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-tabs__item">
|
|
<a href="../../../.." class="md-tabs__link">
|
|
|
|
|
|
|
|
|
|
|
|
Home
|
|
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-tabs__item md-tabs__item--active">
|
|
<a href="../../preface/" class="md-tabs__link">
|
|
|
|
|
|
|
|
Books
|
|
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-tabs__item">
|
|
<a href="../../../../lectures/dms/01_java_collections/" class="md-tabs__link">
|
|
|
|
|
|
|
|
Lecture Notes
|
|
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
</ul>
|
|
</div>
|
|
</nav>
|
|
|
|
|
|
|
|
<main class="md-main" data-md-component="main">
|
|
<div class="md-main__inner md-grid">
|
|
|
|
|
|
|
|
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
|
|
<div class="md-sidebar__scrollwrap">
|
|
<div class="md-sidebar__inner">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<nav class="md-nav md-nav--primary md-nav--lifted md-nav--integrated" aria-label="Navigation" data-md-level="0">
|
|
<label class="md-nav__title" for="__drawer">
|
|
<a href="../../../.." title="Notes" class="md-nav__button md-logo" aria-label="Notes" data-md-component="logo">
|
|
|
|
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54"/></svg>
|
|
|
|
</a>
|
|
Notes
|
|
</label>
|
|
|
|
<ul class="md-nav__list" data-md-scrollfix>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../../.." class="md-nav__link">
|
|
|
|
|
|
|
|
<span class="md-ellipsis">
|
|
|
|
|
|
Home
|
|
|
|
|
|
|
|
</span>
|
|
|
|
|
|
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item md-nav__item--active md-nav__item--section md-nav__item--nested">
|
|
|
|
|
|
|
|
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2" checked>
|
|
|
|
|
|
<label class="md-nav__link" for="__nav_2" id="__nav_2_label" tabindex="">
|
|
|
|
|
|
|
|
<span class="md-ellipsis">
|
|
|
|
|
|
Books
|
|
|
|
|
|
|
|
</span>
|
|
|
|
|
|
|
|
<span class="md-nav__icon md-icon"></span>
|
|
</label>
|
|
|
|
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_2_label" aria-expanded="true">
|
|
<label class="md-nav__title" for="__nav_2">
|
|
<span class="md-nav__icon md-icon"></span>
|
|
|
|
|
|
Books
|
|
|
|
|
|
</label>
|
|
<ul class="md-nav__list" data-md-scrollfix>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item md-nav__item--active md-nav__item--nested">
|
|
|
|
|
|
|
|
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_1" checked>
|
|
|
|
|
|
<label class="md-nav__link" for="__nav_2_1" id="__nav_2_1_label" tabindex="0">
|
|
|
|
|
|
|
|
<span class="md-ellipsis">
|
|
|
|
|
|
Designing Data-Intensive Applications
|
|
|
|
|
|
|
|
</span>
|
|
|
|
|
|
|
|
<span class="md-nav__icon md-icon"></span>
|
|
</label>
|
|
|
|
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_2_1_label" aria-expanded="true">
|
|
<label class="md-nav__title" for="__nav_2_1">
|
|
<span class="md-nav__icon md-icon"></span>
|
|
|
|
|
|
Designing Data-Intensive Applications
|
|
|
|
|
|
</label>
|
|
<ul class="md-nav__list" data-md-scrollfix>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../preface/" class="md-nav__link">
|
|
|
|
|
|
|
|
<span class="md-ellipsis">
|
|
|
|
|
|
Preface
|
|
|
|
|
|
|
|
</span>
|
|
|
|
|
|
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item md-nav__item--active md-nav__item--nested">
|
|
|
|
|
|
|
|
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_1_2" checked>
|
|
|
|
|
|
<label class="md-nav__link" for="__nav_2_1_2" id="__nav_2_1_2_label" tabindex="0">
|
|
|
|
|
|
|
|
<span class="md-ellipsis">
|
|
|
|
|
|
Part 1. Foundations of Data Systems
|
|
|
|
|
|
|
|
</span>
|
|
|
|
|
|
|
|
<span class="md-nav__icon md-icon"></span>
|
|
</label>
|
|
|
|
<nav class="md-nav" data-md-level="3" aria-labelledby="__nav_2_1_2_label" aria-expanded="true">
|
|
<label class="md-nav__title" for="__nav_2_1_2">
|
|
<span class="md-nav__icon md-icon"></span>
|
|
|
|
|
|
Part 1. Foundations of Data Systems
|
|
|
|
|
|
</label>
|
|
<ul class="md-nav__list" data-md-scrollfix>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item md-nav__item--active">
|
|
|
|
<input class="md-nav__toggle md-toggle" type="checkbox" id="__toc">
|
|
|
|
|
|
|
|
|
|
|
|
<label class="md-nav__link md-nav__link--active" for="__toc">
|
|
|
|
|
|
|
|
<span class="md-ellipsis">
|
|
|
|
|
|
Chapter 1. Reliable, Scalable and Maintainable Applications
|
|
|
|
|
|
|
|
</span>
|
|
|
|
|
|
|
|
<span class="md-nav__icon md-icon"></span>
|
|
</label>
|
|
|
|
<a href="./" class="md-nav__link md-nav__link--active">
|
|
|
|
|
|
|
|
<span class="md-ellipsis">
|
|
|
|
|
|
Chapter 1. Reliable, Scalable and Maintainable Applications
|
|
|
|
|
|
|
|
</span>
|
|
|
|
|
|
|
|
</a>
|
|
|
|
|
|
|
|
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<label class="md-nav__title" for="__toc">
|
|
<span class="md-nav__icon md-icon"></span>
|
|
Table of contents
|
|
</label>
|
|
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#thinking-about-data-systems" class="md-nav__link">
|
|
<span class="md-ellipsis">
|
|
|
|
Thinking about Data Systems
|
|
|
|
</span>
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#reliability" class="md-nav__link">
|
|
<span class="md-ellipsis">
|
|
|
|
Reliability
|
|
|
|
</span>
|
|
</a>
|
|
|
|
<nav class="md-nav" aria-label="Reliability">
|
|
<ul class="md-nav__list">
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#hardware-faults" class="md-nav__link">
|
|
<span class="md-ellipsis">
|
|
|
|
Hardware Faults
|
|
|
|
</span>
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#software-faults" class="md-nav__link">
|
|
<span class="md-ellipsis">
|
|
|
|
Software Faults
|
|
|
|
</span>
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#human-errors" class="md-nav__link">
|
|
<span class="md-ellipsis">
|
|
|
|
Human Errors
|
|
|
|
</span>
|
|
</a>
|
|
|
|
</li>
|
|
|
|
</ul>
|
|
</nav>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#scalability" class="md-nav__link">
|
|
<span class="md-ellipsis">
|
|
|
|
Scalability
|
|
|
|
</span>
|
|
</a>
|
|
|
|
<nav class="md-nav" aria-label="Scalability">
|
|
<ul class="md-nav__list">
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#describing-load" class="md-nav__link">
|
|
<span class="md-ellipsis">
|
|
|
|
Describing Load
|
|
|
|
</span>
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#describing-performance" class="md-nav__link">
|
|
<span class="md-ellipsis">
|
|
|
|
Describing Performance
|
|
|
|
</span>
|
|
</a>
|
|
|
|
<nav class="md-nav" aria-label="Describing Performance">
|
|
<ul class="md-nav__list">
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#approaches-for-coping-with-load" class="md-nav__link">
|
|
<span class="md-ellipsis">
|
|
|
|
Approaches for Coping with Load
|
|
|
|
</span>
|
|
</a>
|
|
|
|
</li>
|
|
|
|
</ul>
|
|
</nav>
|
|
|
|
</li>
|
|
|
|
</ul>
|
|
</nav>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#maintainability" class="md-nav__link">
|
|
<span class="md-ellipsis">
|
|
|
|
Maintainability
|
|
|
|
</span>
|
|
</a>
|
|
|
|
<nav class="md-nav" aria-label="Maintainability">
|
|
<ul class="md-nav__list">
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#operability-making-life-easy-for-operations" class="md-nav__link">
|
|
<span class="md-ellipsis">
|
|
|
|
Operability: Making Life Easy for Operations
|
|
|
|
</span>
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#simplicity-managing-complexity" class="md-nav__link">
|
|
<span class="md-ellipsis">
|
|
|
|
Simplicity: Managing Complexity
|
|
|
|
</span>
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#evolvability-making-change-easy" class="md-nav__link">
|
|
<span class="md-ellipsis">
|
|
|
|
Evolvability: Making Change Easy
|
|
|
|
</span>
|
|
</a>
|
|
|
|
</li>
|
|
|
|
</ul>
|
|
</nav>
|
|
|
|
</li>
|
|
|
|
</ul>
|
|
|
|
</nav>
|
|
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../chapter2/" class="md-nav__link">
|
|
|
|
|
|
|
|
<span class="md-ellipsis">
|
|
|
|
|
|
Chapter 2. Data Models and Query Languages
|
|
|
|
|
|
|
|
</span>
|
|
|
|
|
|
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
</ul>
|
|
</nav>
|
|
|
|
</li>
|
|
|
|
|
|
|
|
|
|
</ul>
|
|
</nav>
|
|
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item md-nav__item--nested">
|
|
|
|
|
|
|
|
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_2" >
|
|
|
|
|
|
<label class="md-nav__link" for="__nav_2_2" id="__nav_2_2_label" tabindex="0">
|
|
|
|
|
|
|
|
<span class="md-ellipsis">
|
|
|
|
|
|
API Design Patterns
|
|
|
|
|
|
|
|
</span>
|
|
|
|
|
|
|
|
<span class="md-nav__icon md-icon"></span>
|
|
</label>
|
|
|
|
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_2_2_label" aria-expanded="false">
|
|
<label class="md-nav__title" for="__nav_2_2">
|
|
<span class="md-nav__icon md-icon"></span>
|
|
|
|
|
|
API Design Patterns
|
|
|
|
|
|
</label>
|
|
<ul class="md-nav__list" data-md-scrollfix>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item md-nav__item--nested">
|
|
|
|
|
|
|
|
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_2_1" >
|
|
|
|
|
|
<label class="md-nav__link" for="__nav_2_2_1" id="__nav_2_2_1_label" tabindex="0">
|
|
|
|
|
|
|
|
<span class="md-ellipsis">
|
|
|
|
|
|
Part 1. Introduction
|
|
|
|
|
|
|
|
</span>
|
|
|
|
|
|
|
|
<span class="md-nav__icon md-icon"></span>
|
|
</label>
|
|
|
|
<nav class="md-nav" data-md-level="3" aria-labelledby="__nav_2_2_1_label" aria-expanded="false">
|
|
<label class="md-nav__title" for="__nav_2_2_1">
|
|
<span class="md-nav__icon md-icon"></span>
|
|
|
|
|
|
Part 1. Introduction
|
|
|
|
|
|
</label>
|
|
<ul class="md-nav__list" data-md-scrollfix>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../../api_design_patterns/part1/chapter1/" class="md-nav__link">
|
|
|
|
|
|
|
|
<span class="md-ellipsis">
|
|
|
|
|
|
Chapter 1. Introduction to APIs
|
|
|
|
|
|
|
|
</span>
|
|
|
|
|
|
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../../api_design_patterns/part1/chapter2/" class="md-nav__link">
|
|
|
|
|
|
|
|
<span class="md-ellipsis">
|
|
|
|
|
|
Chapter 2. Introduction to API Design Patterns
|
|
|
|
|
|
|
|
</span>
|
|
|
|
|
|
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
</ul>
|
|
</nav>
|
|
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item md-nav__item--nested">
|
|
|
|
|
|
|
|
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_2_2" >
|
|
|
|
|
|
<label class="md-nav__link" for="__nav_2_2_2" id="__nav_2_2_2_label" tabindex="0">
|
|
|
|
|
|
|
|
<span class="md-ellipsis">
|
|
|
|
|
|
Part 2. Design Principles
|
|
|
|
|
|
|
|
</span>
|
|
|
|
|
|
|
|
<span class="md-nav__icon md-icon"></span>
|
|
</label>
|
|
|
|
<nav class="md-nav" data-md-level="3" aria-labelledby="__nav_2_2_2_label" aria-expanded="false">
|
|
<label class="md-nav__title" for="__nav_2_2_2">
|
|
<span class="md-nav__icon md-icon"></span>
|
|
|
|
|
|
Part 2. Design Principles
|
|
|
|
|
|
</label>
|
|
<ul class="md-nav__list" data-md-scrollfix>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../../api_design_patterns/part2/chapter3/" class="md-nav__link">
|
|
|
|
|
|
|
|
<span class="md-ellipsis">
|
|
|
|
|
|
Chapter 3. Naming
|
|
|
|
|
|
|
|
</span>
|
|
|
|
|
|
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../../api_design_patterns/part2/chapter4/" class="md-nav__link">
|
|
|
|
|
|
|
|
<span class="md-ellipsis">
|
|
|
|
|
|
Chapter 4. Resource Scope and Hierarchy
|
|
|
|
|
|
|
|
</span>
|
|
|
|
|
|
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
</ul>
|
|
</nav>
|
|
|
|
</li>
|
|
|
|
|
|
|
|
|
|
</ul>
|
|
</nav>
|
|
|
|
</li>
|
|
|
|
|
|
|
|
|
|
</ul>
|
|
</nav>
|
|
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item md-nav__item--nested">
|
|
|
|
|
|
|
|
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3" >
|
|
|
|
|
|
<label class="md-nav__link" for="__nav_3" id="__nav_3_label" tabindex="0">
|
|
|
|
|
|
|
|
<span class="md-ellipsis">
|
|
|
|
|
|
Lecture Notes
|
|
|
|
|
|
|
|
</span>
|
|
|
|
|
|
|
|
<span class="md-nav__icon md-icon"></span>
|
|
</label>
|
|
|
|
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_3_label" aria-expanded="false">
|
|
<label class="md-nav__title" for="__nav_3">
|
|
<span class="md-nav__icon md-icon"></span>
|
|
|
|
|
|
Lecture Notes
|
|
|
|
|
|
</label>
|
|
<ul class="md-nav__list" data-md-scrollfix>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item md-nav__item--nested">
|
|
|
|
|
|
|
|
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3_1" >
|
|
|
|
|
|
<label class="md-nav__link" for="__nav_3_1" id="__nav_3_1_label" tabindex="0">
|
|
|
|
|
|
|
|
<span class="md-ellipsis">
|
|
|
|
|
|
Developing Maintainable Software
|
|
|
|
|
|
|
|
</span>
|
|
|
|
|
|
|
|
<span class="md-nav__icon md-icon"></span>
|
|
</label>
|
|
|
|
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_1_label" aria-expanded="false">
|
|
<label class="md-nav__title" for="__nav_3_1">
|
|
<span class="md-nav__icon md-icon"></span>
|
|
|
|
|
|
Developing Maintainable Software
|
|
|
|
|
|
</label>
|
|
<ul class="md-nav__list" data-md-scrollfix>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../../../lectures/dms/01_java_collections/" class="md-nav__link">
|
|
|
|
|
|
|
|
<span class="md-ellipsis">
|
|
|
|
|
|
Java Collections
|
|
|
|
|
|
|
|
</span>
|
|
|
|
|
|
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../../../lectures/dms/02_uml/" class="md-nav__link">
|
|
|
|
|
|
|
|
<span class="md-ellipsis">
|
|
|
|
|
|
UML Diagrams
|
|
|
|
|
|
|
|
</span>
|
|
|
|
|
|
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
</ul>
|
|
</nav>
|
|
|
|
</li>
|
|
|
|
|
|
|
|
|
|
</ul>
|
|
</nav>
|
|
|
|
</li>
|
|
|
|
|
|
|
|
</ul>
|
|
</nav>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="md-content" data-md-component="content">
|
|
|
|
<article class="md-content__inner md-typeset">
|
|
|
|
|
|
|
|
|
|
|
|
<h1 id="chapter-1-reliable-scalable-and-maintainable-applications">Chapter 1: Reliable, Scalable and Maintainable Applications<a class="headerlink" href="#chapter-1-reliable-scalable-and-maintainable-applications" title="Permanent link">¶</a></h1>
|
|
<p>Many applications today are <em>data-intensive</em>, as opposed to <em>compute-intensive</em>. Raw CPU power is rarely a limiting factor for these applications.</p>
|
|
<p>A data-intensive application is built from the following building blocks</p>
|
|
<ul>
|
|
<li>Store data so that they, or another application can find it again later (<em>databases</em>)</li>
|
|
<li>Remember the result of an expensive operation, to sped up reads (<em>caches</em>)</li>
|
|
<li>Allow users to search data by keyword or filter it in various ways (<em>search indexes</em>)</li>
|
|
<li>Send a message to another process, to be handled asynchronously (<em>stream processing</em>)</li>
|
|
<li>Periodically crunch a large amount of accumulated data (<em>batch processing</em>)</li>
|
|
</ul>
|
|
<h2 id="thinking-about-data-systems">Thinking about Data Systems<a class="headerlink" href="#thinking-about-data-systems" title="Permanent link">¶</a></h2>
|
|
<p>Database and a message queue are quite similar. They both store data for some time - though they have very different access patterns which means different performance characteristics and thus very different implementations.</p>
|
|
<p>Boundaries between these implementations are becoming slightly blurred. There are data-stores that are also used as message queues (<em>Redis</em>) and there are messages queues with database-like durability guarantees (<em>Apache Kafka</em>).</p>
|
|
<figure>
|
|
<img src="/books/designing_data_intensive_applications/media/ddia_0101.gif">
|
|
<figcaption>One possible architecture for data system that combines several components</figcaption>
|
|
</figure>
|
|
|
|
<p>When you combine several tools in order to provide a service, the service's interface or application programming interface (API) usually hides those implementation details from clients.</p>
|
|
<ul>
|
|
<li><em>Reliability</em>: The system should continue to work <em>correctly</em> (performing the correct function at the desired level of performance) even in the face of <em>adversity</em> (hardware or software faults, even human error).</li>
|
|
<li><em>Scalability</em>: As the system <em>grows</em> (in data volume, traffic volume or complexity), there should be reasonable ways of dealing with that growth.</li>
|
|
<li><em>Maintainability</em>: Over time, many different people will work on the system (engineering and operations, both maintaining current behaviour and adapting the system to new use cases), and they should all be able to work in it <em>productively</em>.</li>
|
|
</ul>
|
|
<h2 id="reliability">Reliability<a class="headerlink" href="#reliability" title="Permanent link">¶</a></h2>
|
|
<ul>
|
|
<li>The application performs the function that the user expected.</li>
|
|
<li>It can tolerate the user making mistakes or using the software in unexpected ways.</li>
|
|
<li>Its performance is good enough for the required use case, under the expected load and data volume.</li>
|
|
<li>The system prevents any unauthorized access and abuse.</li>
|
|
</ul>
|
|
<p>Things that ca go wrong are called <em>faults</em>. Systems that anticipate faults and can cope with them are called <em>fault-tolerant</em> or <em>resilient</em>. Fault tolerance does not mean making a system tolerant of all faults, but only tolerating <em>certain types</em> of faults.</p>
|
|
<p><strong>NOTE</strong>: A fault is not the same as a failure. </p>
|
|
<ul>
|
|
<li>A fault is defined as one component of the system deviating from its spec.</li>
|
|
<li>A failure is when the system as a whole stops providing the required service to the user,</li>
|
|
</ul>
|
|
<p>It is impossible to to reduce the probability of a fault to zero; therefore it is best to design fault-tolerance mechanisms that prevent faults from causing failures.</p>
|
|
<h3 id="hardware-faults">Hardware Faults<a class="headerlink" href="#hardware-faults" title="Permanent link">¶</a></h3>
|
|
<p>Hard disks are reported as having a mean time to failing (MTTF) of about 10 to 50 years. So on a storage cluster with 10,000 disks, we should expect on average one disk to die per day.</p>
|
|
<p>A good combatant for this is <strong>redundancy</strong>. Disks may be set up in RAID configurations, servers can have dual power supplies etc. When a component dies, the redundant component can take it's place whilst the broken one is being replaced. This approach cannot complete prevent hardware problems from causing failures, but it is well understood and can often keep a machine running uninterrupted for years.</p>
|
|
<p>However, as data volumes and applications' computing demands have increased, more applications have begun using larger number of machines, which proportionally increase the rate of hardware faults. Moreover, in some cloud platforms such as AWS it is fairly common for virtual machine instances to become unavailable without warning as the platforms are designed to prioritise flexibility and elasticity over single-machine reliability.</p>
|
|
<p>Hence there is a move toward systems that can tolerate the loss of entire machines, by using software fault-tolerance techniques in preference or in addition to hardware redundancy. Such systems also have operations advantages: a single-server system requires planned downtime, whereas a system that can tolerate machine failure can be patched one node at a time with no downtime of the entire system (<em>rolling upgrade</em>).</p>
|
|
<h3 id="software-faults">Software Faults<a class="headerlink" href="#software-faults" title="Permanent link">¶</a></h3>
|
|
<p>Hardware faults are normally random and independent form each other. This is not the case for software faults. Software fault can lie dormant for a long time until they are triggered by am unusual set of circumstances. Though there is no quick solution, there are lots of small ones:</p>
|
|
<ul>
|
|
<li>Testing</li>
|
|
<li>Process isolation</li>
|
|
<li>Allowing crash & restart</li>
|
|
<li>Measuring and monitoring</li>
|
|
</ul>
|
|
<h3 id="human-errors">Human Errors<a class="headerlink" href="#human-errors" title="Permanent link">¶</a></h3>
|
|
<p>Humans design and build software systems, and the operators are also human. Humans are unreliable.</p>
|
|
<p>10%-25% of outages are caused by hardware faults, the rest are human related faults.</p>
|
|
<ul>
|
|
<li>Design systems in a way that minimises opportunities for error.<ul>
|
|
<li>e.g. well designed abstractions, APIs and admin interfaces that make it easy to do "the right thing"</li>
|
|
</ul>
|
|
</li>
|
|
<li>Decouple the places where people make the most mistakes from places where they can cause failures<ul>
|
|
<li>Provide fully featured non-production <em>sandbox</em> environments.</li>
|
|
</ul>
|
|
</li>
|
|
<li>Test thoroughly at all levels, from unit tests to whole-system integration tests & manual tests.</li>
|
|
<li>Allow quick and easy recovery from human errors to minimise the impact in the case of failure.<ul>
|
|
<li>Make it fast to roll back configuration changes</li>
|
|
<li>Roll out new code gradually</li>
|
|
<li>Provide tools to recompute data</li>
|
|
</ul>
|
|
</li>
|
|
<li>Set up detailed and clear monitoring, such as performance metrics and error rates.</li>
|
|
</ul>
|
|
<h2 id="scalability">Scalability<a class="headerlink" href="#scalability" title="Permanent link">¶</a></h2>
|
|
<p>Even if a system is working reliably today, that doesn't mean it will necessarily work reliably in the future.</p>
|
|
<p><em>Scalability</em> is the term we used to describe a system's ability to cope with increased load.</p>
|
|
<h3 id="describing-load">Describing Load<a class="headerlink" href="#describing-load" title="Permanent link">¶</a></h3>
|
|
<p>Load can be described with a few numbers which we call <em>load parameters</em>. These parameters depend on the architecture of the system. It might be:</p>
|
|
<ul>
|
|
<li>Requests per second</li>
|
|
<li>Ratio of reads to writes</li>
|
|
<li>Number of simultaneous active users</li>
|
|
<li>Hit rate on cache</li>
|
|
</ul>
|
|
<p>Consider <strong>Twitter</strong> as an example, they have two main operations, <em>post tweet</em> and <em>home timeline</em>. There are two ways of implementing these.</p>
|
|
<p><strong>Approach 1</strong>: Posting a tweet simply inserts the new tweet into a global collection of tweets. When user requests their home timeline, look up all the people they follow, find all the tweets for each of those users and merge them (sorting on time). In a <strong>relational database</strong>
|
|
<div class="highlight"><pre><span></span><code><span class="k">SELECT</span><span class="w"> </span><span class="n">tweets</span><span class="p">.</span><span class="o">*</span><span class="p">,</span><span class="w"> </span><span class="n">users</span><span class="p">.</span><span class="o">*</span>
|
|
<span class="k">FROM</span><span class="w"> </span><span class="n">tweets</span>
|
|
<span class="k">JOIN</span><span class="w"> </span><span class="n">users</span><span class="w"> </span><span class="k">ON</span><span class="w"> </span><span class="n">tweets</span><span class="p">.</span><span class="n">sender_id</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">users</span><span class="p">.</span><span class="n">id</span>
|
|
<span class="k">JOIN</span><span class="w"> </span><span class="n">follows</span><span class="w"> </span><span class="k">ON</span><span class="w"> </span><span class="n">follows</span><span class="p">.</span><span class="n">followee_id</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">users</span><span class="p">.</span><span class="n">id</span>
|
|
<span class="k">WHERE</span><span class="w"> </span><span class="n">follows</span><span class="p">.</span><span class="n">follower_id</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">current_user</span>
|
|
</code></pre></div>
|
|
<strong>Approach 2</strong>: Maintain a cache for each user's home timeline - like a mailbox of tweets for each user. When user <em>posts a tweet</em>, look up all the people who follow that user, and insert the new tweet into each of their home timeline caches. The request to read the home timeline is the cheap, because its result has been computed ahead of time.</p>
|
|
<figure>
|
|
<img src="/books/designing_data_intensive_applications/media/ddia_0103.gif">
|
|
<figcaption>Twitter's data pipeline for delivering tweets to followers, with load parameters</figcaption>
|
|
</figure>
|
|
|
|
<p>The first version of Twitter used approach 1, but the systems struggled to keep up with the load of home timeline queries, so the company switched to approach 2. The average rate of published tweets is almost two orders of magnitude lower than the rate of home timeline reads, so in this case its preferable to do more work at write time and less at read time.</p>
|
|
<p>However the downside of approach 2 is posting a tweet now requires a lot of extra work. On average a tweet is delivered to about 75 followers, so 4.6K tweets/second became 345k writes/second to home timeline caches. However now consider some accounts have 30 million followers.</p>
|
|
<p>Twitter uses a hybrid of both solutions. For users with smaller follow counts approach 2 is used, however for celebrity accounts approach 1 is used and these two timelines are merged together.</p>
|
|
<h3 id="describing-performance">Describing Performance<a class="headerlink" href="#describing-performance" title="Permanent link">¶</a></h3>
|
|
<p>Once you have described the load on your system, you can investigate what happens when load increases.</p>
|
|
<ul>
|
|
<li>When you increase a load parameter and keep the system resources unchanged, how is the performance of your system affected?</li>
|
|
<li>When you increase a load parameter, how much do you need to increase the resources if you want to keep performance unchanged?</li>
|
|
</ul>
|
|
<blockquote>
|
|
<p><strong>LATENCY AND RESPONSE TIME</strong></p>
|
|
<p><em>Latency</em> and <em>response time</em> are often used synonymously, but they are not the same.
|
|
<strong>Response time</strong>: Is what the client sees: the sum of service time, network delays and queuing delays.
|
|
<strong>Latency</strong>: Is the duration that a request is waiting to be handled - during which it is <em>latent</em>, awaiting service.</p>
|
|
</blockquote>
|
|
<figure>
|
|
<img src="/books/designing_data_intensive_applications/media/ddia_0104.gif">
|
|
<figcaption>Illustrating mean and percentiles: response times for a sample of 100 requests to a service</figcaption>
|
|
</figure>
|
|
|
|
<p>Most requests are reasonably fast, but there are occasional <em>outliers</em> that take much longer. Perhaps these requests are intrinsically more expensive - however even the same request will see variations due to all matter of reasons.</p>
|
|
<p><em>Average</em> response time of a service is common however it is not a very good metric if you want to know your "typical" response time - it doesn't tell you how many users actually experienced that delay.</p>
|
|
<p><em>Percentiles</em> are a better metric. </p>
|
|
<ul>
|
|
<li>Take all response times, sort them and the <em>median</em> is the half way point. </li>
|
|
<li>This makes the median a good metric if you want to know how long users typically have to wait: half of users are served in less than the median, the other half longer. The median is also known as the <em>50<sup>th</sup> percentile</em> and abbreviated as <em>p50</em>.</li>
|
|
<li>Note this refers to a single request. If a user creates multiple requests, the probability that one of them is over the p50 is much greater than 50%.</li>
|
|
<li>In order to figure out how bad your outliers are you can look at higher percentiles: the <em>95<sup>th</sup></em>, <em>99<sup>th</sup></em> and <em>99.9<sup>th</sup></em> (abbreviated to <em>p95</em>, <em>p99</em> and <em>p999</em>).<ul>
|
|
<li>e.g. if p95 is 1.5 seconds, that means 95 out of 100 requests are served quicker than 1.5 seconds, and 5 are served slower.</li>
|
|
</ul>
|
|
</li>
|
|
<li>High percentiles of response times (also known as <em>tail latencies</em>), are important because they directly affect users' experience of the service.</li>
|
|
</ul>
|
|
<p>Amazon descries response time requirements for internal services in terms of p999 even though it only affects 1 in 1000 requests. This is because customers with the slowest requests are often those who have the most data in their accounts (valuable customers).</p>
|
|
<p>Queuing delays often account for a large part of the response time at high percentiles. It only takes a small number of sow requests to hold up the processing of subsequent requests - known as <em>head-of-line blocking</em>. Due to this it is important to measure response times on client side.</p>
|
|
<figure>
|
|
<img src="/books/designing_data_intensive_applications/media/ddia_0105.gif">
|
|
<figcaption>When several back end calls are needed to serve a request, it takes just a single slow back end request to slow down the entire end-user request.</figcaption>
|
|
</figure>
|
|
|
|
<h4 id="approaches-for-coping-with-load">Approaches for Coping with Load<a class="headerlink" href="#approaches-for-coping-with-load" title="Permanent link">¶</a></h4>
|
|
<p><strong>Vertical Scaling</strong>: Moving to a more powerful machine.</p>
|
|
<p><strong>Horizontal Scaling</strong>: Distributing the load across multiple smaller machines.</p>
|
|
<p>Some systems are <em>elastic</em>, meaning that they can automatically add computing resources when they detect a load increase. Elastic systems are useful if load is unpredictable, but manual/periodic scaled systems are simpler and have fewer operational surprises.</p>
|
|
<p>While distributing stateless services across multiple machines is fairly straightforward, taking stateful data systems from a single node to a distributed set up can introduce additional complexity. Common wisdom (until recently) was to keep your database on a single node and vertically scale until cost dictated horizontal scaling.</p>
|
|
<h2 id="maintainability">Maintainability<a class="headerlink" href="#maintainability" title="Permanent link">¶</a></h2>
|
|
<p>Majority of the cost of software is not initial development, but in on going maintenance:</p>
|
|
<ul>
|
|
<li>Fixing bugs</li>
|
|
<li>Keeping systems operational</li>
|
|
<li>Investigating failures</li>
|
|
<li>Adapting to new platforms</li>
|
|
<li>Modifying it for new use cases</li>
|
|
<li>Repaying technical debt</li>
|
|
</ul>
|
|
<p><strong>Operability</strong>: Make it easy for operations teams to keep the system running smoothly.</p>
|
|
<p><strong>Simplicity</strong>: Make it easy for new engineers to understand the system, by removing as much complexity as possible from the system.</p>
|
|
<p><strong>Evolvability</strong>: Make it easy for engineers to make changes to the system in the future, adapting it for unanticipated use cases are requirements change. (Also known as <em>extensibility</em>, <em>modifiability</em> or <em>plasticity</em>)</p>
|
|
<h3 id="operability-making-life-easy-for-operations">Operability: Making Life Easy for Operations<a class="headerlink" href="#operability-making-life-easy-for-operations" title="Permanent link">¶</a></h3>
|
|
<blockquote>
|
|
<p>"Good operations can work around the limitations of bad software, but good software cannot run reliably with bad operations"</p>
|
|
</blockquote>
|
|
<p>Operation teams are responsible for the following:</p>
|
|
<ul>
|
|
<li>Monitoring the health of the system and quickly restoring services.</li>
|
|
<li>Tracking down the cause of the problems.</li>
|
|
<li>Keeping software and platforms up to date, including security patches.</li>
|
|
<li>Keeping tabs on how different systems affect each other.</li>
|
|
<li>Anticipating future problems and applying fixes before they occur.</li>
|
|
<li>Establishing good practices are tools for deployment and configuration management.</li>
|
|
<li>Performing complex maintenance tasks such as moving an application from one platform to another.</li>
|
|
<li>Maintaining the security of the system.</li>
|
|
<li>Defining processes that make operations predictable and help keep the production environment stable.</li>
|
|
<li>Preserving the organisations knowledge about the system, even as individuals come and go.</li>
|
|
</ul>
|
|
<p>Good operability means making routine tasks easy - allowing the operations team to focus their efforts on high-value activities. Data systems can do various things to make routine tasks easy:</p>
|
|
<ul>
|
|
<li>Providing visibility into the runtime behaviour and internals of the system.</li>
|
|
<li>Providing good support for automation and integration with standard tools.</li>
|
|
<li>Avoiding dependency on individual machines.</li>
|
|
<li>Providing good documentation and easy to understand operational model.</li>
|
|
<li>Providing good default behaviour.</li>
|
|
<li>Self-healing where appropriate.</li>
|
|
<li>Exhibiting predictable behaviour, minimising surprises.</li>
|
|
</ul>
|
|
<h3 id="simplicity-managing-complexity">Simplicity: Managing Complexity<a class="headerlink" href="#simplicity-managing-complexity" title="Permanent link">¶</a></h3>
|
|
<p>In complex software, there is a greater risk of introducing bugs when making a change: when the system is harder for developers to understand and reason about, hidden assumptions, unintended consequences, and unexpected interactions are more easily overlooked.</p>
|
|
<p>Complexity can be <em>accidental</em>. This is defined if it is not inherent in the problem the software is trying to solve, but only arises from implementation. One of the best tools for removing accidental complexity is <em>abstraction</em>.</p>
|
|
<h3 id="evolvability-making-change-easy">Evolvability: Making Change Easy<a class="headerlink" href="#evolvability-making-change-easy" title="Permanent link">¶</a></h3>
|
|
<p>The ease with which you can modify a data system, and adapt it to changing requirements, is closely linked to its simplicity and its abstractions: simple and easy-to-understand systems are usually easier to modify than complex ones.</p>
|
|
<p><em>Evolvability</em> can be thought of the agility on a data system level.</p>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
</article>
|
|
</div>
|
|
|
|
|
|
<script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script>
|
|
</div>
|
|
|
|
<button type="button" class="md-top md-icon" data-md-component="top" hidden>
|
|
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8z"/></svg>
|
|
Back to top
|
|
</button>
|
|
|
|
</main>
|
|
|
|
<footer class="md-footer">
|
|
|
|
|
|
|
|
<nav class="md-footer__inner md-grid" aria-label="Footer" >
|
|
|
|
|
|
<a href="../../preface/" class="md-footer__link md-footer__link--prev" aria-label="Previous: Preface">
|
|
<div class="md-footer__button md-icon">
|
|
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"/></svg>
|
|
</div>
|
|
<div class="md-footer__title">
|
|
<span class="md-footer__direction">
|
|
Previous
|
|
</span>
|
|
<div class="md-ellipsis">
|
|
Preface
|
|
</div>
|
|
</div>
|
|
</a>
|
|
|
|
|
|
|
|
<a href="../chapter2/" class="md-footer__link md-footer__link--next" aria-label="Next: Chapter 2. Data Models and Query Languages">
|
|
<div class="md-footer__title">
|
|
<span class="md-footer__direction">
|
|
Next
|
|
</span>
|
|
<div class="md-ellipsis">
|
|
Chapter 2. Data Models and Query Languages
|
|
</div>
|
|
</div>
|
|
<div class="md-footer__button md-icon">
|
|
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M4 11v2h12l-5.5 5.5 1.42 1.42L19.84 12l-7.92-7.92L10.5 5.5 16 11z"/></svg>
|
|
</div>
|
|
</a>
|
|
|
|
</nav>
|
|
|
|
|
|
<div class="md-footer-meta md-typeset">
|
|
<div class="md-footer-meta__inner md-grid">
|
|
<div class="md-copyright">
|
|
|
|
|
|
Made with
|
|
<a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
|
|
Material for MkDocs
|
|
</a>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
</footer>
|
|
|
|
</div>
|
|
<div class="md-dialog" data-md-component="dialog">
|
|
<div class="md-dialog__inner md-typeset"></div>
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<script id="__config" type="application/json">{"annotate": null, "base": "../../../..", "features": ["navigation.instant", "navigation.tabs", "navigation.top", "navigation.footer", "toc.integrate", "content.code.copy", "content.code.annotate", "search.suggest", "search.highlight", "search.share", "content.action.edit", "content.action.view"], "search": "../../../../assets/javascripts/workers/search.2c215733.min.js", "tags": null, "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": null}</script>
|
|
|
|
|
|
<script src="../../../../assets/javascripts/bundle.79ae519e.min.js"></script>
|
|
|
|
<script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
|
|
|
|
|
|
</body>
|
|
</html> |