Otetaan tietokanta, jossa on esimerkiksi 600 miljoonaa riviä.
Data kopioidaan uuteen Google Cloud -ympäristöön. Työ valmistuu ja tarkistuksessa nähdään, että rivejä on suunnilleen sama määrä.
Tässä vaiheessa on helppo ajatella, että suurin työ on tehty.
Ei välttämättä.
Jos kopiointi kesti 14 tuntia, vanha järjestelmä ehti muuttua koko tuon ajan.
Ensimmäisen tunnin aikana syntyneet uudet rivit eivät välttämättä kuulu enää alkuperäiseen kopioon. Päivityksiä on voinut tulla samaan aikaan. Jotkin tietueet on ehkä poistettu.
Sama koskee järjestelmiä, jotka kirjoittavat tietokantaan automaattisesti.
ERP voi päivittää varastosaldoja. Maksupalvelu voi palauttaa maksun tilan. Integraatio voi lisätä uuden asiakkaan. Taustalla ajettava prosessi voi muuttaa tuhansia rivejä ilman, että yksikään ihminen koskee sovellukseen.
Siksi migraation ensimmäinen täysi datakopio on oikeastaan vain lähtötilanne.
Sen jälkeen pitää saada kiinni muutokset.
Koko tietokannan kopioiminen uudelleen ei yleensä ole järkevä tapa ratkaista asiaa.
Jos 600 miljoonasta rivistä muuttuu päivän aikana 200 000, ei ole mitään erityistä hyötyä siitä, että kaikki 600 miljoonaa siirretään taas kerran.
Tarvitaan tapa tunnistaa muuttunut osa.
Yksinkertaisessa järjestelmässä se voi olla esimerkiksi updated_at-kenttä.
Ajatuksena on silloin:
hae kaikki rivit, jotka ovat muuttuneet viimeisen onnistuneen synkronoinnin jälkeen.
Tämä toimii niin kauan kuin kenttä on luotettava.
Ja siinä tulee vastaan ensimmäinen käytännön ongelma.
Kaikissa vanhoissa järjestelmissä ei ole kunnollista muutosleimaa. Joissakin tauluissa päivämäärä voi tarkoittaa liiketoiminnan tapahtuma-aikaa eikä viimeistä teknistä muutosta. Joissakin päivityksissä kenttä ei päivity ollenkaan.
Silloin updated_at näyttää hyvältä ratkaisulta arkkitehtuurikaaviossa, mutta tuotannossa se voi jättää osan muutoksista huomaamatta.
Tämä unohtuu yllättävän helposti.
Jos asiakas lisätään lähdejärjestelmään, uusi rivi voidaan siirtää kohdejärjestelmään.
Jos asiakas päivitetään, muutos voidaan siirtää.
Mutta mitä tapahtuu, kun asiakas poistetaan?
Jos synkronointi seuraa vain uusia ja päivitettyjä rivejä, kohdejärjestelmään voi jäädä vanha tietue.
Tämän seurauksena vanha ja uusi ympäristö näyttävät aluksi hyvin samanlaisilta. Ero syntyy hiljalleen.
Poistot pitää siis käsitellä samalla tavalla kuin muutkin muutokset.
Joissakin järjestelmissä fyysistä poistoa ei tehdä lainkaan, vaan käytetään esimerkiksi deleted_at-kenttää tai muuta soft delete -mallia. Silloin tilanne on helpompi, mutta myös tässä pitää tietää, mikä tieto siirretään ja milloin.
Tämä on niitä asioita, joita on vaikea huomata tavallisessa testissä.
Kuvitellaan, että asiakkaan tilaus luodaan.
Ensin syntyy:
order_created
Sen jälkeen asiakas peruu tilauksen:
order_cancelled
Jos molemmat tapahtumat päätyvät kohdejärjestelmään oikeassa järjestyksessä, kaikki näyttää hyvältä.
Mutta jos peruuttaminen käsitellään ennen luontia, tulos voi olla aika outo.
Tapahtumapohjaisessa arkkitehtuurissa ei siis riitä, että viesti “saapui”.
Pitää tietää, mitä tapahtuma tarkoittaa ja voiko sen käsitellä tässä vaiheessa.
Tämä on yksi syy siihen, miksi tapahtumilla käytetään usein versionumeroita, järjestysnumeroita tai muuta tietoa, jonka perusteella vastaanottaja pystyy päättelemään, onko muutos vielä ajantasainen.
Google Cloudin Pub/Sub sopii hyvin tähän kokonaisuuteen.
Se voi välittää tapahtumia palvelusta toiseen ilman, että lähettäjän ja vastaanottajan pitää olla samaan aikaan suorassa yhteydessä.
Mutta Pub/Sub ei tiedä, onko esimerkiksi asiakkaan osoitteen muuttaminen sallittua.
Se ei tiedä, onko tilaus jo olemassa.
Se ei tiedä, pitääkö tapahtuma käsitellä ennen jotain toista tapahtumaa.
Nämä päätökset tehdään sovelluksessa.
Siksi arkkitehtuurissa kannattaa pitää eri asiat erillään:
tapahtuman kuljetus on yksi asia.
tapahtuman käsittely on toinen.
datan oikeellisuuden varmistaminen on kolmas.
Kun nämä kaikki niputetaan yhdeksi “synkronoinniksi”, ongelman tutkiminen muuttuu nopeasti hankalaksi.
Tämä on ehkä yksi kiinnostavimmista puolista datamigraatiossa.
Joskus uusi Google Cloud -ympäristö ei oikeastaan ole ongelman aiheuttaja.
Migraatio vain paljastaa asian, joka oli vanhassa järjestelmässä jo pitkään.
Esimerkiksi samalle asiakkaalle voi löytyä kolme eri tunnistetta.
Yhdessä järjestelmässä:
12345
Toisessa:
C-12345
Kolmannessa:
0012345
Kun kaikki olivat vuosia erillään, asia ei välttämättä aiheuttanut suurta ongelmaa.
Migraatiossa järjestelmät yhdistetään.
Yhtäkkiä pitää tietää, ovatko nämä kolme sama henkilö vai kolme eri asiakasta.
Tätä ei ratkaista Google Cloudin asetuksilla.
Se on datan laadun ja liiketoimintasääntöjen kysymys.
Tätä tapahtuu helposti.
Testitietokannassa on 50 000 asiakasta.
Tuotannossa on 8 miljoonaa.
Kehitysympäristössä synkronointi näyttää toimivan nopeasti. Tuotannossa sama prosessi alkaa muodostaa tuntien viivettä.
Syy voi olla niinkin yksinkertainen kuin se, että kyselyt, indeksit ja käsittelylogiikka eivät käyttäydy samalla tavalla suurella datamäärällä.
Myös tapahtumamäärä vaikuttaa.
Jos kehitysympäristössä syntyy sata tapahtumaa minuutissa ja tuotannossa 20 000, kuluttajan suorituskyky pitää mitoittaa aivan eri tavalla.
Tämän takia migraation testaamisessa ei pitäisi katsoa vain sitä, meneekö yksi tapahtuma onnistuneesti läpi.
Pitää nähdä myös, miten järjestelmä käyttäytyy kuormassa.
Vanha tietokanta voi olla täynnä historiaa, jota uusi sovellus ei koskaan käytä.
Vuosien vanhat lokit.
Arkistoidut tilaukset.
Väliaikaiset taulut.
Poistetut käyttäjät.
Vanha integraatiodata.
Jos kaikki siirretään automaattisesti, uusi ympäristö saa kaiken mukana.
Se voi olla turhaa.
Joskus parempi ratkaisu on siirtää aktiivinen data uuteen tietokantaan ja säilyttää vanhempi aineisto erillisessä tallennuksessa tai arkistossa.
Tämä ei ole pelkästään kustannuskysymys.
Suuri määrä tarpeetonta dataa vaikuttaa myös indekseihin, varmistuksiin, kyselyihin ja siihen, kuinka helposti järjestelmän sisältöä pystytään myöhemmin ymmärtämään.
Jos tapahtuma ei onnistu useista yrityksistä huolimatta, se voidaan siirtää erilliseen käsittelyjonoon.
Google Cloudin Pub/Subissa tähän voidaan käyttää dead-letter topic -ratkaisua.
Se on hyödyllinen mekanismi.
Mutta helposti syntyy ajatus, että ongelma on ratkaistu, kun epäonnistunut viesti siirtyy dead-letteriin.
Ei ole.
Nyt ongelma on vain siirretty paikkaan, josta joku tarvitsee löytää sen.
Jos siellä on 30 000 viestiä eikä kukaan tiedä, miksi ne epäonnistuivat, järjestelmä ei ole kovin hyvässä kunnossa.
Dead-letter-ratkaisun ympärille tarvitaan seuranta ja prosessi: kuka tutkii virheet, miten yksittäinen tapahtuma korjataan ja voidaanko se ajaa uudelleen turvallisesti.
Tähän pitäisi olla mitattava vastaus.
Ei:
“Näyttää siltä, että synkronointi toimii.”
Vaan esimerkiksi:
“Kohdejärjestelmä on tällä hetkellä 4,2 sekuntia lähdejärjestelmää jäljessä.”
Tai:
“Jonossa on 182 käsittelemätöntä tapahtumaa.”
Näistä voidaan tehdä metriikoita ja hälytyksiä.
Jos viive normaalisti pysyy alle kymmenessä sekunnissa mutta nousee viiteen minuuttiin, siitä pitäisi saada tieto ennen kuin käyttäjä huomaa ongelman.
Tässä kohtaa Google Cloudin seuranta- ja lokityökalut ovat hyödyllisiä. Mutta jälleen kerran tärkeintä ei ole työkalun nimi.
Tärkeintä on päättää etukäteen, mikä arvo tarkoittaa ongelmaa.
Tässä vaiheessa moni migraatiokaavio näyttää liian yksinkertaiselta.
Liikenne siirtyy uuteen järjestelmään.
Sitten huomataan ongelma.
Palataan vanhaan.
Mutta mitä tapahtuu kaikille niille muutoksille, jotka tehtiin uuden järjestelmän ollessa käytössä?
Jos asiakas teki uuden tilauksen, vaihtoi osoitettaan ja perui yhden vanhan tilauksen, vanhan järjestelmän pitää saada nämä muutokset ennen kuin sitä voidaan käyttää uudelleen.
Muuten rollback palauttaa kyllä sovelluksen, mutta vanhaan dataan.
Siksi palautussuunnitelma pitää tehdä datan näkökulmasta, ei vain infrastruktuurin näkökulmasta.
Kun vanha ja uusi ympäristö elävät rinnakkain, on hyvä päättää mahdollisimman tarkasti, kumpi järjestelmä saa kirjoittaa mitäkin.
Jos molemmat voivat muuttaa samaa asiakastietoa, ristiriitojen määrä kasvaa nopeasti.
Parempi malli voi olla esimerkiksi se, että uusi järjestelmä omistaa asiakasprofiilin, mutta vanha ERP saa edelleen hallita laskutustietoja.
Silloin tiedetään, missä muutos syntyy.
Synkronointi ei yritä ratkaista kaikkea kaikkeen.
Tämä voi kuulostaa enemmän järjestelmäarkkitehtuurilta kuin datamigraatiolta. Käytännössä nämä asiat ovat kuitenkin tiukasti sidoksissa toisiinsa.