Ailysgrifennu cronfa ddata negeseuon VKontakte o'r dechrau a goroesi

Mae ein defnyddwyr yn ysgrifennu negeseuon at ei gilydd heb wybod blinder.
Ailysgrifennu cronfa ddata negeseuon VKontakte o'r dechrau a goroesi
Mae hynny'n eithaf llawer. Pe baech yn bwriadu darllen holl negeseuon yr holl ddefnyddwyr, byddai'n cymryd mwy na 150 mil o flynyddoedd. Ar yr amod eich bod yn ddarllenwr eithaf datblygedig ac yn gwario dim mwy nag eiliad ar bob neges.

Gyda chymaint o ddata, mae'n hanfodol bod y rhesymeg ar gyfer ei storio a'i gyrchu yn cael ei hadeiladu yn y ffordd orau bosibl. Fel arall, mewn un eiliad nad yw mor wych, efallai y daw'n amlwg y bydd popeth yn mynd o'i le yn fuan.

I ni, daeth y foment hon flwyddyn a hanner yn ôl. Sut y daethom i hyn a beth ddigwyddodd yn y diwedd - rydym yn dweud wrthych mewn trefn.

Cefndir

Yn y gweithrediad cyntaf, gweithiodd negeseuon VKontakte ar gyfuniad o backend PHP a MySQL. Mae hwn yn ateb cwbl arferol ar gyfer gwefan myfyrwyr bach. Fodd bynnag, tyfodd y wefan hon yn afreolus a dechreuodd fynnu optimeiddio strwythurau data drosto'i hun.

Ar ddiwedd 2009, ysgrifennwyd y storfa peiriant testun cyntaf, ac yn 2010 trosglwyddwyd negeseuon iddi.

Yn y peiriant testun, roedd negeseuon yn cael eu storio mewn rhestrau - math o “flychau post”. Mae pob rhestr o'r fath yn cael ei phennu gan uid - y defnyddiwr sy'n berchen ar yr holl negeseuon hyn. Mae gan neges set o briodoleddau: dynodwr interlocutor, testun, atodiadau, ac ati. Y dynodwr neges yn y “blwch” yw local_id, nid yw byth yn newid ac fe'i neilltuir yn olynol ar gyfer negeseuon newydd. Mae'r “blychau” yn annibynnol ac nid ydynt wedi'u cydamseru â'i gilydd y tu mewn i'r injan; mae cyfathrebu rhyngddynt yn digwydd ar lefel PHP. Gallwch edrych ar strwythur data a galluoedd peiriant testun o'r tu mewn yma.
Ailysgrifennu cronfa ddata negeseuon VKontakte o'r dechrau a goroesi
Roedd hyn yn ddigon ar gyfer gohebiaeth rhwng dau ddefnyddiwr. Tybed beth ddigwyddodd nesaf?

Ym mis Mai 2011, cyflwynodd VKontakte sgyrsiau gyda nifer o gyfranogwyr - aml-sgwrs. Er mwyn gweithio gyda nhw, fe wnaethom godi dau glwstwr newydd - sgyrsiau-aelodau a sgwrsio-aelodau. Mae'r cyntaf yn storio data am sgyrsiau gan ddefnyddwyr, mae'r ail yn storio data am ddefnyddwyr trwy sgyrsiau. Yn ogystal â'r rhestrau eu hunain, mae hyn yn cynnwys, er enghraifft, y defnyddiwr sy'n gwahodd a'r amser y cawsant eu hychwanegu at y sgwrs.

“PHP, gadewch i ni anfon neges i'r sgwrs,” meddai'r defnyddiwr.
“Dewch ymlaen, {enw defnyddiwr},” meddai PHP.
Ailysgrifennu cronfa ddata negeseuon VKontakte o'r dechrau a goroesi
Mae anfanteision i'r cynllun hwn. Mae cydamseru yn dal i fod yn gyfrifoldeb PHP. Mae sgyrsiau mawr a defnyddwyr sy'n anfon negeseuon atynt ar yr un pryd yn stori beryglus. Gan fod yr enghraifft peiriant testun yn dibynnu ar yr uid, gallai cyfranogwyr sgwrs dderbyn yr un neges ar wahanol adegau. Gallai rhywun fyw gyda hyn pe bai cynnydd yn aros yn ei unfan. Ond ni fydd hynny'n digwydd.

Ar ddiwedd 2015, fe wnaethom lansio negeseuon cymunedol, ac ar ddechrau 2016, lansiwyd API ar eu cyfer. Gyda dyfodiad chatbots mawr mewn cymunedau, roedd yn bosibl anghofio am ddosbarthiad llwyth cyfartal.

Mae bot da yn cynhyrchu sawl miliwn o negeseuon y dydd - ni all hyd yn oed y defnyddwyr mwyaf siaradus frolio hyn. Mae hyn yn golygu bod rhai achosion o beiriant testun, yr oedd botiau o'r fath yn byw arnynt, wedi dechrau dioddef i'r eithaf.

Mae peiriannau negeseuon yn 2016 yn 100 achos o sgwrsio-aelodau a sgyrsiau-aelodau, ac 8000 o beiriannau testun. Cawsant eu cynnal ar fil o weinyddion, pob un â 64 GB o gof. Fel mesur brys cyntaf, gwnaethom gynyddu'r cof 32 GB arall. Fe wnaethom amcangyfrif y rhagolygon. Heb newidiadau llym, byddai hyn yn ddigon am ryw flwyddyn arall. Mae angen i chi naill ai gael gafael ar galedwedd neu optimeiddio'r cronfeydd data eu hunain.

Oherwydd natur y bensaernïaeth, dim ond yn gwneud synnwyr i gynyddu caledwedd mewn lluosrifau. Hynny yw, o leiaf dyblu nifer y ceir - yn amlwg, mae hwn yn llwybr braidd yn ddrud. Byddwn yn gwneud y gorau.

Cysyniad newydd

Hanfod canolog y dull newydd yw sgwrsio. Mae gan sgwrs restr o negeseuon sy'n ymwneud ag ef. Mae gan y defnyddiwr restr o sgyrsiau.

Yr isafswm gofynnol yw dwy gronfa ddata newydd:

  • peiriant sgwrsio. Mae hon yn ystorfa o fectorau sgwrsio. Mae gan bob sgwrs fector o negeseuon sy'n ymwneud ag ef. Mae gan bob neges destun a dynodwr neges unigryw y tu mewn i'r sgwrs - chat_local_id.
  • defnyddiwr-injan. Mae hwn yn storfa o fectorau defnyddwyr - dolenni i ddefnyddwyr. Mae gan bob defnyddiwr fector o peer_id (interlocutors - defnyddwyr eraill, aml-sgwrs neu gymunedau) a fector o negeseuon. Mae gan bob peer_id fector o negeseuon sy'n ymwneud ag ef. Mae gan bob neges chat_local_id ac ID neges unigryw ar gyfer y defnyddiwr hwnnw - user_local_id.

Ailysgrifennu cronfa ddata negeseuon VKontakte o'r dechrau a goroesi
Mae clystyrau newydd yn cyfathrebu â'i gilydd gan ddefnyddio TCP - mae hyn yn sicrhau nad yw trefn y ceisiadau yn newid. Mae'r ceisiadau eu hunain a chadarnhadau ar eu cyfer yn cael eu cofnodi ar y gyriant caled - fel y gallwn adfer cyflwr y ciw ar unrhyw adeg ar ôl methiant neu ailgychwyn yr injan. Gan fod y peiriant defnyddiwr a'r peiriant sgwrsio yn 4 mil o ddarnau yr un, bydd y ciw ceisiadau rhwng y clystyrau yn cael ei ddosbarthu'n gyfartal (ond mewn gwirionedd nid oes dim o gwbl - ac mae'n gweithio'n gyflym iawn).

Mae gweithio gyda disg yn ein cronfeydd data yn y rhan fwyaf o achosion yn seiliedig ar gyfuniad o log deuaidd o newidiadau (binlog), cipluniau statig a delwedd rannol yn y cof. Ysgrifennir newidiadau yn ystod y dydd i binlog, a chreir ciplun o'r cyflwr presennol o bryd i'w gilydd. Mae ciplun yn gasgliad o strwythurau data sydd wedi'u hoptimeiddio at ein dibenion ni. Mae'n cynnwys pennawd (metaindex y ddelwedd) a set o fetaffeiliau. Mae'r pennawd yn cael ei storio'n barhaol yn RAM ac mae'n nodi ble i chwilio am ddata o'r ciplun. Mae pob metaffeil yn cynnwys data sy'n debygol o fod ei angen ar adegau agos - er enghraifft, yn ymwneud ag un defnyddiwr. Pan fyddwch yn cwestiynu'r gronfa ddata gan ddefnyddio'r pennawd ciplun, darllenir y metaffeil gofynnol, ac yna cymerir newidiadau yn y binlog a ddigwyddodd ar ôl i'r ciplun gael ei greu i ystyriaeth. Gallwch ddarllen mwy am fanteision y dull hwn yma.

Ar yr un pryd, dim ond unwaith y dydd y mae'r data ar y gyriant caled ei hun yn newid - yn hwyr yn y nos ym Moscow, pan fo'r llwyth yn fach iawn. Diolch i hyn (gan wybod bod y strwythur ar y ddisg yn gyson trwy gydol y dydd), gallwn fforddio disodli fectorau gyda araeau o faint sefydlog - ac oherwydd hyn, ennill yn y cof.

Mae anfon neges yn y cynllun newydd yn edrych fel hyn:

  1. Mae'r backend PHP yn cysylltu â'r peiriant defnyddiwr gyda chais i anfon neges.
  2. mae user-engine yn dirprwyo'r cais i'r enghraifft chat-engine a ddymunir, sy'n dychwelyd i user-engine chat_local_id - dynodwr unigryw neges newydd o fewn y sgwrs hon. Yna mae'r chat_engine yn darlledu'r neges i'r holl dderbynwyr yn y sgwrs.
  3. Mae user-engine yn derbyn chat_local_id o chat-engine ac yn dychwelyd user_local_id i PHP - dynodwr neges unigryw ar gyfer y defnyddiwr hwn. Yna defnyddir y dynodwr hwn, er enghraifft, i weithio gyda negeseuon trwy'r API.

Ailysgrifennu cronfa ddata negeseuon VKontakte o'r dechrau a goroesi
Ond yn ogystal ag anfon negeseuon mewn gwirionedd, mae angen i chi weithredu ychydig o bethau pwysicach:

  • Is-restrau, er enghraifft, yw'r negeseuon mwyaf diweddar a welwch wrth agor y rhestr sgwrsio. Negeseuon heb eu darllen, negeseuon gyda thagiau (“Pwysig”, “Sbam”, ac ati).
  • Cywasgu negeseuon yn y peiriant sgwrsio
  • Cadw negeseuon yn y peiriant defnyddiwr
  • Chwilio (trwy bob deialog ac o fewn un penodol).
  • Diweddariad amser real (Longpolling).
  • Arbed hanes i weithredu caching ar gleientiaid symudol.

Mae pob is-restr yn strwythurau sy'n newid yn gyflym. I weithio gyda nhw rydym yn defnyddio Coed ar led. Eglurir y dewis hwn gan y ffaith ein bod weithiau ar frig y goeden yn storio segment cyfan o negeseuon o giplun - er enghraifft, ar ôl ail-fynegi bob nos, mae'r goeden yn cynnwys un top, sy'n cynnwys holl negeseuon yr is-restr. Mae'r goeden Splay yn ei gwneud hi'n hawdd ei fewnosod i ganol fertig o'r fath heb feddwl am gydbwyso. Yn ogystal, nid yw Splay yn storio data diangen, sy'n arbed cof i ni.

Mae negeseuon yn cynnwys llawer iawn o wybodaeth, testun yn bennaf, sy'n ddefnyddiol i allu cywasgu. Mae'n bwysig ein bod yn gallu dadarchifo hyd yn oed un neges unigol yn gywir. Defnyddir i gywasgu negeseuon algorithm Huffman gyda'n heuristics ein hunain - er enghraifft, rydym yn gwybod bod geiriau mewn negeseuon yn ail â “di-eiriau” - bylchau, atalnodau - ac rydym hefyd yn cofio rhai o nodweddion defnyddio symbolau ar gyfer yr iaith Rwsieg.

Gan fod llawer llai o ddefnyddwyr na sgyrsiau, er mwyn arbed ceisiadau disg mynediad ar hap yn y peiriant sgwrsio, rydym yn storio negeseuon yn y peiriant defnyddiwr.

Gweithredir chwiliad neges fel ymholiad croeslin o beiriant-defnyddiwr i bob achos peiriant sgwrsio sy'n cynnwys sgyrsiau'r defnyddiwr hwn. Cyfunir y canlyniadau yn y peiriant defnyddiwr ei hun.

Wel, mae'r holl fanylion wedi'u cymryd i ystyriaeth, y cyfan sydd ar ôl yw newid i gynllun newydd - a gorau oll heb i ddefnyddwyr sylwi arno.

Mudo data

Felly, mae gennym beiriant testun sy'n storio negeseuon fesul defnyddiwr, a dau glwstwr o aelodau sgwrsio a sgyrsiau aelodau sy'n storio data am ystafelloedd aml-sgwrs a'r defnyddwyr ynddynt. Sut i symud o hyn i'r peiriant defnyddiwr a'r peiriant sgwrsio newydd?

defnyddiwyd sgyrsiau aelod yn yr hen gynllun yn bennaf ar gyfer optimeiddio. Fe wnaethom drosglwyddo'r data angenrheidiol ohono'n gyflym i aelodau sgwrsio, ac yna ni chymerodd ran yn y broses fudo mwyach.

Ciw ar gyfer sgwrs-aelodau. Mae'n cynnwys 100 o achosion, tra bod gan chat-engine 4 mil. Er mwyn trosglwyddo'r data, mae angen i chi gydymffurfio ag ef - ar gyfer hyn, rhannwyd yr aelodau sgwrsio yn yr un 4 mil o gopïau, ac yna galluogwyd darllen y binlog sgwrsio-aelodau yn y peiriant sgwrsio.
Ailysgrifennu cronfa ddata negeseuon VKontakte o'r dechrau a goroesi
Nawr mae chat-engine yn gwybod am aml-sgwrs gan sgwrsio-aelodau, ond nid yw'n gwybod dim eto am ddeialogau gyda dau gydweithiwr. Mae deialogau o'r fath wedi'u lleoli yn y peiriant testun gan gyfeirio at ddefnyddwyr. Yma fe wnaethom gymryd y data “yn uniongyrchol”: roedd pob enghraifft o beiriant sgwrsio yn gofyn i bob peiriant testun a oedd ganddynt y ddeialog yr oedd ei angen.

Gwych - mae peiriant sgwrsio yn gwybod pa sgyrsiau aml-sgwrs sydd yna ac yn gwybod pa ddeialogau sydd yna.
Mae angen i chi gyfuno negeseuon mewn sgyrsiau aml-sgwrs fel bod gennych restr o negeseuon ym mhob sgwrs yn y pen draw. Yn gyntaf, mae peiriant sgwrsio yn adalw pob neges defnyddiwr o'r sgwrs hon o beiriant testun. Mewn rhai achosion mae yna lawer ohonyn nhw (hyd at gannoedd o filiynau), ond gydag eithriadau prin iawn mae'r sgwrs yn ffitio'n gyfan gwbl i RAM. Mae gennym negeseuon heb eu trefnu, pob un mewn sawl copi - wedi'r cyfan, maent i gyd yn cael eu tynnu o wahanol enghreifftiau o beiriannau testun sy'n cyfateb i ddefnyddwyr. Y nod yw didoli negeseuon a chael gwared ar gopïau sy'n cymryd lle diangen.

Mae gan bob neges stamp amser sy'n cynnwys yr amser y'i hanfonwyd a thestun. Rydyn ni'n defnyddio amser ar gyfer didoli - rydyn ni'n gosod awgrymiadau i negeseuon hynaf y cyfranogwyr aml-sgwrs ac yn cymharu hashes o destun y copïau arfaethedig, gan symud tuag at gynyddu'r stamp amser. Mae'n rhesymegol y bydd gan y copïau yr un hash a stamp amser, ond yn ymarferol nid yw hyn bob amser yn wir. Fel y cofiwch, PHP a gyflawnwyd cydamseru yn yr hen gynllun - ac mewn achosion prin, roedd amser anfon yr un neges yn amrywio ymhlith gwahanol ddefnyddwyr. Yn yr achosion hyn, roeddem yn caniatáu i ni ein hunain olygu'r stamp amser - fel arfer o fewn eiliad. Yr ail broblem yw trefn wahanol negeseuon ar gyfer derbynwyr gwahanol. Mewn achosion o'r fath, fe wnaethom ganiatáu i gopi ychwanegol gael ei greu, gyda gwahanol opsiynau archebu ar gyfer gwahanol ddefnyddwyr.

Ar ôl hyn, anfonir data am negeseuon aml-sgwrs i'r peiriant defnyddiwr. Ac yma daw nodwedd annymunol o negeseuon a fewnforiwyd. Mewn gweithrediad arferol, mae negeseuon sy'n dod i'r injan yn cael eu harchebu'n gaeth mewn trefn esgynnol gan user_local_id. Collodd negeseuon a fewnforiwyd o'r hen injan i'r injan-defnyddiwr yr eiddo defnyddiol hwn. Ar yr un pryd, er hwylustod profi, mae angen i chi allu cyrchu atynt yn gyflym, chwilio am rywbeth ynddynt ac ychwanegu rhai newydd.

Rydym yn defnyddio strwythur data arbennig i storio negeseuon a fewnforiwyd.

Mae'n cynrychioli fector o faint Ailysgrifennu cronfa ddata negeseuon VKontakte o'r dechrau a goroesille mae pawb Ailysgrifennu cronfa ddata negeseuon VKontakte o'r dechrau a goroesi - yn wahanol ac yn drefnus mewn trefn ddisgynnol, gyda threfn arbennig o elfennau. Ym mhob segment gyda mynegeion Ailysgrifennu cronfa ddata negeseuon VKontakte o'r dechrau a goroesi elfennau yn cael eu didoli. Mae chwilio am elfen mewn strwythur o'r fath yn cymryd amser Ailysgrifennu cronfa ddata negeseuon VKontakte o'r dechrau a goroesi drwy Ailysgrifennu cronfa ddata negeseuon VKontakte o'r dechrau a goroesi chwiliadau deuaidd. Mae ychwanegu elfen yn cael ei amorteiddio drosodd Ailysgrifennu cronfa ddata negeseuon VKontakte o'r dechrau a goroesi.

Felly, gwnaethom ddarganfod sut i drosglwyddo data o hen beiriannau i rai newydd. Ond mae'r broses hon yn cymryd sawl diwrnod - ac mae'n annhebygol y bydd ein defnyddwyr yn rhoi'r gorau i'r arfer o ysgrifennu at ei gilydd yn ystod y dyddiau hyn. Er mwyn peidio â cholli negeseuon yn ystod y cyfnod hwn, rydym yn newid i gynllun gwaith sy'n defnyddio clystyrau hen a newydd.

Ysgrifennir data at aelodau sgwrsio a pheiriant defnyddwyr (ac nid i'r peiriant testun, fel sy'n digwydd yn arferol yn ôl yr hen gynllun). dirprwy user-engine y cais i chat-engine - ac yma mae'r ymddygiad yn dibynnu a yw'r sgwrs hon eisoes wedi'i chyfuno ai peidio. Os nad yw'r sgwrs wedi'i huno eto, nid yw'r peiriant sgwrsio yn ysgrifennu'r neges iddo'i hun, ac mae ei brosesu yn digwydd yn y peiriant testun yn unig. Os yw'r sgwrs eisoes wedi'i chyfuno â chat-engine, mae'n dychwelyd chat_local_id i user-engine ac yn anfon y neges at yr holl dderbynwyr. dirprwyon defnyddiwr-injan yr holl ddata i'r peiriant testun - felly os bydd rhywbeth yn digwydd, gallwn bob amser rolio'n ôl, gyda'r holl ddata cyfredol yn yr hen injan. mae text-engine yn dychwelyd user_local_id, y mae user-engine yn ei storio ac yn dychwelyd i'r backend.
Ailysgrifennu cronfa ddata negeseuon VKontakte o'r dechrau a goroesi
O ganlyniad, mae'r broses bontio yn edrych fel hyn: rydym yn cysylltu clystyrau peiriannau-defnyddiwr a pheiriannau sgwrsio gwag. Mae chat-engine yn darllen y binlog sgwrsio-aelodau cyfan, yna mae dirprwyo yn dechrau yn unol â'r cynllun a ddisgrifir uchod. Rydym yn trosglwyddo'r hen ddata ac yn cael dau glwstwr cydamserol (hen a newydd). Y cyfan sydd ar ôl yw newid darllen o beiriant testun i beiriant defnyddiwr ac analluogi dirprwyo.

Canfyddiadau

Diolch i'r dull newydd, mae holl fetrigau perfformiad y peiriannau wedi'u gwella ac mae problemau gyda chysondeb data wedi'u datrys. Nawr gallwn weithredu nodweddion newydd yn gyflym mewn negeseuon (ac rydym eisoes wedi dechrau gwneud hyn - fe wnaethom gynyddu nifer uchaf y cyfranogwyr sgwrsio, gweithredu chwiliad am negeseuon a anfonwyd ymlaen, lansio negeseuon wedi'u pinio a chodi'r terfyn ar gyfanswm nifer y negeseuon fesul defnyddiwr) .

Mae'r newidiadau mewn rhesymeg yn wirioneddol enfawr. A hoffwn nodi nad yw hyn bob amser yn golygu blynyddoedd cyfan o ddatblygiad gan dîm enfawr a myrdd o linellau o god. chat-engine a user-engine ynghyd â'r holl straeon ychwanegol fel Huffman ar gyfer cywasgu neges, coed Splay a strwythur ar gyfer negeseuon a fewnforiwyd yn llai na 20 mil o linellau o god. Ac fe'u hysgrifennwyd gan 3 datblygwr mewn dim ond 10 mis (fodd bynnag, mae'n werth cadw hynny mewn cof holl 3 datblygwr - pencampwyr y byd mewn rhaglenni chwaraeon).

Ar ben hynny, yn lle dyblu nifer y gweinyddwyr, fe wnaethom leihau eu nifer i hanner - nawr mae'r peiriant defnyddiwr a'r peiriant sgwrsio yn byw ar 500 o beiriannau corfforol, tra bod gan y cynllun newydd uchdwr mawr ar gyfer llwyth. Fe wnaethon ni arbed llawer o arian ar offer - tua $5 miliwn + $750 mil y flwyddyn mewn costau gweithredu.

Rydym yn ymdrechu i ddod o hyd i'r atebion gorau ar gyfer y problemau mwyaf cymhleth a mawr. Mae gennym ni ddigonedd ohonyn nhw - a dyna pam rydyn ni'n chwilio am ddatblygwyr dawnus yn yr adran gronfa ddata. Os ydych chi'n caru ac yn gwybod sut i ddatrys problemau o'r fath, yn meddu ar wybodaeth ragorol am algorithmau a strwythurau data, rydym yn eich gwahodd i ymuno â'r tîm. Cysylltwch â'n HRam fanylion.

Hyd yn oed os nad yw'r stori hon yn ymwneud â chi, nodwch ein bod yn gwerthfawrogi argymhellion. Dywedwch wrth ffrind am swyddi gwag datblygwyr, ac os bydd yn cwblhau'r cyfnod prawf yn llwyddiannus, byddwch yn derbyn bonws o 100 mil rubles.

Ffynhonnell: hab.com

Ychwanegu sylw