Experimental: specify avg recovery time instead of speed
parent
fe06536dd0
commit
6f01329374
|
@ -45,7 +45,7 @@ https://yourcmc.ru/git/vitalif/vitastor/
|
|||
AFR сервера эмпирически поделен на число дисков, чтобы "размазать" вероятность отказа сервера
|
||||
по его дискам.
|
||||
|
||||
Парадоксы дней рождений:
|
||||
## Парадокс дней рождений
|
||||
|
||||
- PG почти гарантированно пересекаются, особенно в небольших кластерах. Степень их пересечения
|
||||
очень полезно учитывать.
|
||||
|
|
17
afr.js
17
afr.js
|
@ -55,7 +55,8 @@ function failure_rate_fullmesh(n, a, f)
|
|||
// is that, with k=2, total failure rate doesn't depend on number of peers per OSD,
|
||||
// because it gets increased linearly by increased number of peers to fail
|
||||
// and decreased linearly by reduced rebalance time.
|
||||
function cluster_afr({ n_hosts, n_drives, afr_drive, afr_host, capacity, speed, ec, ec_data, ec_parity, replicas, pgs = 1, osd_rm, degraded_replacement, down_out_interval = 600 })
|
||||
function cluster_afr({ n_hosts, n_drives, afr_drive, afr_host, capacity, speed, disk_heal_hours, host_heal_hours,
|
||||
ec, ec_data, ec_parity, replicas, pgs = 1, osd_rm, degraded_replacement, down_out_interval = 0 })
|
||||
{
|
||||
const pg_size = (ec ? ec_data+ec_parity : replicas);
|
||||
// <peers> is a number of non-intersecting PGs that a single OSD/drive has on average
|
||||
|
@ -66,8 +67,18 @@ function cluster_afr({ n_hosts, n_drives, afr_drive, afr_host, capacity, speed,
|
|||
const resilver_peers = n_drives == 1 || osd_rm ? avg_distinct((n_hosts-1)*n_drives, pgs) : avg_distinct(n_drives-1, pgs);
|
||||
// <host_resilver_peers> other drives participate in resilvering of a failed host
|
||||
const host_resilver_peers = avg_distinct((n_hosts-1)*n_drives, n_drives*pgs);
|
||||
const disk_heal_time = (down_out_interval + capacity/(degraded_replacement ? 1 : resilver_peers)/speed)/86400/365;
|
||||
const host_heal_time = (down_out_interval + n_drives*capacity/host_resilver_peers/speed)/86400/365;
|
||||
let disk_heal_time, host_heal_time;
|
||||
if (speed)
|
||||
disk_heal_time = (down_out_interval + capacity/(degraded_replacement ? 1 : resilver_peers)/speed)/86400/365;
|
||||
else
|
||||
{
|
||||
disk_heal_time = disk_heal_hours/24/365;
|
||||
speed = capacity / (degraded_replacement ? 1 : resilver_peers) / (disk_heal_hours*3600 - down_out_interval);
|
||||
}
|
||||
if (host_heal_hours)
|
||||
host_heal_time = host_heal_hours/24/365;
|
||||
else
|
||||
host_heal_time = (down_out_interval + n_drives*capacity/host_resilver_peers/speed)/86400/365;
|
||||
const disk_heal_fail = ((afr_drive+afr_host/n_drives)*disk_heal_time);
|
||||
const host_heal_fail = ((afr_drive+afr_host/n_drives)*host_heal_time);
|
||||
const disk_pg_fail = ec
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"name": "fontello",
|
||||
"css_prefix_text": "icon-",
|
||||
"css_use_suffix": false,
|
||||
"hinting": true,
|
||||
"units_per_em": 1000,
|
||||
"ascent": 850,
|
||||
"glyphs": [
|
||||
{
|
||||
"uid": "0430f56230dd33f67f26be82b07a84fc",
|
||||
"css": "arw-down",
|
||||
"code": 59412,
|
||||
"src": "custom_icons",
|
||||
"selected": true,
|
||||
"svg": {
|
||||
"path": "M800 956C828.7 956 857.4 945.1 879.2 923.2L1567.2 235.2C1610.9 191.5 1610.9 120.5 1567.2 76.8 1523.4 33 1452.5 33 1408.7 76.8L800 685.5 191.3 76.8C147.5 33.1 76.6 33.1 32.8 76.8-10.9 120.6-10.9 191.5 32.8 235.3L720.8 923.2C742.7 945.1 771.3 956 800 956Z",
|
||||
"width": 1600
|
||||
},
|
||||
"search": [
|
||||
"arw-down"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
@font-face {
|
||||
font-family: 'fontello';
|
||||
src: url('../font/fontello.eot?162972');
|
||||
src: url('../font/fontello.eot?162972#iefix') format('embedded-opentype'),
|
||||
url('../font/fontello.woff2?162972') format('woff2'),
|
||||
url('../font/fontello.woff?162972') format('woff'),
|
||||
url('../font/fontello.ttf?162972') format('truetype'),
|
||||
url('../font/fontello.svg?162972#fontello') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
/* Chrome hack: SVG is rendered more smooth in Windozze. 100% magic, uncomment if you need it. */
|
||||
/* Note, that will break hinting! In other OS-es font will be not as sharp as it could be */
|
||||
/*
|
||||
@media screen and (-webkit-min-device-pixel-ratio:0) {
|
||||
@font-face {
|
||||
font-family: 'fontello';
|
||||
src: url('../font/fontello.svg?162972#fontello') format('svg');
|
||||
}
|
||||
}
|
||||
*/
|
||||
[class^="icon-"]:before, [class*=" icon-"]:before {
|
||||
font-family: "fontello";
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
speak: never;
|
||||
|
||||
display: inline-block;
|
||||
text-decoration: inherit;
|
||||
width: 1em;
|
||||
margin-right: .2em;
|
||||
text-align: center;
|
||||
/* opacity: .8; */
|
||||
|
||||
/* For safety - reset parent styles, that can break glyph codes*/
|
||||
font-variant: normal;
|
||||
text-transform: none;
|
||||
|
||||
/* fix buttons height, for twitter bootstrap */
|
||||
line-height: 1em;
|
||||
|
||||
/* Animation center compensation - margins should be symmetric */
|
||||
/* remove if not needed */
|
||||
margin-left: .2em;
|
||||
|
||||
/* you can be more comfortable with increased icons size */
|
||||
/* font-size: 120%; */
|
||||
|
||||
/* Font smoothing. That was taken from TWBS */
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
|
||||
/* Uncomment for 3D effect */
|
||||
/* text-shadow: 1px 1px 1px rgba(127, 127, 127, 0.3); */
|
||||
}
|
||||
|
||||
.icon-arw-down:before { content: '\e814'; } /* '' */
|
Binary file not shown.
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg xmlns="http://www.w3.org/2000/svg">
|
||||
<metadata>Copyright (C) 2021 by original authors @ fontello.com</metadata>
|
||||
<defs>
|
||||
<font id="fontello" horiz-adv-x="1000" >
|
||||
<font-face font-family="fontello" font-weight="400" font-stretch="normal" units-per-em="1000" ascent="850" descent="-150" />
|
||||
<missing-glyph horiz-adv-x="1000" />
|
||||
<glyph glyph-name="arw-down" unicode="" d="M800-106c29 0 57 11 79 33l688 688c44 44 44 115 0 158-44 44-114 44-158 0l-609-608-609 608c-43 44-114 44-158 0-44-44-44-114 0-158l688-688c22-22 50-33 79-33z" horiz-adv-x="1600" />
|
||||
</font>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 715 B |
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -4,6 +4,7 @@
|
|||
<title>Калькулятор вероятности отказа кластера Ceph/Vitastor</title>
|
||||
<meta name="viewport" content="width=790px, initial-scale=1">
|
||||
<meta charset="utf-8" />
|
||||
<link rel="stylesheet" href="fontello/css/fontello.css" />
|
||||
<style>
|
||||
* { box-sizing: border-box; }
|
||||
body { margin: 0; font-size: 15px; font-family: Arial, Helvetica, sans-serif; }
|
||||
|
@ -18,6 +19,14 @@ input[type="text"] { border: 1px solid #aaa; padding: 4px; border-radius: 3px; }
|
|||
.switch.r { border-left-width: 0; border-radius: 0 20px 20px 0; padding-right: 15px; }
|
||||
.switch.sel { border-color: #08f; background: #08f; color: white; }
|
||||
.switch:hover { border-color: #4af; background: #4af; color: white; }
|
||||
.icombo { display: inline-block; position: relative; border: 1px solid #aaa; border-radius: 3px; padding: 2px 8px 2px 5px; cursor: pointer; transition: 0.2s ease-out; }
|
||||
.icombo .icon-arw-down { font-size: 7px; display: inline-block; vertical-align: middle; color: #aaa; transition: 0.2s ease-out; }
|
||||
.icombo:hover { border-color: #4af; background: #4af; color: white; }
|
||||
.icombo:hover .icon-arw-down { color: white; }
|
||||
.icombo .options { opacity: 0; position: absolute; top: 100%; left: -1px; width: 150px; background: white; color: black; border-radius: 3px; overflow: hidden; cursor: pointer; transition: 0.2s ease-out; box-shadow: 0 0 10px 3px rgba(0, 0, 0, 0.2); }
|
||||
.icombo:hover .options { opacity: 1; }
|
||||
.icombo .option { display: block; padding: 4px 6px; }
|
||||
.icombo .option:hover { background: #4af; color: white; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
|
37
main.js
37
main.js
|
@ -11,7 +11,7 @@ class Calc extends preact.Component
|
|||
afr_host: 5,
|
||||
capacity: 8,
|
||||
speed: 20,
|
||||
pg_per_osd: 50,
|
||||
pg_per_osd: 100,
|
||||
ec: false,
|
||||
replicas: 2,
|
||||
ec_data: 2,
|
||||
|
@ -19,6 +19,7 @@ class Calc extends preact.Component
|
|||
eager: false,
|
||||
same_host: true,
|
||||
result: 0,
|
||||
use_speed: true,
|
||||
}
|
||||
|
||||
calc(st)
|
||||
|
@ -30,7 +31,8 @@ class Calc extends preact.Component
|
|||
afr_drive: st.afr_drive/100,
|
||||
afr_host: st.afr_host/100,
|
||||
capacity: st.capacity*1000,
|
||||
speed: st.speed/1000,
|
||||
speed: st.use_speed ? st.speed/1000 : null,
|
||||
disk_heal_hours: st.use_speed ? null : st.disk_heal_hours,
|
||||
ec: st.ec,
|
||||
ec_data: st.ec_data,
|
||||
ec_parity: st.ec_parity,
|
||||
|
@ -38,6 +40,7 @@ class Calc extends preact.Component
|
|||
pgs: st.pg_per_osd,
|
||||
osd_rm: !st.same_host,
|
||||
degraded_replacement: st.eager,
|
||||
down_out_interval: 600,
|
||||
});
|
||||
this.setState(st);
|
||||
}
|
||||
|
@ -69,6 +72,16 @@ class Calc extends preact.Component
|
|||
this.calc({ eager: event.target.checked });
|
||||
}
|
||||
|
||||
useSpeed = () =>
|
||||
{
|
||||
this.calc({ use_speed: true, speed: this.state.speed || 20 });
|
||||
}
|
||||
|
||||
useTime = () =>
|
||||
{
|
||||
this.calc({ use_speed: false, disk_heal_hours: 12 });
|
||||
}
|
||||
|
||||
setSameHost = (event) =>
|
||||
{
|
||||
this.calc({ same_host: event.target.checked });
|
||||
|
@ -110,7 +123,7 @@ class Calc extends preact.Component
|
|||
Калькулятор вероятности отказа кластера Ceph/Vitastor
|
||||
</h2>
|
||||
<p>
|
||||
Вероятность полного отказа кластера зависит от числа серверов и дисков
|
||||
Вероятность потери данных в кластере зависит от числа серверов и дисков
|
||||
(чем их больше, тем вероятность больше), от схемы избыточности, скорости ребаланса (восстановления),
|
||||
и, конечно, непосредственно вероятности выхода из строя самих дисков и серверов.
|
||||
</p>
|
||||
|
@ -154,11 +167,23 @@ class Calc extends preact.Component
|
|||
<td><input type="text" value={state.ec_parity} onchange={this.setter('ec_parity')} /></td>
|
||||
</tr> : null}
|
||||
<tr>
|
||||
<th>Оценочная скорость<br />восстановления на 1 OSD</th>
|
||||
<td><input type="text" value={state.speed} onchange={this.setter('speed')} /> МБ/с</td>
|
||||
<th>
|
||||
{state.use_speed ? 'Оценочная' : 'Оценочное'}
|
||||
<span className="icombo">
|
||||
{state.use_speed ? 'скорость' : 'время'} <span className="icon-arw-down"></span>
|
||||
<span className="options">
|
||||
<span className="option" onClick={this.useSpeed}>скорость</span>
|
||||
<span className="option" onClick={this.useTime}>время</span>
|
||||
</span>
|
||||
</span>
|
||||
<br />восстановления на 1 OSD
|
||||
</th>
|
||||
{state.use_speed
|
||||
? <td><input type="text" value={state.speed} onchange={this.setter('speed')} /> МБ/с</td>
|
||||
: <td><input type="text" value={state.disk_heal_hours} onchange={this.setter('disk_heal_hours')} /> час(ов)</td>}
|
||||
</tr>
|
||||
<tr>
|
||||
<th><abbr title="Среднее число уникальных групп чётности (пар/троек и т.п.), включающих каждый отдельный диск. В Ceph нормой считается 100 PG на OSD, из которых, допустим, половина дублируется">PG на OSD</abbr></th>
|
||||
<th><abbr title="Среднее число уникальных групп чётности (пар/троек и т.п.), включающих каждый отдельный диск. В Ceph нормой считается 100 PG на OSD">PG на OSD</abbr></th>
|
||||
<td><input type="text" value={state.pg_per_osd} onchange={this.setter('pg_per_osd')} /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
|
Loading…
Reference in New Issue