Experimental: specify avg recovery time instead of speed

master
Vitaliy Filippov 2021-12-07 22:56:46 +03:00
parent fe06536dd0
commit 6f01329374
11 changed files with 148 additions and 10 deletions

View File

@ -45,7 +45,7 @@ https://yourcmc.ru/git/vitalif/vitastor/
AFR сервера эмпирически поделен на число дисков, чтобы "размазать" вероятность отказа сервера
по его дискам.
Парадоксы дней рождений:
## Парадокс дней рождений
- PG почти гарантированно пересекаются, особенно в небольших кластерах. Степень их пересечения
очень полезно учитывать.

17
afr.js
View File

@ -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

24
fontello/config.json Normal file
View File

@ -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"
]
}
]
}

57
fontello/css/fontello.css vendored Normal file
View File

@ -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'; } /* '' */

BIN
fontello/font/fontello.eot Normal file

Binary file not shown.

View File

@ -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="&#xe814;" 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

BIN
fontello/font/fontello.ttf Normal file

Binary file not shown.

BIN
fontello/font/fontello.woff Normal file

Binary file not shown.

Binary file not shown.

View File

@ -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
View File

@ -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 ? 'Оценочная' : 'Оценочное'}&nbsp;
<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>