Ngeunaan pindah ti Redis ka Redis-cluster

Ngeunaan pindah ti Redis ka Redis-cluster

Datang kana produk anu parantos ngembangkeun langkung ti dasawarsa, henteu heran mendakan téknologi anu luntur di jerona. Tapi kumaha upami dina genep bulan anjeun kedah nahan beban 10 kali langkung luhur, sareng biaya ragrag naék ratusan kali? Dina hal ieu, anjeun peryogi Insinyur Highload anu saé. Tapi dina henteuna babu sapertos kitu, aranjeunna dipercayakeun kuring pikeun ngarengsekeun masalah. Dina bagian kahiji artikel, abdi bakal ngabejaan ka maneh kumaha urang dipindahkeun ti Redis ka Redis-cluster, sarta dina bagian kadua kuring bakal masihan nasihat ngeunaan kumaha carana ngawitan nganggo klaster jeung naon néangan salila operasi.

Pilihan Téhnologi

Naha parah pisan misah Redis (Redis mandiri) dina konfigurasi 1 master na N budak? Naha kuring nyebatna téknologi luntur?

Heueuh, Redis teu pati goréng... Tapi, aya sababaraha kakirangan anu teu bisa dipaliré.

  • Kahiji, Redis teu ngarojong mékanisme recovery musibah sanggeus master kacilakaan. Pikeun ngabéréskeun masalah ieu, kami nganggo konfigurasi sareng transfer otomatis VIP ka master anyar, ngarobih peran salah sahiji budak sareng ngagentos sésana. Mékanisme ieu jalan, tapi éta sanés solusi anu tiasa dipercaya. Firstly, aya positip palsu, sarta Bréh, éta disposable, sarta sanggeus triggering, lampah manual anu diperlukeun pikeun ngecas cinyusu.

  • Bréh, ayana ngan hiji master ngabalukarkeun masalah sharding. Kuring kungsi nyieun sababaraha klaster bebas "1 master na N budak", lajeng sacara manual ngadistribusikaeun database diantara mesin ieu sarta miharep yén besok salah sahiji database moal ngabareuhan jadi loba nu kudu dipindahkeun ka conto misah.

Naon pilihan na?

  • Solusi anu paling mahal sareng paling sugih nyaéta Redis-Enterprise. Ieu mangrupikeun solusi kotak kalayan dukungan téknis anu lengkep. Sanaos kanyataan yén éta katingalina idéal tina sudut pandang téknis, éta henteu cocog pikeun urang kusabab alesan ideologis.
  • redis-kluster. Out of the box, aya dukungan pikeun master failover sareng sharding. Antarbeungeutna ampir sami sareng versi biasa. Sigana ngajangjikeun, hayu urang ngobrol ngeunaan pitfalls engké.
  • Tarantool, Memcache, Aerospike sareng anu sanésna. Sadaya alat ieu ngalakukeun hal anu sami. Tapi unggal boga drawbacks na. Urang mutuskeun teu nempatkeun sakabéh endog urang dina hiji karinjang. Kami nganggo Memcache sareng Tarantool pikeun tugas-tugas sanés, sareng ningali payun, kuring bakal nyarios yén dina prakték urang aya seueur masalah sareng aranjeunna.

Spésifikasi pamakéan

Hayu urang tingali tugas naon anu kami parantos direngsekeun ku Redis sareng fungsi naon anu kami dianggo:

  • Cache sateuacan naros ka jasa jauh sapertos 2GIS | golang

    GET SET MGET MSET "PILIH DB"

  • Cache saméméh MYSQL | PHP

    GET SET MGET MSET SCAN "KEY BY PATTERN" "SELECT DB"

  • Panyimpenan utama pikeun jasa damel sareng sesi sareng koordinat supir | golang

    GET SET MGET MSET "PILIH DB" "TAMBAHAN GEO KEY" "GET GEO KEY" SCAN

Sakumaha anjeun tiasa tingali, euweuh matematik luhur. Naon lajeng kasusah? Hayu urang nempo unggal metoda misah.

Metode
gambaran
Fitur redis-cluster
kaputusan

KASET
Tulis/baca konci

MGET MSET
Tulis / baca sababaraha konci
Kenopna bakal aya dina titik anu béda. Perpustakaan anu siap-siap tiasa ngalakukeun Multi-operasi ngan dina hiji titik
Ganti MGET sareng pipa operasi N GET

PILIH DB
Milih basa pikeun digawekeun ku
Henteu ngadukung sababaraha pangkalan data
Pasang sadayana dina hiji dasar. Tambahkeun awalan kana konci

Scan
Ngaliwat sadaya konci dina pangkalan data
Kusabab urang gaduh hiji basa, éta mahal teuing pikeun ngaliwat sadaya konci dina kluster
Pertahankeun invarian dina hiji konci sareng lakukeun HSCAN dina konci ieu. Atawa nyerah sagemblengna

geo
Operasi kalawan geokey
Geokey teu beling

Konci ku pola
Pilarian konci ku pola
Kusabab urang gaduh hiji basa, urang bakal milarian sadaya konci dina kluster. Mahal teuing
Nolak atanapi ngajaga invarian, sapertos dina kasus SCAN

redis vs redis-kluster

Naon anu urang leungit sareng naon anu urang kéngingkeun nalika ngalih ka klaster?

  • kalemahan: urang leungit fungsionalitas sababaraha database.
    • Lamun urang hayang nyimpen data logis nu teu patali dina hiji klaster, urang kudu nyieun crutches dina bentuk awalan.
    • Urang kaleungitan sadaya operasi database, sapertos SCAN, DBSIZE, CLEAR DB, jsb.
    • Multi-operasi geus jadi leuwih hese pikeun nerapkeun, sabab bisa merlukeun aksés ka sababaraha titik.
  • kaunggulan:
    • Failover dina bentuk master failover.
    • Sharding di sisi Redis.
    • Mindahkeun data antara titik sacara atom sareng tanpa downtime.
    • Nambahkeun sareng ngadistribusikaeun kapasitas sareng beban tanpa waktos downtime.

Kuring bakal nyimpulkeun yén upami anjeun henteu kedah nyayogikeun tingkat kasabaran sesar anu luhur, teras pindah ka klaster henteu patut, sabab ieu tiasa janten tugas anu teu penting. Tapi upami anjeun mimitina milih antara versi anu misah sareng klaster, maka anjeun kedah milih klaster, sabab éta henteu langkung parah sareng, sajaba, bakal ngaleungitkeun nyeri sirah anjeun.

Nyiapkeun pikeun pindah

Hayu urang mimitian ku sarat pikeun pindah:

  • Éta kedah mulus. A eureun pinuh ku layanan pikeun 5 menit teu cocog kami.
  • Éta kedah aman sareng laun-gancang. Abdi hoyong gaduh sababaraha kontrol kana kaayaan. Kami henteu hoyong ngagedekeun sadayana sakaligus sareng ngadoakeun tombol rollback.
  • Leungitna data minimal nalika pindah. Urang ngarti yén éta bakal hésé pisan mindahkeun atom, sangkan ngidinan sababaraha desynchronization antara data dina Redis biasa na clustered.

Pangropéa Klaster

Sateuacan ngalih, anjeun kedah mikir naha urang tiasa ngadukung klaster:

  • Grafik. Kami nganggo Prometheus sareng Grafana pikeun grafik beban prosesor, mémori anu dianggo, jumlah klien, jumlah GET, SET, operasi AUTH, jsb.
  • Kaahlian. Bayangkeun yén isukan anjeun bakal tanggung jawab pikeun klaster anu ageung. Lamun megatkeun, teu saurang ogé tapi anjeun bisa ngalereskeun eta. Upami anjeunna mimiti ngalambatkeun, sadayana bakal lumpat ka anjeun. Upami anjeun kedah nambihan sumber atanapi ngabagikeun deui beban - balik deui ka anjeun. Dina raraga teu ngahurungkeun abu di 25, éta sasaena foresee kasus ieu jeung pariksa sateuacanna kumaha téhnologi bakal kalakuanana dina lampah nu tangtu. Urang bakal ngobrol ngeunaan ieu dina leuwih jéntré dina bagian Kaahlian.
  • Pangimeutan sareng panggeuing. Nalika klaster ngarecah, anjeun hoyong anu pangheulana terang ngeunaan éta. Di dieu kami ngawatesan diri kana béwara yén sadaya titik ngabalikeun inpormasi anu sami ngeunaan kaayaan klaster (enya, éta kajadian béda). Sareng sesa masalah tiasa gancang ditingali ku béwara tina jasa klien Redis.

Relokasi

Kumaha urang bakal mindahkeun:

  • Anu mimiti, anjeun kedah nyiapkeun perpustakaan pikeun damel sareng kluster. Salaku dasar pikeun versi Go, kami nyandak go-redis sareng ngarobih sakedik pikeun diri urang sorangan. Urang ngalaksanakeun Multi-métode ngaliwatan pipelines, sarta ogé rada dilereskeun aturan pikeun requests repeating. Versi PHP miboga leuwih masalah, tapi urang ahirna netep dina php-redis. Aranjeunna nembe ngalaksanakeun dukungan kluster sareng katingalina saé dina pendapat urang.
  • Salajengna, anjeun kedah nyebarkeun klaster sorangan. Hal ieu dilakukeun sacara harfiah dina dua paréntah dumasar kana file konfigurasi. Setélan bakal dibahas dina leuwih jéntré di handap.
  • Pikeun gerakan bertahap, kami nganggo mode garing. Kusabab urang gaduh dua vérsi perpustakaan sareng antarmuka anu sami (hiji kanggo vérsi biasa, anu sanés pikeun kluster), teu aya biaya naon waé pikeun ngadamel bungkus anu bakal tiasa dianggo sareng versi anu misah sareng sakaligus duplikat sadaya pamundut ka klaster, ngabandingkeun réspon jeung nulis discrepancies kana log (bisi kami di NewRelic). Ku kituna, sanajan versi klaster megatkeun salila rollout nu, produksi urang moal kapangaruhan.
  • Saatos ngagulung kluster dina modeu garing, urang tiasa ningal grafik tina bédana réspon. Upami proporsi kasalahan lalaunan tapi pasti nuju ka sababaraha konstanta leutik, maka sadayana henteu kunanaon. Naha aya kénéh discrepancies? Kusabab rekaman dina versi misah lumangsung saeutik saméméhna ti dina klaster, sarta alatan microlag nu, data bisa diverge. Tetep ngan ukur ningali log anu béda, sareng upami sadayana tiasa dijelaskeun ku sipat non-atom tina catetan, maka urang tiasa langkung jauh.
  • Ayeuna anjeun tiasa ngalihkeun modeu garing dina arah anu sabalikna. Urang bakal nulis jeung maca tina klaster, sarta duplikat kana versi misah. Kanggo naon? Dina minggu hareup, abdi hoyong niténan karya klaster. Lamun ujug-ujug tétéla yén aya masalah dina Puncak beban, atawa urang teu tumut kana akun hiji hal, urang salawasna boga hiji rollback darurat ka kode heubeul jeung up-to-date data berkat garing-mode.
  • Tetep nganonaktipkeun mode garing sareng ngabongkar versi anu misah.

Pakar

Kahiji, sakeudeung ngeunaan alat klaster.

Anu mimiti, Redis mangrupikeun toko konci-nilai. Senar wenang dipaké salaku konci. Angka, string, sareng struktur integer tiasa dianggo salaku nilai. Aya seueur anu terakhir, tapi ieu henteu penting pikeun urang ngartos struktur umum.
Tingkat salajengna abstraksi sanggeus konci téh slot (SLOT). Unggal konci milik salah sahiji 16 liang . Unggal slot bisa ngandung sagala angka konci. Ku kituna, sadaya kenop digolongkeun kana 383 susunan disjoint.
Ngeunaan pindah ti Redis ka Redis-cluster

Salajengna, kedah aya N master titik dina klaster. Unggal titik tiasa dianggap salaku conto Redis anu misah anu terang sadayana ngeunaan titik-titik sanés dina kluster. Unggal titik master ngandung sababaraha slot. Unggal slot milik ngan hiji titik master. Kabéh slot kudu disebarkeun antara titik. Upami sababaraha slot henteu dialokasikeun, teras konci anu disimpen di dinya moal sayogi. Masuk akal pikeun ngajalankeun unggal titik master dina mesin logis atanapi fisik anu misah. Perlu diinget yén unggal titik ngan ukur dijalankeun dina hiji inti, sareng upami anjeun hoyong ngajalankeun sababaraha instansi Redis dina mesin logis anu sami, teras pastikeun aranjeunna dijalankeun dina inti anu béda (kami henteu acan nyobian ieu, tapi dina téori sadayana kedahna. gawé). Intina, master node nyayogikeun sharding normal, sareng langkung seueur master node ngamungkinkeun anjeun pikeun skala nyerat sareng maca pamundut.

Barina ogé kenop disebarkeun ngaliwatan slot, sarta slot sumebar dina master titik, jumlah wenang titik budak bisa ditambahkeun kana unggal titik master. Di jero unggal bungkusan "master-slave" sapertos kitu, réplikasi normal bakal jalan. Budak anu diperlukeun pikeun skala requests maca jeung failover lamun master gagal.
Ngeunaan pindah ti Redis ka Redis-cluster

Ayeuna hayu urang ngobrol ngeunaan operasi anu bakal leuwih hadé mun bisa ngalakukeun.

Urang bakal ngakses sistem ngaliwatan Redis-CLI. Kusabab Redis teu gaduh titik éntri tunggal, anjeun tiasa ngalakukeun operasi di handap ieu dina salah sahiji titik. Dina unggal paragraf, kuring nyalira narik perhatian kana kamungkinan ngalaksanakeun operasi dina beban.

  • Hal kahiji sareng anu paling penting anu urang peryogikeun nyaéta operasi titik kluster. Ieu mulih kaayaan klaster, nembongkeun daptar titik, kalungguhan maranéhna, alokasi slot, jsb. Kanggo inpo nu leuwih lengkep, tingali inpo klaster jeung slot klaster.
  • Éta langkung saé upami tiasa nambihan sareng ngahapus titik. Aya klaster papanggih jeung klaster poho operasi pikeun ieu. Punten dicatet yén klaster hilap kedah diterapkeun ka unggal titik, boh master sareng réplika. Jeung papanggih klaster cukup pikeun nelepon ngan dina hiji titik. Bédana ieu tiasa pikasieuneun, janten langkung saé diajar ngeunaan éta sateuacan anjeun nempatkeun klaster anjeun kana produksi. Nambahkeun titik hiji aman dipigawé dina ngempur sarta henteu mangaruhan operasi tina klaster sagala cara (anu logis). Upami anjeun badé ngahapus titik tina kluster, anjeun kedah mastikeun yén teu aya slot anu tinggaleun (disebutkeun anjeun résiko kaleungitan aksés ka sadaya konci dina titik ieu). Ogé, ulah ngahapus master anu gaduh budak, upami teu aya sora anu teu perlu pikeun master anyar bakal dilakukeun. Upami teu aya slot dina titik, maka ieu mangrupikeun masalah leutik, tapi naha urang peryogi pilihan tambahan upami urang mimiti tiasa ngahapus budak.
  • Upami anjeun kedah maksakeun ngarobih master sareng budak, maka paréntah failover klaster bakal dilakukeun. Nalika nyauran éta dina perang, anjeun kedah ngartos yén master moal sayogi salami operasi. Ilaharna, saklar lumangsung kirang ti sadetik, tapi henteu sacara atom. Anjeun tiasa ngaharepkeun sababaraha pamundut ka master gagal dina waktos ayeuna.
  • Sateuacan ngahapus titik tina kluster, éta henteu kedah ngagaduhan slot anu tinggaleun. Éta langkung saé pikeun ngadistribusikaeun aranjeunna nganggo paréntah reshard klaster. Slot bakal ditransfer tina hiji master ka anu sanés. Sakabéh operasi butuh sababaraha menit, gumantung kana jumlah data anu ditransfer, tapi prosés mindahkeun éta aman tur henteu mangaruhan operasi klaster dina sagala cara. Ku kituna, sadaya data bisa ditransfer ti hiji titik ka katuhu sejen dina beban, sarta ulah salempang ngeunaan kasadiaan maranéhanana. Sanajan kitu, aya ogé subtleties. Firstly, mindahkeun data pakait sareng beban tangtu dina titik panarima tur ngirim. Upami titik panarima parantos dimuat dina prosésor, maka anjeun henteu kedah ngamuat nampi data énggal. Bréh, pas teu aya hiji slot ditinggalkeun dina master ngirim, sadaya budak na bakal langsung indit ka master nu slot ieu dipindahkeun. Jeung masalahna nyaeta sakabeh budak ieu bakal hoyong nyinkronkeun data sakaligus. Sareng anjeun bakal untung upami éta parsial tinimbang singkronisasi pinuh. Tetep kieu dina pikiran jeung ngagabungkeun operasi mindahkeun slot jeung nganonaktipkeun / mindahkeun budak. Atawa miharep yén anjeun boga margin cukup kaamanan.
  • Naon anu kudu dipigawé lamun salila mindahkeun anjeun manggihan yén anjeun geus leungit slot wae? Kuring miharep masalah ieu teu mangaruhan anjeun, tapi lamun nanaon, aya operasi fix klaster. Sahenteuna, manehna bakal paburencay slot diantara titik dina urutan acak. Abdi nyarankeun mariksa karyana ku mimiti nyoplokkeun titik kalawan slot disebarkeun ti kluster. Kusabab data dina slot unallocated geus sadia, éta telat salempang ngeunaan masalah sareng kasadiaan slot ieu. Dina gilirannana, operasi moal mangaruhan slot disadiakeun.
  • Operasi mangpaat séjén nyaéta monitor. Eta ngidinan Anjeun pikeun ningali sacara real waktu sakabéh daptar requests bade titik. Leuwih ti éta, anjeun tiasa grep eta sarta manggihan lamun aya lalulintas diperlukeun.

Ogé kedah disebatkeun nyaéta prosedur master failover. Pondokna, éta, sarta, dina pamanggih kuring, gawéna hébat. Nanging, ulah nganggap yén upami anjeun cabut kabel listrik dina mesin sareng master node, Redis bakal langsung ngalih sareng klien moal perhatikeun karugian. Dina prakték kuring, switching nyokot sababaraha detik. Antukna, bagian tina data moal sadia: unavailability master dideteksi, titik milih nu anyar, budak nu switched, data disingkronkeun. Cara anu pangsaéna pikeun mastikeun yén skéma éta jalanna nyaéta ngalaksanakeun latihan lokal. Nyetél klaster dina laptop anjeun, masihan beban minimal, simulate kacilakaan (Contona, ku blocking palabuhan), evaluate laju switching. Dina pamanggih kuring, ngan sanggeus maén dina cara kieu pikeun atawa dua poé, anjeun tiasa pastikeun yén téhnologi bakal jalan. Nya, atanapi ngarepkeun parangkat lunak anu dianggo ku satengah tina Internét sigana tiasa dianggo.

Konfigurasi

Seringna, konfigurasi mangrupikeun hal anu mimiti anjeun kedah ngamimitian damel sareng alat éta. Butuh sababaraha usaha pikeun maksakeun diri pikeun balik deui ka setélan sareng ngaliwat aranjeunna sacara saksama. Dina mémori kuring, urang ngagaduhan sahenteuna dua gagal serius kusabab henteu merhatikeun konfigurasi. Nengetan husus ka titik handap:

  • waktos 0
    Waktos saatos sambungan anu teu aktip ditutup (dina detik). 0 - ulah nutup
    Henteu unggal perpustakaan urang tiasa nutup sambungan anu leres. Ku nganonaktipkeun setelan ieu, urang ngajalankeun résiko ngajalankeun kana wates dina jumlah klien. Di sisi anu sanés, upami aya masalah sapertos kitu, maka sambungan anu leungit sacara otomatis bakal nyumputkeunana, sareng urang moal perhatikeun. Ogé, ulah aktipkeun setelan ieu nalika nganggo sambungan anu tetep.
  • Simpen xy & appendonly enya
    Nyimpen snapshot RDB.
    Masalah RDB/AOF bakal dibahas sacara rinci di handap.
  • eureun-nulis-on-bgsave-kasalahan euweuh & budak-ngawula-basi-data enya
    Upami diaktipkeun, teras upami snapshot RDB rusak, master bakal lirén nampi pamundut parobihan. Lamun sambungan ka master leungit, budak bisa neruskeun ngabales (enya). Atawa eureun ngajawab (henteu)
    Kami henteu resep kana kaayaan dimana Redis janten waluh.
  • repl-ping-budak-periode 5
    Saatos waktos ieu, urang bakal hariwang yén master parantos rusak sareng éta waktosna pikeun ngalaksanakeun prosedur failover.
    Anjeun kedah sacara manual milarian kasaimbangan antara positip palsu sareng peluncuran failover. Dina prakték urang, ieu 5 detik.
  • repl-backlog-ukuran 1024mb & epl-backlog-ttl 0
    Persis salaku loba data urang bisa nyimpen dina panyangga pikeun replica fallen kaluar. Upami panyangga béak, anjeun kedah nyinkronkeun lengkep.
    Prakték nunjukkeun yén éta langkung saé pikeun nyetél nilai anu langkung ageung. Aya seueur alesan kunaon réplika tiasa mimiti katinggaleun. Upami éta katinggaleun, maka kamungkinan master anjeun parantos berjuang pikeun ngatasi, sareng sinkronisasi lengkep bakal janten jerami anu terakhir.
  • maxclients 10000
    Jumlah maksimum klien hiji-waktos.
    Dina pangalaman urang, éta hadé pikeun nempatkeun hiji nilai nu leuwih gede. Redis nanganan 10K sambungan anu saé. Ngan pastikeun sistem ngabogaan sockets cukup.
  • maxmemory-kawijakan volatile-ttl
    Aturan dimana kenop dihapus nalika wates memori sadia geus ngahontal.
    Henteu aturan sorangan anu penting, tapi ngartos kumaha ieu bakal kajadian. Redis tiasa dipuji pikeun kamampuanna pikeun ngalakukeun sacara normal nalika wates mémori parantos ngahontal.

Masalah RDB sareng AOF

Sanajan Redis sorangan nyimpen sagala informasi dina RAM, aya ogé mékanisme pikeun nyimpen data kana disk. Leuwih husus, aya tilu mékanisme:

  • RDB-snapshot mangrupakeun snapshot lengkep sadaya data. Setel nganggo konfigurasi SAVE XY sareng baca salaku "Simpen snapshot pinuh sadaya data unggal X detik upami sahenteuna konci Y parantos robih."
  • append-hijina file - daptar operasi dina urutan aranjeunna dipigawé. Nambahkeun operasi asup anyar kana file unggal X detik atawa unggal operasi Y.
  • RDB sareng AOF - kombinasi dua anu sateuacana.

Sadaya metode gaduh kaunggulan sareng kalemahanana, kuring moal daptar sadayana, kuring ngan ukur nengetan titik anu henteu atra, dina pendapat kuring.

Kahiji, nyimpen snapshot RDB merlukeun nelepon FORK. Lamun aya loba data, ieu bisa ngagantung sakabéh Redis pikeun periode ti sababaraha milliseconds ka detik. Salaku tambahan, sistem kedah nyayogikeun mémori pikeun snapshot sapertos kitu, anu nyababkeun kabutuhan pikeun nyimpen dua kali cadangan RAM dina mesin logis: upami 8 GB dialokasikeun pikeun Redis, maka 16 kedah sayogi dina mesin virtual sareng éta. .

Bréh, aya masalah sareng sinkronisasi parsial. Dina modeu AOF, nalika budak disambungkeun deui, sinkronisasi pinuh bisa dipigawé tinimbang singkronisasi parsial. Naha ieu kajadian, kuring teu bisa ngarti. Tapi patut diémutan.

Dua titik ieu geus ngajadikeun anjeun pikir ngeunaan naha urang bener butuh data ieu dina disk, lamun sagalana geus duplicated ku budak atoh. Anjeun tiasa leungit data ngan lamun sakabeh budak gagal, sarta ieu masalah tingkat "seuneu di DC". Salaku kompromi a, anjeun tiasa nyarankeun nyimpen data ukur dina budak, tapi dina hal ieu anjeun kudu mastikeun yén budak ieu moal pernah jadi master salila recovery musibah (aya setelan prioritas budak dina config maranéhna pikeun ieu). Pikeun diri urang sorangan, dina unggal hal husus, urang mikir ngeunaan naha perlu pikeun nyimpen data kana disk, sarta paling sering jawaban - "henteu".

kacindekan

Dina kacindekan, kuring ngarepkeun kuring tiasa masihan ide umum ngeunaan karya redis-cluster ka anu teu acan kantos ngupingkeun éta, sareng ogé narik perhatian kana sababaraha titik anu teu jelas pikeun anu parantos ngagunakeunana. lila.
Hatur nuhun pikeun waktos anjeun sareng, sapertos biasa, koméntar ngeunaan topik éta wilujeng sumping.

sumber: www.habr.com

Tambahkeun komentar