18-bo‘lim
O'zgarishlar oqimi va gorizontal kengayish
watch bilan o'zgarishlarni kuzatish, hodisa turlari, resume token, fullDocument va bo'laklash (sharding) tushunchasi.
Ushbu bo‘lim mundarijasi
Ma'lumot o'zgarganda dasturga xabar berish kerak bo'ladi: keshni yangilash, xabar yuborish, qidiruv indeksini sinxronlash. Buni so'rab turish (polling) bilan emas, o'zgarishlar oqimi bilan qilish to'g'ri.
db.buyurtma.insertMany([
{ _id: 1, mijoz: "Husanboy", holat: "yangi", summa: 250000 },
{ _id: 2, mijoz: "Malika", holat: "yangi", summa: 180000 }
])
watch - oqimni ochish #
const oqim = db.buyurtma.watch()
oqim.disableBlockWarnings()
db.buyurtma.insertOne({ _id: 3, mijoz: "Nodira", summa: 95000 })
const h = oqim.next()
h.operationType
h.documentKey
h.fullDocument
oqim.close()
ChangeStreamCursor on buyurtma
{ acknowledged: true, insertedId: 3 }
insert
{ _id: 3 }
{ _id: 3, mijoz: 'Nodira', summa: 95000 }
Oqim ochilgandan keyin sodir bo'lgan har bir o'zgarishni beradi.
Hodisa turlari #
const oqim = db.buyurtma.watch()
oqim.disableBlockWarnings()
db.buyurtma.updateOne({ _id: 1 }, { $set: { holat: "yolda" } })
db.buyurtma.deleteOne({ _id: 2 })
const y = oqim.next()
y.operationType
y.updateDescription.updatedFields
const o = oqim.next()
o.operationType
o.documentKey
oqim.close()
ChangeStreamCursor on buyurtma
{
acknowledged: true,
insertedId: null,
matchedCount: 1,
modifiedCount: 1,
upsertedCount: 0
}
{ acknowledged: true, deletedCount: 1 }
update
{ holat: 'yolda' }
delete
{ _id: 2 }
operationType | Qachon |
|---|---|
insert | Yangi hujjat |
update | $set, $inc va shunga o'xshash |
replace | replaceOne |
delete | O'chirildi |
drop | To'plam tashlandi |
invalidate | Oqim yaroqsiz bo'lib qoldi |
update hodisasi to'liq hujjatni bermaydiOdatiy holda update hodisasida faqat o'zgargan
maydonlar keladi - updateDescription.updatedFields.
Bu ataylab: butun hujjatni har o'zgarishda yuborish katta hujjatlarda qimmat bo'lardi.
To'liq hujjat kerak bo'lsa, uni ochiq so'rang:
db.buyurtma.watch([], { fullDocument: "updateLookup" })
Lekin bitta muhim tafsilot bor: updateLookup hujjatni
hozirgi holatida o'qiydi, o'zgarish paytidagi holatida
emas. Agar o'sha oraliqda yana bir yangilash bo'lsa, siz
eng oxirgi holatni olasiz.
MongoDB 6.0 dan boshlab fullDocumentBeforeChange ham bor -
u o'zgarishdan oldingi holatni beradi. Buning uchun
to'plamda changeStreamPreAndPostImages yoqilgan bo'lishi
kerak.
const oqim = db.buyurtma.watch([], { fullDocument: "updateLookup" })
oqim.disableBlockWarnings()
db.buyurtma.updateOne({ _id: 1 }, { $set: { holat: "yakunlandi" } })
const h = oqim.next()
h.operationType
h.fullDocument
oqim.close()
ChangeStreamCursor on buyurtma
{
acknowledged: true,
insertedId: null,
matchedCount: 1,
modifiedCount: 1,
upsertedCount: 0
}
update
{ _id: 1, mijoz: 'Husanboy', holat: 'yakunlandi', summa: 250000 }
Oqimni filtrlash #
watch agregatsiya quvurini qabul qiladi:
const oqim = db.buyurtma.watch([
{ $match: {
operationType: "insert",
"fullDocument.summa": { $gte: 200000 }
} }
])
oqim.disableBlockWarnings()
db.buyurtma.insertOne({ _id: 4, mijoz: "Aziza", summa: 50000 })
db.buyurtma.insertOne({ _id: 5, mijoz: "Kamola", summa: 400000 })
const h = oqim.next()
h.fullDocument.mijoz
h.fullDocument.summa
oqim.close()
ChangeStreamCursor on buyurtma
{ acknowledged: true, insertedId: 4 }
{ acknowledged: true, insertedId: 5 }
Kamola
400000
Birinchi hujjat filtrga tushmadi - oqim uni umuman bermadi. Filtrlash serverda bajariladi, shuning uchun keraksiz ma'lumot tarmoqqa chiqmaydi.
Resume token - uzilishdan keyin davom etish #
Har bir hodisada _id bor - bu davom etish belgisi:
const oqim = db.buyurtma.watch()
oqim.disableBlockWarnings()
db.buyurtma.insertOne({ _id: 6, mijoz: "Dilnoza", summa: 77000 })
const h = oqim.next()
typeof h._id._data
h._id._data.length > 0
oqim.close()
ChangeStreamCursor on buyurtma
{ acknowledged: true, insertedId: 6 }
string
true
Uni saqlab qo'yib, keyinroq shu joydan davom etish mumkin:
db.buyurtma.watch([], { resumeAfter: saqlangan_token })
Dastur qayta ishga tushganda oqim noldan boshlanadi - ya'ni uzilish paytidagi o'zgarishlar butunlay o'tkazib yuboriladi.
Bu, ayniqsa, quyidagi holatlarda zarar keltiradi:
| Vazifa | Yo'qotish |
|---|---|
| Qidiruv indeksini sinxronlash | Indeks bazadan orqada qoladi |
| Kesh yangilash | Eski ma'lumot ko'rsatiladi |
| Xabar yuborish | Mijoz xabarni olmaydi |
To'g'ri naqsh:
- Har hodisani qayta ishlagandan keyin
h._idni saqlang. - Dastur ishga tushganda oxirgi tokendan davom eting.
- Token
resumeAfteruchun juda eski bo'lsa - MongoDB xato beradi va siz to'liq qayta sinxronlashni boshlaysiz.
Uchinchi holat oplog to'lib ketganda yuz beradi. Oplog hajmi - vaqt oynasi: u 24 soatlik o'zgarishni saqlasa, dastur 24 soatdan ko'p o'chib turmasligi kerak.
Butun baza va klaster bo'yicha kuzatish #
| Yozuv | Nimani kuzatadi |
|---|---|
db.buyurtma.watch() | Bitta to'plam |
db.watch() | Butun baza |
db.getMongo().watch() | Butun klaster |
const oqim = db.watch()
oqim.disableBlockWarnings()
db.buyurtma.insertOne({ _id: 7, mijoz: "Husanboy", summa: 30000 })
db.mijoz.insertOne({ _id: 1, ism: "Malika" })
const a = oqim.next()
a.ns.coll
const b = oqim.next()
b.ns.coll
oqim.close()
ChangeStreamCursor on dokon
{ acknowledged: true, insertedId: 7 }
{ acknowledged: true, insertedId: 1 }
buyurtma
mijoz
ns.coll - hodisa qaysi to'plamda sodir bo'lganini
ko'rsatadi.
Gorizontal kengayish - bo'laklash #
Bitta server yetmay qolganda ikki yo'l bor:
| Yo'l | Nima qilinadi | Chegarasi |
|---|---|---|
| Vertikal | Kuchliroq server | Bir kun kelib tugaydi |
| Gorizontal | Ma'lumotni serverlarga bo'lish | Deyarli cheksiz |
MongoDB da gorizontal kengayish sharding deb ataladi. To'plam bo'lak kaliti (shard key) bo'yicha bir nechta serverga taqsimlanadi:
sh.enableSharding("dokon")
sh.shardCollection("dokon.buyurtma", { mijoz_id: "hashed" })
| Qism | Vazifasi |
|---|---|
| Shard | Ma'lumotning bir bo'lagini saqlaydigan replika to'plami |
| mongos | So'rovni to'g'ri shard ga yo'naltiruvchi vositachi |
| Config server | Qaysi bo'lak qayerda ekanini biladi |
Dastur mongos ga ulanadi va bo'laklar haqida hech narsa
bilmaydi - so'rovlar o'zgarishsiz qolaveradi.
Bo'lak kaliti - shardingdagi eng muhim qaror. Uni noto'g'ri tanlash butun klasterni foydasiz qiladi.
Yomon kalitning uchta belgisi:
| Muammo | Misol | Oqibat |
|---|---|---|
| Monoton o'suvchi | sana, ObjectId | Hamma yangi yozuv bitta shard ga tushadi |
| Kam xilma-xillik | holat (3 ta qiymat) | Ko'pi bilan 3 ta bo'lak |
| So'rovlarga mos emas | Kalit mijoz_id, so'rov sana bo'yicha | Har so'rov hamma shard ga boradi |
Birinchisi eng ko'p uchraydi va u "issiq shard" muammosini keltirib chiqaradi: o'nta serverdan bittasi 100% yuk ostida, qolgan to'qqiztasi bo'sh turadi.
Yaxshi kalit uchta shartni bajaradi: yuqori xilma-xillik, teng taqsimlanish va so'rovlarga moslik.
MongoDB 5.0 dan boshlab kalitni qayta belgilash
(reshardCollection) mumkin, lekin bu butun ma'lumotni
ko'chirishni anglatadi - terabaytlik to'plamda bu kunlar
davom etadi.
Amaliy maslahat: shardingni kerak bo'lgunicha qilmang. Ko'p loyihada bitta yaxshi indekslangan replika to'plami yetadi.
watch()bilan oqim oching va hujjat qo'shing.operationTypevadocumentKeyni chiqaring.updatehodisasida nima kelishini tekshiring.fullDocument: "updateLookup"qo'shib, farqni ko'ring.updateLookupning cheklovini o'z so'zingiz bilan yozing.- Oqimga
$matchfiltri qo'shing. - Filtrga tushmagan hujjat kelmasligini tasdiqlang.
- Resume token nima uchun kerakligini tushuntiring.
db.watch()bilan butun bazani kuzating.- Yomon bo'lak kalitining uchta belgisini sanang.
Xulosa #
- O'zgarishlar oqimi so'rab turishning o'rnini bosadi: server o'zi xabar beradi.
watch()oqim ochilgandan keyingi o'zgarishlarni beradi.operationTypehodisa turini bildiradi:insert,update,deleteva boshqalar.updatehodisasi faqat o'zgargan maydonlarni beradi.- To'liq hujjat uchun
fullDocument: "updateLookup"kerak - lekin u hozirgi holatni o'qiydi. watchagregatsiya quvurini qabul qiladi - filtrlash serverda bajariladi.- Har hodisadagi
_id- resume token; uni saqlamasangiz uzilish paytidagi o'zgarishlar yo'qoladi. - Oqim oplog ustida ishlaydi, shuning uchun replika to'plami talab qilinadi.
- Gorizontal kengayish - sharding; dastur
mongosga ulanadi va bo'laklarni ko'rmaydi. - Bo'lak kaliti eng muhim qaror: monoton o'suvchi kalit butun yukni bitta shard ga to'playdi.
Keyingi bo'limda xavfsizlik va zaxira nusxani 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.