17-bo‘lim
Zaxira nusxa va falokatdan tiklanish
3-2-1 qoidasi, RPO va RTO, o'zgartirilmaydigan zaxira, tiklash mashqlari va biznes uzluksizligi.
Ushbu bo‘lim mundarijasi
Zaxira nusxa - oxirgi himoya chizig'i. Boshqa hamma narsa buzilganda u ishlashi kerak.
Nima uchun zaxira? #
-- Rejalashtirilgan
DELETE FROM buyurtmalar WHERE holat = 'bekor' AND yaratilgan < '2024-01-01';
-- Amalda bajarilgan (WHERE ni tanlab olishni unutgan)
DELETE FROM buyurtmalar;
Bir soniyada barcha buyurtmalar yo'qoladi.
Himoya:
- Ishlab chiqarishda tranzaksiya ichida ishlang
- Avval
SELECT COUNT(*)bilan tekshiring --i-am-a-dummyrejimini yoqing (WHERE siz DELETE ni taqiqlaydi)- Va albatta - zaxira nusxa
mysql --safe-updates -u root dokon
RPO va RTO #
| Tizim | RPO | RTO | Strategiya |
|---|---|---|---|
| To'lov tizimi | 0 | 5 daqiqa | Sinxron replikatsiya, avtomatik almashish |
| Onlayn do'kon | 15 daqiqa | 1 soat | Asinxron replikatsiya + zaxira |
| Ichki CRM | 4 soat | 8 soat | Kunlik zaxira + jurnal |
| Arxiv tizimi | 24 soat | 3 kun | Kunlik zaxira |
| Hujjatlar | 24 soat | 1 hafta | Haftalik zaxira |
Texnik jamoa emas, biznes aytishi kerak:
- "Bir soatlik ma'lumot yo'qolsa nima bo'ladi?"
- "Bir kun ishlamasak, qancha zarar?"
Keyin texnik jamoa shu talabga mos yechim quradi.
RPO = 0 va RTO = 0 - imkonsiz va juda qimmat. Muvozanat kerak.
# Biznes ta'sirini tahlil qilish
| Jarayon | 1 soat | 4 soat | 1 kun | 1 hafta |
|---------|--------|--------|-------|---------|
| Onlayn savdo | 5 mln | 20 mln | 120 mln | 800 mln |
| Ombor boshqaruvi | 0 | 2 mln | 15 mln | 100 mln |
| Buxgalteriya | 0 | 0 | 5 mln | 40 mln |
| Marketing | 0 | 0 | 0 | 10 mln |
Bu jadval ustuvorlikni belgilaydi: onlayn savdo birinchi tiklanadi.
3-2-1 qoidasi #
Ransomware tarmoqqa ulangan barcha zaxiralarni topib o'chiradi.
Oflayn nusxa:
- Tarmoqdan jismonan uzilgan (disk seyfda)
- Yoki o'zgartirilmaydigan saqlash (Object Lock)
- Yoki bir tomonlama uzatish (faqat yozish mumkin)
Bu oxirgi umid - qolgan hamma narsa buzilganda.
Zaxira turlari #
| Tur | Nima saqlaydi | Hajm | Tiklash |
|---|---|---|---|
| To'liq | Hamma narsa | Katta | Tez, oddiy |
| Inkremental | Oxirgi zaxiradan keyingi o'zgarishlar | Kichik | Sekin, zanjir kerak |
| Differensial | Oxirgi to'liq zaxiradan keyingi | O'rtacha | O'rtacha |
| Snapshot | Vaqt kesimidagi holat | Kichik | Juda tez |
# Odatiy jadval
# Yakshanba: to'liq zaxira
# Dushanba-Shanba: inkremental
0 2 * * 0 /usr/local/bin/zaxira.sh --toliq
0 2 * * 1-6 /usr/local/bin/zaxira.sh --inkremental
Inkremental zaxirada tiklash uchun butun zanjir kerak:
To'liq (yak) → Ink (dush) → Ink (sesh) → Ink (chor) → tiklash
Agar seshanbadagi fayl buzilgan bo'lsa - chorshanbani tiklab bo'lmaydi.
Differensial zaxirada faqat ikki fayl kerak: to'liq + oxirgi differensial. Bu ishonchliroq.
Ma'lumotlar bazasi zaxirasi #
#!/bin/bash
# db-zaxira.sh
set -euo pipefail
SANA=$(date +%F_%H%M)
ZAXIRA=/zaxira/db
[email protected]
mkdir -p "$ZAXIRA"
echo "==> Mantiqiy zaxira (mysqldump)"
mysqldump \
--single-transaction \
--routines --triggers --events \
--default-character-set=utf8mb4 \
--set-gtid-purged=OFF \
dokon | gzip -9 > "$ZAXIRA/dokon_${SANA}.sql.gz"
echo "==> Shifrlash"
gpg --encrypt --recipient "$KALIT_ID" --trust-model always \
"$ZAXIRA/dokon_${SANA}.sql.gz"
rm "$ZAXIRA/dokon_${SANA}.sql.gz"
echo "==> Tekshirish"
gpg --decrypt "$ZAXIRA/dokon_${SANA}.sql.gz.gpg" 2>/dev/null \
| gunzip -t
echo "Arxiv butun"
echo "==> Xesh"
sha256sum "$ZAXIRA/dokon_${SANA}.sql.gz.gpg" \
> "$ZAXIRA/dokon_${SANA}.sql.gz.gpg.sha256"
echo "==> Bulutga yuborish"
aws s3 cp "$ZAXIRA/dokon_${SANA}.sql.gz.gpg" \
"s3://dokon-zaxira/db/" \
--storage-class STANDARD_IA
echo "==> Eskilarini tozalash (30 kundan eski)"
find "$ZAXIRA" -name "*.gpg" -mtime +30 -delete
find "$ZAXIRA" -name "*.sha256" -mtime +30 -delete
echo "==> Tayyor: dokon_${SANA}.sql.gz.gpg"
--single-transaction majburiyUsiz mysqldump jadvallarni bloklaydi va sayt zaxira olinayotgan
paytda ishlamaydi.
Bu bayroq InnoDB uchun izchil suratni oladi va sayt ishlashda davom etadi.
# Nuqta-vaqtga tiklash uchun binlog
# my.cnf
[mysqld]
log_bin = /var/log/mysql/mysql-bin
binlog_format = ROW
expire_logs_days = 14
# Kechagi to'liq zaxira + bugungi binlog = istalgan vaqtga tiklash
mysql dokon < dokon_2026-09-15.sql
mysqlbinlog \
--start-datetime="2026-09-15 02:00:00" \
--stop-datetime="2026-09-16 14:22:00" \
/var/log/mysql/mysql-bin.* | mysql dokon
Bu imkoniyat inson xatosidan himoya qiladi.
DELETE FROM buyurtmalar; 14:22 da bajarilgan bo'lsa, siz
14:21:59 holatiga tiklanasiz - faqat bir soniyalik ma'lumot
yo'qoladi.
Binlog yoqilmagan bo'lsa - oxirgi zaxiragacha (bir necha soat) qaytasiz.
Fayllar zaxirasi #
# Restic - zamonaviy, shifrlangan, dedublikatsiyali
export RESTIC_REPOSITORY="s3:s3.amazonaws.com/dokon-zaxira"
export RESTIC_PASSWORD_FILE="/root/.restic-parol"
# Birinchi marta
restic init
# Zaxira
restic backup /var/www/dokon/storage \
--exclude-file=/etc/restic/istisnolar.txt \
--tag kunlik
# Ro'yxat
restic snapshots
# Tiklash
restic restore latest --target /tiklash
# Faqat bitta fayl
restic restore latest --target /tiklash --include /var/www/dokon/storage/muhim.pdf
# Eskilarini tozalash
restic forget \
--keep-daily 7 \
--keep-weekly 4 \
--keep-monthly 12 \
--keep-yearly 3 \
--prune
# Yaxlitlikni tekshirish
restic check --read-data-subset=10%
# /etc/restic/istisnolar.txt
*.log
*.tmp
node_modules/
vendor/
.git/
cache/
- Shifrlash standart holatda
- Dedublikatsiya - takrorlanuvchi bloklar bir marta saqlanadi
- Inkremental - faqat o'zgarishlar
- Ko'p backend: S3, B2, SFTP, mahalliy
- Yaxlitlik tekshiruvi o'rnatilgan
O'zgartirilmaydigan zaxira #
# S3 Object Lock - o'chirib bo'lmaydigan saqlash
aws s3api create-bucket \
--bucket dokon-zaxira-immutable \
--object-lock-enabled-for-bucket
aws s3api put-object-lock-configuration \
--bucket dokon-zaxira-immutable \
--object-lock-configuration '{
"ObjectLockEnabled": "Enabled",
"Rule": {
"DefaultRetention": {
"Mode": "COMPLIANCE",
"Days": 30
}
}
}'
| Rejim | Kim o'chira oladi |
|---|---|
| GOVERNANCE | Maxsus huquqli foydalanuvchi |
| COMPLIANCE | Hech kim, hatto root ham |
Ransomware ga qarshi COMPLIANCE kerak: hujumchi administrator huquqini olsa ham, zaxirani o'chira olmaydi.
Lekin ehtiyot bo'ling: xato bilan yozilgan ma'lumotni ham o'chirib bo'lmaydi va u muddat tugaguncha joy egallaydi.
# Zaxira uchun alohida hisob va cheklangan huquq
# IAM siyosati: faqat yozish, o'chirish yo'q
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetBucketLocation"
],
"Resource": [
"arn:aws:s3:::dokon-zaxira/*",
"arn:aws:s3:::dokon-zaxira"
]
}
]
}
Server buzilsa, hujumchi zaxira kalitini topadi.
Agar shu kalitda faqat yozish huquqi bo'lsa - u zaxirani o'chira olmaydi.
Eski nusxalarni tozalash alohida hisob orqali, boshqa serverdan bajarilsin.
Tiklashni sinash #
#!/bin/bash
# tiklash-sinovi.sh - har oy avtomatik ishga tushadi
set -euo pipefail
SINOV_BAZA="dokon_tiklash_sinovi"
HISOBOT="/var/log/tiklash-sinovi-$(date +%F).log"
{
echo "=== Tiklash sinovi: $(date -Iseconds) ==="
BOSHLANDI=$(date +%s)
echo "1. Oxirgi zaxirani yuklab olish"
OXIRGI=$(aws s3 ls s3://dokon-zaxira/db/ | sort | tail -1 | awk '{print $4}')
aws s3 cp "s3://dokon-zaxira/db/$OXIRGI" /tmp/
echo "2. Xeshni tekshirish"
aws s3 cp "s3://dokon-zaxira/db/${OXIRGI}.sha256" /tmp/
(cd /tmp && sha256sum -c "${OXIRGI}.sha256")
echo "3. Shifrni ochish"
gpg --decrypt "/tmp/$OXIRGI" > /tmp/tiklash.sql.gz
echo "4. Bazaga tiklash"
mysql -e "DROP DATABASE IF EXISTS $SINOV_BAZA; CREATE DATABASE $SINOV_BAZA;"
gunzip -c /tmp/tiklash.sql.gz | mysql "$SINOV_BAZA"
TUGADI=$(date +%s)
VAQT=$((TUGADI - BOSHLANDI))
echo "5. Ma'lumotni tekshirish"
for jadval in mijozlar buyurtmalar mahsulotlar; do
SONI=$(mysql -N -e "SELECT COUNT(*) FROM $SINOV_BAZA.$jadval;")
echo " $jadval: $SONI qator"
if [ "$SONI" -eq 0 ]; then
echo " XATO: $jadval bo'sh!"
exit 1
fi
done
echo "6. Oxirgi yozuv sanasi"
mysql -N -e "SELECT MAX(yaratilgan) FROM $SINOV_BAZA.buyurtmalar;"
echo "7. Tozalash"
mysql -e "DROP DATABASE $SINOV_BAZA;"
rm -f /tmp/tiklash.sql.gz "/tmp/$OXIRGI"*
echo "=== MUVAFFAQIYATLI. Tiklash vaqti: ${VAQT} soniya ==="
} 2>&1 | tee "$HISOBOT"
# Natijani yuborish
mail -s "Tiklash sinovi: $(date +%F)" [email protected] < "$HISOBOT"
Keng tarqalgan holatlar:
- Zaxira skripti xato bilan tugaydi, lekin hech kim ko'rmaydi
- Arxiv buzilgan
- Shifrlash kaliti yo'qolgan
- Zaxirada faqat bo'sh jadvallar bor
- Tiklash 3 kun oladi (RTO 4 soat edi)
Ko'p tashkilotlar buni faqat falokat kunida biladi.
Har oyda avtomatik sinov o'tkazing.
Replikatsiya #
# MySQL replikatsiya (asosiy server)
[mysqld]
server-id = 1
log_bin = /var/log/mysql/mysql-bin
binlog_format = ROW
gtid_mode = ON
enforce_gtid_consistency = ON
-- Nusxa serverda
CHANGE REPLICATION SOURCE TO
SOURCE_HOST = '10.0.2.10',
SOURCE_USER = 'replikator',
SOURCE_PASSWORD = '...',
SOURCE_AUTO_POSITION = 1;
START REPLICA;
SHOW REPLICA STATUS\G
-- Kechikishni kuzatish
SELECT
SERVICE_STATE,
LAST_ERROR_MESSAGE,
APPLYING_TRANSACTION
FROM performance_schema.replication_applier_status_by_worker;
Bitta nusxani ataylab kechiktiring:
CHANGE REPLICATION SOURCE TO SOURCE_DELAY = 3600; -- 1 soat
Agar kimdir DELETE FROM bajarsa, sizda bir soat vaqt bor:
kechiktirilgan nusxada ma'lumot hali joyida.
Bu inson xatosidan himoyaning arzon va samarali usuli.
Falokatdan tiklanish rejasi #
# Falokatdan tiklanish rejasi
## 1. Ssenariylar
| Ssenariy | Ehtimol | Ta'sir | RTO |
|----------|---------|--------|-----|
| Bitta server qulashi | Yuqori | Past | 15 daq |
| Ma'lumotlar bazasi buzilishi | O'rta | Yuqori | 2 soat |
| Serverxona ishdan chiqishi | Past | Kritik | 8 soat |
| Ransomware | O'rta | Kritik | 24 soat |
| Provayder to'liq ishlamasligi | Past | Kritik | 12 soat |
## 2. Tiklash ustuvorligi
1. Ma'lumotlar bazasi
2. API xizmati
3. Veb sayt
4. Admin panel
5. Hisobot tizimi
6. Ichki vositalar
## 3. Kontaktlar
| Rol | Kim | Telefon | Zaxira |
|-----|-----|---------|--------|
| Tiklash rahbari | @husanboy | +998 90 xxx | @aziz |
| Baza | @aziz | +998 91 xxx | Tashqi maslahatchi |
| Tarmoq | @jasur | +998 93 xxx | Provayder |
| Bulut provayder | AWS Support | Case #xxx | — |
## 4. Tiklash qadamlari (baza buzilishi)
1. Muammoni tasdiqlash (5 daq)
2. Xizmatni texnik ish rejimiga o'tkazish (2 daq)
3. Oxirgi zaxirani aniqlash (5 daq)
4. Yangi server tayyorlash (20 daq)
5. Zaxirani tiklash (45 daq)
6. Binlog bilan nuqta-vaqtga tiklash (15 daq)
7. Ma'lumotni tekshirish (15 daq)
8. Ilovani ulash (5 daq)
9. Bosqichma-bosqich ishga tushirish (10 daq)
**Jami: ~2 soat**
## 5. Aloqa
- Status sahifasi: status.dokon.uz
- Mijozlarga: 30 daqiqada bir marta yangilanish
- Ichki: Slack #falokat kanali
# Status sahifasi (alohida infratuzilmada!)
# Asosiy sayt ishlamaganda ham u ishlashi kerak
Agar status sahifasi shu serverda bo'lsa, server qulaganda u ham ishlamaydi.
Yechim: alohida provayder yoki statik sahifa (GitHub Pages, Netlify, S3).
Bulut zaxirasi #
# EBS snapshot (AWS)
aws ec2 create-snapshot \
--volume-id vol-0123456789abcdef0 \
--description "Kunlik zaxira $(date +%F)" \
--tag-specifications 'ResourceType=snapshot,Tags=[{Key=Nomi,Value=dokon-kunlik}]'
# Avtomatik siyosat
aws dlm create-lifecycle-policy \
--execution-role-arn arn:aws:iam::123456789012:role/AWSDataLifecycleManagerDefaultRole \
--description "Kunlik snapshot" \
--state ENABLED \
--policy-details file://siyosat.json
{
"ResourceTypes": ["VOLUME"],
"TargetTags": [{"Key": "Zaxira", "Value": "kunlik"}],
"Schedules": [{
"Name": "Kunlik",
"CreateRule": {"Interval": 24, "IntervalUnit": "HOURS", "Times": ["02:00"]},
"RetainRule": {"Count": 7},
"CopyTags": true
}]
}
Keng tarqalgan yanglishuv: "bizda bulutda, demak zaxira bor".
Bulut provayderlari infratuzilma mavjudligini kafolatlaydi, lekin sizning ma'lumotingizni zaxiralamaydi.
Agar siz jadvalni o'chirib yuborsangiz - bu sizning muammoyingiz.
Shartnomani o'qing: umumiy mas'uliyat modelida nima sizning zimmangizda ekanini bilib oling.
Zaxira monitoringi #
final class ZaxiraNazorati
{
private const MAKS_YOSH_SOAT = 26; // kunlik zaxira + zaxira vaqt
private const MIN_HAJM_MB = 100;
public function tekshiring(): array
{
$muammolar = [];
$oxirgi = $this->zaxiralar->oxirgisi();
if ($oxirgi === null) {
return ['Zaxira umuman topilmadi'];
}
$yosh = (time() - $oxirgi->vaqt) / 3600;
if ($yosh > self::MAKS_YOSH_SOAT) {
$muammolar[] = sprintf('Oxirgi zaxira %.1f soat oldin', $yosh);
}
if ($oxirgi->hajmMb < self::MIN_HAJM_MB) {
$muammolar[] = sprintf('Zaxira hajmi juda kichik: %d MB', $oxirgi->hajmMb);
}
// Hajm keskin o'zgardimi?
$oldingi = $this->zaxiralar->oldingisi();
if ($oldingi !== null) {
$farq = abs($oxirgi->hajmMb - $oldingi->hajmMb) / $oldingi->hajmMb;
if ($farq > 0.3) {
$muammolar[] = sprintf('Hajm %.0f%% ga o\'zgardi', $farq * 100);
}
}
// Oxirgi tiklash sinovi
$sinov = $this->sinovlar->oxirgisi();
if ($sinov === null || (time() - $sinov->vaqt) > 35 * 86400) {
$muammolar[] = 'Tiklash sinovi 35 kundan beri o\'tkazilmagan';
}
return $muammolar;
}
}
Zaxira hajmi to'satdan kamaysa:
- Ma'lumot o'chirilgan bo'lishi mumkin
- Zaxira skripti xato ishlagan
To'satdan oshsa:
- Ma'lumot dublikatlanmoqda
- Kutilmagan fayllar qo'shilmoqda
Ikkala holat ham tekshirishni talab qiladi.
Zaxira ro'yxati #
| Talab | Bajarildi |
|---|---|
| 3-2-1-1-0 qoidasiga rioya qilinadi | |
| RPO va RTO belgilangan va biznes bilan kelishilgan | |
| Zaxira avtomatik va rejalashtirilgan | |
| Zaxira shifrlangan | |
| Shifrlash kaliti alohida saqlanadi | |
| Oflayn yoki o'zgartirilmaydigan nusxa mavjud | |
| Zaxira hisobida o'chirish huquqi yo'q | |
| Nuqta-vaqtga tiklash mumkin (binlog) | |
| Kechiktirilgan nusxa mavjud | |
| Tiklash oyiga bir marta sinovdan o'tadi | |
| Tiklash vaqti o'lchangan va RTO ga mos | |
| Zaxira monitoringi va ogohlantirish | |
| Falokatdan tiklanish rejasi yozilgan | |
| Status sahifasi alohida infratuzilmada |
- Loyihangiz uchun RPO va RTO ni belgilang.
- Biznes ta'siri tahlilini tuzing.
- Zaxira skriptini yozing (shifrlash bilan).
- Zaxirani bulutga yuboring.
- Zaxira hisobiga faqat yozish huquqini bering.
- Tiklash sinovi skriptini yozing.
- Uni ishga tushiring va tiklash vaqtini o'lchang.
- Binlog ni yoqing va nuqta-vaqtga tiklashni sinang.
- Kechiktirilgan nusxa sozlang (yoki uni rejalashtiring).
- Falokatdan tiklanish rejasini yozing.
Xulosa #
- Ma'lumot yo'qotishning eng ko'p sababi - inson xatosi.
- RPO - qancha ma'lumot yo'qoladi; RTO - qancha vaqt ishlamaydi.
- Ularni biznes belgilaydi, texnik jamoa emas.
- 3-2-1-1-0: 3 nusxa, 2 turdagi, 1 tashqarida, 1 oflayn, 0 xato.
- Oflayn nusxa - ransomware ga qarshi oxirgi umid.
- Zaxira shifrlangan bo'lsin, kalit alohida saqlansin.
- Zaxira hisobida o'chirish huquqi bo'lmasin.
- Binlog nuqta-vaqtga tiklash imkonini beradi.
- Kechiktirilgan nusxa - inson xatosidan arzon himoya.
- Replikatsiya zaxirani almashtirmaydi - xato ham nusxalanadi.
- Sinovdan o'tmagan zaxira - zaxira emas; oyiga bir marta sinang.
- Bulut provayderi sizning ma'lumotingizni zaxiralamaydi.
Keyingi bo'limda xavfsiz dasturlash amaliyotini ko'ramiz.
O‘qish tarixini saqlamoqchimisiz?
Tizimga kirsangiz, tugatgan bo‘limlaringiz saqlanadi va qoldirgan joyingizdan davom etasiz.
Xatolik topdingizmi?
Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.