väärä tapa skaalata Cassandra DB: tä, kun toissijaiset indeksit ovat käytössä
Cassandra on suosikkini (ei hallinnoitu) tietokannasta monesta syystä: sillä ei ole yhtä vikapistettä (SPoF), se tukee useita alueita, se on hyvä lukea ja kirjoittaa ops, joustava luku-ja kirjoitustasoista, asteikot lineaarisesti eikä liian monimutkainen päivittäisten toimintojen hallintaan.
kuten jokainen tietokanta, sinun tulisi käyttää Cassandraa tietojen käyttömallien perusteella, joten jos tarvitset joustavaa tietokantaa ad-hoc-kyselyjä varten tai riittävän mukautuvaa jatkuvasti tietokantamallimuutoksia varten, kannattaa harkita muita vaihtoehtoja.
Cassandra on pylväspainotteinen DB ja se on todella tehokas, kun datakyselyt on jo määritelty. Datastax, yritys, joka tukee Cassandra, suosittelee sinun pitäisi aloittaa suunnittelemalla kyselyt ja sitten tietomalli Cassandra. Huolimatta columnar-rakenteesta Cassandra tukee monia tietorakenteita pylvästyyppinä, kuten karttoja.
Cassandra on ensisijainen avaintietokanta, mikä tarkoittaa, että tietosi on säilytetty ja järjestetty klusterin ympärille ensisijaisen avaimen hajautusarvon (partition key) perusteella. Taulukoita, joissa on enemmän kuin yksi PK, Cassandra katsoo vain ensimmäinen osa PK kuin se osio avain. Katso lisää komposiittiavaimista täältä.
selvyyden vuoksi palataan yhteen Cassandra DB: n tärkeimmistä ominaisuuksista: se on arkkitehtuuria ja sitä, että siinä ei ole Spofia.
Cassandran klusterin muodostavat solmut (3 tai enemmän) ja nämä solmut muodostavat yhdessä solmujen renkaan:
jokainen Cassandran klusterin solmu toimii “itsenäisesti”, mutta eri solmut voisivat tallentaa samat tiedot vastaavasti klusterille asetetun replikaatiokertoimen (RF) konfiguraation mukaisesti.
tietääkseen, missä (missä solmussa) tietosi säilyvät, Cassandra käyttää hash-arvoa (tokenia), joka on laskettu johdonmukaisen hash-funktion kautta käyttäen tietyn taulukon PK-saraketta.
kun suoritat kyselyn, koordinaattorisolmu (yleensä lähin sovellusesimerkkisi) etsii, mitkä solmut renkaassa sisältävät tietosi. jos yksi solmu on jostain syystä alhaalla, toinen solmu voi palvella tietojasi (RF ≥2). Se on taikaa mestarillisesta lähestymistavasta, jossa jokainen solmu kehässä on yhtä suuri lukemisessa ja kirjoittamisessa.
tämä PK: ta ja replikaatiotekijää koskeva käsite on erittäin tärkeä ymmärtää, miten Cassandra-klusteri skaalataan, kun sovellus on suuren kuormituksen olosuhteissa.
sekundaariset indeksit
Cassandralla on myös käsite sekundaariset indeksit. Relaatiotietokannoissa voisi olla monta indeksiä tietyssä taulukossa, kustannukset ovat toissijainen indeksi liittyy kirjoittaa operaatioita, ei lukea operaatioita. Cassandrassa tämä ei pidä paikkaansa.
Cassandran toissijaiset indeksit voivat olla hyödyllisiä ja houkuttelevia, kun tietomallisi vaihtuu ja joudut tekemään kyselyn uuden sarakkeen perusteella.
näin, toissijaisella indeksillä, voit suorittaa kyselyn näin:
valitse * FROM my_table WHERE SECONDARY_INDEX = ‘value’;
ongelma toissijaisen indeksin
käyttämisestä Kuvittele skenaario: olet Blackfriday / CyberMonday ja Cassandra-klusterisi kärsii huipputapahtumista ja sinun täytyy lisätä enemmän solmuja skaalataksesi tietokantaasi, tasapainottaaksesi paremmin liikennettä ja … selviytyäksesi. Eikö olekin hyvä?
normaalisti se on normaalitilanne erittäin skaalautuvassa sovelluksessa. Mutta entä jos sovellus suorittaa kyselyjä toissijaisen indeksin avulla?
joo, perille meni.
Muistatko, kun sanoin, että Cassandra jakaa dataa kehässä osioavaimen avulla? Tämä tapahtuu jo, mutta ongelma on, kun otat toisen indeksin käyttöön kyselyssäsi. Toissijaiset indeksit eivät ole osa osioavainta, ja Cassandra tietää osioavaimen kautta, missä tietosi elävät. Kun suoritat kyselyn, joka käyttää tällaista indeksiä, Cassandra etsii jokaista rengassolmua yrittäen tyydyttää kyselysi.
todellinen skenaario
Blackfridayn aikana hakemuksemme olivat suurella kuormituksella. Monet ja monet asiakkaat haluavat hyötyä valtavia alennuksia tarjoamia Blackfriday tapahtuma.
tarkastelimme APM: ää ja kaikki analyysi johti meidät sinnikkyyteen, tässä tapauksessa Cassandra DB: hen. Meillä on pitkiä viiveitä, mutta ei joka pyynnöstä, vain joidenkin.
yrittäessämme pitää asiat taas normaalitilassa, ensimmäinen liikkeemme oli lisätä lisää solmuja Cassandra-rykelmäämme.
lisäsimme ja kärsimme edelleen latenssiongelmista. Kysymys kuului: miksi näin edelleen tapahtuu?
olimme väärässä. Se oli yksinkertainen johtopäätös, emmekä kiinnittäneet huomiota yhteen hyvin tärkeään yksityiskohtaan: tällaista käytöstä ei tapahtunut kaikissa pyynnöissä, vaan joissakin niistä.
jos mietit toissijaista indeksiä, bingo! Juuri se oli ongelma.
solmujen lisääminen ei koskaan ratkaisisi ongelmaa, koska ongelma ei liittynyt kaikkiin tietokantaan saapuviin kyselyihin, ongelma oli joissakin ja ne olivat todellisia tietokannan suorituskykyä heikentäviä. Se oli täysin Pareton juttu.
ongelman ja sen lieventämisen yksityiskohdat
yksi hetki ennen Blackfriday-tapahtumaa meidän oli muutettava tietomalliamme. Alueellistimme sovelluksemme ja asiakkaan alue alkoi olla meille tärkeä asia, meidän piti kysellä tietoja tuotteen tai alueen perusteella.
kun katsomme taaksepäin ja yhdistämme pisteet, saatoimme ymmärtää, että olimme hyvin arvokkaita toteutuksen suhteen, koska halusimme heijastaa tätä uutta käyttäytymistä paitsi API-kerroksessa (new query param), myös tavassa, jolla pääsimme käsiksi Cassandran tietoihin.
ja miksi olimme niin arvokkaita? Koska vaikka kyselyaikamme ei kasvanut niin paljon, teimme muutoksen.
tämä toteutus ei ainoastaan lisännyt kyselyaikaamme käyttämällä toissijaista indeksiä, vaan myös tuotti lisää kysymyksiä mukaan skaalasimme Cassandran infrastruktuuria. Kuten lisäsimme enemmän solmuja meidän klusteri, tarkoitti enemmän solmuja etsiä tietoja, joten kysymys kasvoi eksponentiaalisesti.
ongelman lieventämiseksi otimme takaisin solmujen määrän, joka meillä oli aiemmin, ja lisäsimme replikaatiokerrointa suurimmalle osalle klusterin solmuista.
muutimme myös lukuainetasoamme vähemmän johdonmukaiseksi. Käytimme * päätösvaltaisuutta ja sen sijaan vaihdoimme yhteen. Tämä auttoi meitä vähentämään kuormitusta solmuissa.
kun jäädytimme hakemuksemme päiviä ennen tapahtumaa, tiesimme, ettei meillä ole uusia tietoja (kirjoitustoimintoja) ja tiedot olisivat yhdenmukaisia nykyisessä tilassaan.
päivää sen jälkeen ja DB-malliratkaisu
osana lopullista ratkaisua meidän piti (uudelleen)miettiä tietokantamalliamme ja kelata takaisin muutokset, joita teimme lieventämispolkuna tapahtuman aikana.
ennen tapahtumaa käytimme product ID: tä (PID)osioavaimena, mikä oli hyvä päätös, koska PID: llä on hyvät ominaisuudet olla PK, koska se on luonteeltaan juokseva numero (korkea kardinaalisuus) ja siten levittää tiedot tasaisesti klusterin ympärille.
uudesta kentästä “alue” hyödynsimme Cassandra collections-tietotyyppiä ja käytimme kunkin alueen karttaa sarakkeena tuotetaulukossamme.
toissijaiset indeksit ovat aina huono idea?
lyhyt vastaus on ei.
selittäen hieman paremmin, Cassandrassa on kahdenlaisia indeksejä: paikallisia ja globaaleja indeksejä.
paikallinen indeksi, kuten nimi sanoo, on eräänlainen indeksi, joka on olemassa vain paikallisesti, eli solmussa. Kun luodaan toissijainen indeksi, Cassandra luo uuden (piilotetun) taulukon, jossa toissijaisesta tulee ensisijainen avain tähän taulukkoon. Tämän uuden taulukon näkyvyys on solmun, ei renkaan (klusterin) kannalta. Tämä koskee toissijaisia indeksejä.
toisaalta globaalilla indeksillä on Ring-näkyvyys sen osionavaimen kautta, joten Cassandra tietää, missä sinun datasi on ringissä tuon osionavaimen kautta.
sekundaariset indeksit voivat olla vaihtoehto, kun kyselyssä on sekä primaariset että sekundaariset indeksit. Siinä tapauksessa, Cassandra tietää missä tietosi asuu (mikä solmu) kautta osio avain ja sitten etsii paikallisen taulukon solmu, joka viittaa (paikallinen) toissijainen indeksit.
toissijaisissa indekseissä on myös joitakin muita vivahteita, jotka tässä selitetään hyvin, mutta paras käytäntö on välttää ne denormalisoimalla tietomallisi.