Redis "CROSSSLOT Keys in request don't hash to the same slot" ir kļūda, ko saņemat, kad viena komanda, transakcija vai skripts skar atslēgas, kas atrodas dažādos Redis Cluster hash slotos. Vienā instancē tas pats kods strādā. Klasterī atslēgas ir sadalītas pa mezgliem, un Redis atsakās izpildīt operācijas ar vairākām atslēgām, kuras tas nevar atomāri izpildīt vienā mezglā. Valkey Cluster atgriež tieši tādu pašu ziņojumu.
Kāpēc šī kļūda pastāv
Redis Cluster specifikācija sadala atslēgu telpu 16384 hash slotos, HASH_SLOT = CRC16(key) mod 16384. Katram primārajam mezglam pieder daļa slotu. Komanda, piemēram, MGET a b, ir droša tikai tad, ja abas atslēgas ir vienā mezglā, un Redis to pārbauda slotu līmenī: visām pieprasījuma atslēgām jāatbilst vienam slotam, nevis tikai vienam mezglam. Ja tā nav, mezgls atbild ar CROSSSLOT un neko neizpilda.
127.0.0.1:7000> MGET user:1000:name user:1001:name
(error) CROSSSLOT Keys in request don't hash to the same slot
127.0.0.1:7000> CLUSTER KEYSLOT user:1000:name
(integer) ...
127.0.0.1:7000> CLUSTER KEYSLOT user:1001:name
(integer) ... # a different slot
Kur tā parādās
- Komandas ar vairākām atslēgām:
MGET,MSET,DELvaiUNLINKar vairākām atslēgām,SUNIONSTORE,SINTER,RENAME,ZUNIONSTOREun līdzīgas. - Transakcijas. Klastera režīmā Redis pārbauda visas rindā ieliktās komandas, kad pienāk
EXEC. Pirmkodā redzams, ka transakcija, kuras komandas skar dažādus slotus, saņem CROSSSLOT un tiek atmesta, tāpēc nekas no tās neizpildās. - Lua skripti un funkcijas. Dokumentācija prasa, lai katra atslēga, ko skripts izmanto, tiktu nodota kā atslēgas arguments, un deklarētajām atslēgām vienmēr jāhešojas uz vienu slotu. Funkcijas un skripti ar shebang galveni pēc noklusējuma arī nevar skart nedeklarētas atslēgas no citiem slotiem; tie neizdodas ar "Script attempted to access keys that do not hash to the same slot". Vecā stila
EVALskripti bez shebang ir iecietīgāki, bet atslēga, ko apkalpo cits mezgls, joprojām izraisa kļūdu. - Klienta pipeline. Pipeline nav atomārs, un labi klastera klienti katru komandu nosūta uz tās mezglu, tāpēc pipeline parasti CROSSSLOT neizraisa. Transakcijas un komandas ar vairākām atslēgām tajos gan izraisa.
Risinājums: hash tagi
Hash tags liek Redis hešot tikai daļu atslēgas. Specifikācija dod precīzus noteikumus: ja atslēgā ir {, pa labi no tās ir } un starp pirmo { un pirmo sekojošo } ir vismaz viena rakstzīme, tad hešo tikai šo apakšvirkni.
{user:1000}.name -> hešo "user:1000"
{user:1000}.cart -> hešo "user:1000" (tas pats slots)
foo{}{bar} -> hešo visu atslēgu (pirmais tags tukšs)
foo{{bar}}zap -> hešo "{bar"
foo{bar}{zap} -> hešo "bar" (skaitās tikai pirmais tags)
Tāpēc tipisks labojums ir ielikt entītijas ID figūriekavās tām atslēgām, kuras jāizmanto kopā:
# pirms: atslēgas nonāk nejaušos slotos
MSET user:1000:name Anna user:1000:email anna@example.com
# pēc: viens hash tags, viens slots, MSET klasterī strādā
MSET {user:1000}:name Anna {user:1000}:email anna@example.com
# pārbaudiet pirms izlaišanas
CLUSTER KEYSLOT {user:1000}:name
CLUSTER KEYSLOT {user:1000}:email
CLUSTER KEYSLOT parāda slotu jebkuram atslēgas nosaukumam. Ielieciet to testā, lai pārdēvēta atslēga vēlāk klusi nesalauztu transakciju.
Citi risinājumi
- Sadaliet pieprasījumu pa slotiem. Ja atomaritāte nav vajadzīga, izpildiet vienu komandu katram slotam. Daži klienti to dara jūsu vietā; piemēram, redis-py klastera klientam ir
mget_nonatomicunmset_nonatomic, kas sagrupē atslēgas pa slotiem un katram slotam sūta vienuMGETvaiMSET. Nosaukums ir godīgs: rezultāts vairs nav atomārs. - Pārdomājiet datu modeli. Vairākas atslēgas, kas vienmēr mainās kopā, bieži labāk glabāt vienā hash. Lietotāja profilam
HSET {user:1000} name ... email ...atomaritāte starp atslēgām vispār nav vajadzīga. - Skripta karogs
allow-cross-slot-keys. Redis 7+ skripti un funkcijas var deklarēt šo karogu, lai piekļūtu nedeklarētām atslēgām no vairākiem slotiem. Dokumentācijā teikts, ka deklarētajām atslēgām joprojām jāhešojas uz vienu slotu, un piekļuve vairākiem slotiem nav ieteicama; pirmkodā atslēga, ko apkalpo cits mezgls, joprojām izraisa kļūdu. Uztveriet to kā migrācijas palīglīdzekli, nevis dizainu.
{app}: uz katras atslēgas nosūta visu datu kopu vienā slotā, tāpēc viens mezgls glabā visu un saņem visu slodzi. Klasteris joprojām darbojas, bet jūs esat atpakaļ pie viena servera, tikai ar papildu sarežģītību.Hash tagi lielās datu kopās
- Slotu nevar sadalīt. Visas atslēgas ar vienu tagu atrodas vienā slotā, un slots vienmēr pieder vienam primārajam mezglam. Ja viens klients vai viens tags izaug līdz desmitiem GB, šim mezglam atmiņa beidzas pirmajam, un mezglu pievienošana nepalīdz. Izvēlieties tagu, kas katru grupu notur mazu, piemēram, lietotāja vai pasūtījuma ID, nevis klientu organizāciju vai valsti.
- Karsti sloti nozīmē karstus mezglus. Pat ar vienmērīgu atmiņu populārs tags koncentrē CPU un tīkla slodzi uz vienu mezglu. Sekojiet operācijām un atmiņai katrā mezglā un salīdziniet mezglus ar
redis-cli --cluster infounCLUSTER COUNTKEYSINSLOT. - Pārdalīšana pārvieto veselus slotus. Slota ar miljoniem atslēgu vai ļoti lielām atslēgām migrācija prasa laiku un noslogo abus mezglus. Saskaņā ar specifikāciju migrācijas laikā operācijas ar vairākām atslēgām, kas sadalītas starp avota un mērķa mezglu vai neeksistē, saņem
-TRYAGAIN. Klientiem tam vajadzīgs atkārtošanas ceļš, un lieli sloti šajā stāvoklī paliek ilgāk. - Plānojiet migrāciju no atsevišķas Redis instances. Pirms lielas instances pārcelšanas uz klasteri (vai no Redis uz Valkey Cluster, skatiet mūsu Redis uz Valkey migrācijas ceļvedi) atrodiet kodā visas komandas ar vairākām atslēgām, transakcijas un skriptus. Tad izlemiet par tagiem un pārdēvējiet atslēgas. Pārdēvēt atslēgas vēlāk dzīvā vairāku GB klasterī ir daudz grūtāk nekā migrācijas laikā.
- Testējiet ar produkcijai līdzīgu atslēgu skaitu. Nevienmērīgi sloti un ilgas migrācijas parādās tikai ar reālu atslēgu sadalījumu un reāliem atslēgu izmēriem.
Ja klasteris pats pārstāj apkalpot slotus, tā ir cita problēma: skatiet mūsu ceļvedi par Redis CLUSTERDOWN.
Galvenās atziņas
- CROSSSLOT nozīmē, ka viena komanda, transakcija vai skripts skāra atslēgas dažādos hash slotos; Redis un Valkey Cluster to atsaka.
- Labojiet ar hash tagiem: hešo tikai tekstu pirmajās netukšajās
{...}; pārbaudiet arCLUSTER KEYSLOT. - Ja atomaritāte nav vajadzīga, sadaliet pieprasījumus pa slotiem; apsveriet hash vairāku saistītu atslēgu vietā.
- Nekad neizmantojiet vienu konstantu tagu visām atslēgām; tagojiet pēc mazas entītijas, piemēram, lietotāja vai pasūtījuma ID.
- Lielās datu kopās sekojiet pārāk lieliem vai karstiem slotiem un rēķinieties ar TRYAGAIN komandām ar vairākām atslēgām pārdalīšanas laikā.