ఈ ఆర్టికల్లో నేను PostgreSQL ఫాల్ట్ టాలరెన్స్ సమస్యను ఎలా సంప్రదించామో, అది మనకు ఎందుకు ముఖ్యమైనది మరియు చివరికి ఏమి జరిగిందో తెలియజేస్తాను.
మేము అధిక లోడ్ చేయబడిన సేవను కలిగి ఉన్నాము: ప్రపంచవ్యాప్తంగా 2,5 మిలియన్ల వినియోగదారులు, ప్రతిరోజూ 50K+ క్రియాశీల వినియోగదారులు. సర్వర్లు ఐర్లాండ్లోని ఒక ప్రాంతంలో అమెజాన్లో ఉన్నాయి: 100+ విభిన్న సర్వర్లు నిరంతరం పనిచేస్తాయి, వాటిలో దాదాపు 50 డేటాబేస్లు ఉన్నాయి.
మొత్తం బ్యాకెండ్ అనేది క్లయింట్తో నిరంతర వెబ్సాకెట్ కనెక్షన్ని నిర్వహించే ఒక పెద్ద ఏకశిలా స్టేట్ఫుల్ జావా అప్లికేషన్. అనేక మంది వినియోగదారులు ఒకే బోర్డ్లో ఏకకాలంలో పని చేసినప్పుడు, వారందరూ నిజ సమయంలో మార్పులను చూస్తారు, ఎందుకంటే మేము డేటాబేస్లో ప్రతి మార్పును రికార్డ్ చేస్తాము. మేము మా డేటాబేస్లకు సెకనుకు దాదాపు 10K అభ్యర్థనలను కలిగి ఉన్నాము. Redisలో పీక్ లోడ్ వద్ద మేము సెకనుకు 80-100K అభ్యర్థనలను వ్రాస్తాము.
మేము Redis నుండి PostgreSQLకి ఎందుకు మారాము
ప్రారంభంలో, మా సేవ Redisతో పని చేసింది, ఇది సర్వర్ యొక్క RAMలో మొత్తం డేటాను నిల్వ చేసే కీలక-విలువ నిల్వ.
రెడిస్ యొక్క ప్రయోజనాలు:
- అధిక ప్రతిస్పందన వేగం, ఎందుకంటే ప్రతిదీ మెమరీలో నిల్వ చేయబడుతుంది;
- అనుకూలమైన బ్యాకప్ మరియు ప్రతిరూపణ.
మాకు Redis యొక్క ప్రతికూలతలు:
- అసలు లావాదేవీలు లేవు. మేము మా అప్లికేషన్ స్థాయిలో వాటిని అనుకరించడానికి ప్రయత్నించాము. దురదృష్టవశాత్తూ, ఇది ఎల్లప్పుడూ బాగా పని చేయదు మరియు చాలా క్లిష్టమైన కోడ్ను వ్రాయడం అవసరం.
- డేటా మొత్తం మెమరీ పరిమాణంతో పరిమితం చేయబడింది. డేటా మొత్తం పెరిగేకొద్దీ, మెమరీ పెరుగుతుంది మరియు చివరికి, మేము ఎంచుకున్న ఉదాహరణ యొక్క లక్షణాల్లోకి ప్రవేశిస్తాము, ఇది AWSలో ఉదాహరణ రకాన్ని మార్చడానికి మా సేవను నిలిపివేయడం అవసరం.
- తక్కువ జాప్యం స్థాయిని నిరంతరం నిర్వహించడం అవసరం, ఎందుకంటే మాకు చాలా పెద్ద సంఖ్యలో అభ్యర్థనలు ఉన్నాయి. మాకు సరైన జాప్యం స్థాయి 17-20 ms. 30-40 ms స్థాయిలో, మేము మా అప్లికేషన్ అభ్యర్థనలు మరియు సేవ క్షీణతకు సుదీర్ఘ ప్రతిస్పందనలను పొందుతాము. దురదృష్టవశాత్తూ, సెప్టెంబరు 2018లో మాకు ఇది జరిగింది, కొన్ని కారణాల వల్ల రెడిస్తో ఒక సందర్భం సాధారణం కంటే 2 రెట్లు ఎక్కువ జాప్యాన్ని పొందింది. సమస్యను పరిష్కరించడానికి, మేము షెడ్యూల్ చేయని నిర్వహణ కోసం పని రోజు మధ్యలో సేవను నిలిపివేసాము మరియు సమస్యాత్మకమైన Redis ఉదాహరణను భర్తీ చేసాము.
- కోడ్లో చిన్న చిన్న ఎర్రర్లతో కూడా అస్థిరమైన డేటాను పొందడం సులభం మరియు ఆ డేటాను పరిష్కరించడానికి చాలా సమయం కోడ్ రాయడం కోసం వెచ్చించవచ్చు.
మేము ప్రతికూలతలను పరిగణనలోకి తీసుకున్నాము మరియు సాధారణ లావాదేవీలు మరియు జాప్యంపై తక్కువ ఆధారపడటంతో మేము మరింత అనుకూలమైన వాటికి వెళ్లాల్సిన అవసరం ఉందని గ్రహించాము. మేము మా పరిశోధన చేసాము, అనేక ఎంపికలను విశ్లేషించాము మరియు PostgreSQLని ఎంచుకున్నాము.
మేము ఇప్పుడు 1,5 సంవత్సరాలుగా కొత్త డేటాబేస్కు తరలిస్తున్నాము మరియు డేటాలో కొంత భాగాన్ని మాత్రమే బదిలీ చేసాము, కాబట్టి ఇప్పుడు మేము Redis మరియు PostgreSQLతో ఏకకాలంలో పని చేస్తున్నాము. డేటాబేస్ల మధ్య డేటాను తరలించే మరియు మారే దశల గురించి మరింత సమాచారం వ్రాయబడింది
మేము మొదట తరలించడం ప్రారంభించినప్పుడు, మా అప్లికేషన్ నేరుగా డేటాబేస్తో పని చేసింది మరియు Redis మరియు PostgreSQL మాస్టర్ను యాక్సెస్ చేసింది. PostgreSQL క్లస్టర్లో మాస్టర్ మరియు అసమకాలిక ప్రతిరూపణతో కూడిన ప్రతిరూపం ఉన్నాయి. డేటాబేస్ వర్క్ఫ్లో ఇలా ఉంది:
PgBouncerని అమలు చేస్తోంది
మేము తరలిస్తున్నప్పుడు, ఉత్పత్తి కూడా అభివృద్ధి చెందుతోంది: PostgreSQLతో పని చేసే వినియోగదారుల సంఖ్య మరియు సర్వర్ల సంఖ్య పెరిగింది మరియు మేము కనెక్షన్లు అయిపోవడం ప్రారంభించాము. PostgreSQL ప్రతి కనెక్షన్ కోసం ఒక ప్రత్యేక ప్రక్రియను సృష్టిస్తుంది మరియు వనరులను వినియోగిస్తుంది. మీరు ఒక నిర్దిష్ట పాయింట్ వరకు కనెక్షన్ల సంఖ్యను పెంచవచ్చు, లేకుంటే డేటాబేస్ ఉత్తమంగా పని చేయని అవకాశం ఉంది. అటువంటి పరిస్థితిలో ఆదర్శవంతమైన ఎంపిక డేటాబేస్ ముందు నిలబడే కనెక్షన్ మేనేజర్ను ఎంచుకోవడం.
కనెక్షన్ మేనేజర్ కోసం మాకు రెండు ఎంపికలు ఉన్నాయి: Pgpool మరియు PgBouncer. కానీ మొదటిది డేటాబేస్తో పని చేసే లావాదేవీల మోడ్కు మద్దతు ఇవ్వదు, కాబట్టి మేము PgBouncerని ఎంచుకున్నాము.
మేము ఈ క్రింది పని పథకాన్ని కాన్ఫిగర్ చేసాము: మా అప్లికేషన్ ఒక PgBouncerని యాక్సెస్ చేస్తుంది, దాని వెనుక PostgreSQL మాస్టర్లు ఉన్నారు మరియు ప్రతి మాస్టర్ వెనుక అసమకాలిక ప్రతిరూపణతో ఒక ప్రతిరూపం ఉంటుంది.
అదే సమయంలో, మేము PostgreSQLలో మొత్తం డేటాను నిల్వ చేయలేము మరియు డేటాబేస్తో పని చేసే వేగం మాకు ముఖ్యమైనది, కాబట్టి మేము అప్లికేషన్ స్థాయిలో PostgreSQLని భాగస్వామ్యం చేయడం ప్రారంభించాము. పైన వివరించిన పథకం దీనికి సాపేక్షంగా సౌకర్యవంతంగా ఉంటుంది: కొత్త PostgreSQL షార్డ్ను జోడించేటప్పుడు, PgBouncer కాన్ఫిగరేషన్ను నవీకరించడం సరిపోతుంది మరియు అప్లికేషన్ వెంటనే కొత్త షార్డ్తో పని చేస్తుంది.
PgBouncer తప్పు సహనం
ఒకే ఒక్క PgBouncer ఉదాహరణ చనిపోయే వరకు ఈ పథకం పనిచేసింది. మేము AWSలో ఉన్నాము, ఇక్కడ అన్ని సందర్భాలు క్రమానుగతంగా చనిపోయే హార్డ్వేర్లో ప్రారంభించబడతాయి. అటువంటి సందర్భాలలో, ఉదాహరణ కొత్త హార్డ్వేర్కు వెళ్లి మళ్లీ పని చేస్తుంది. ఇది PgBouncerతో జరిగింది, కానీ అది అందుబాటులో లేకుండా పోయింది. ఈ క్రాష్ ఫలితంగా మా సేవ 25 నిమిషాల పాటు అందుబాటులో లేదు. అటువంటి పరిస్థితుల కోసం, ఆ సమయంలో మేము అమలు చేయని వినియోగదారు వైపు రిడెండెన్సీని ఉపయోగించమని AWS సిఫార్సు చేస్తుంది.
ఆ తర్వాత, PgBouncer మరియు PostgreSQL క్లస్టర్ల యొక్క తప్పు సహనం గురించి మేము తీవ్రంగా ఆలోచించాము, ఎందుకంటే మా AWS ఖాతాలో ఏదైనా సందర్భంలో ఇలాంటి పరిస్థితి మళ్లీ సంభవించవచ్చు.
మేము PgBouncer ఫాల్ట్ టాలరెన్స్ స్కీమ్ను ఈ క్రింది విధంగా రూపొందించాము: అన్ని అప్లికేషన్ సర్వర్లు నెట్వర్క్ లోడ్ బ్యాలెన్సర్ను యాక్సెస్ చేస్తాయి, దాని వెనుక రెండు PgBouncers ఉన్నాయి. ప్రతి PgBouncers ప్రతి షార్డ్ యొక్క అదే మాస్టర్ PostgreSQLని చూస్తుంది. AWS ఉదాహరణ క్రాష్తో పరిస్థితి పునరావృతమైతే, మొత్తం ట్రాఫిక్ మరొక PgBouncer ద్వారా దారి మళ్లించబడుతుంది. నెట్వర్క్ లోడ్ బ్యాలెన్సర్ ఫాల్ట్ టాలరెన్స్ AWS ద్వారా అందించబడింది.
ఈ పథకం కొత్త PgBouncer సర్వర్లను సులభంగా జోడించడానికి మిమ్మల్ని అనుమతిస్తుంది.
PostgreSQL ఫెయిల్ఓవర్ క్లస్టర్ను సృష్టిస్తోంది
ఈ సమస్యను పరిష్కరించేటప్పుడు, మేము వివిధ ఎంపికలను పరిగణించాము: స్వీయ-వ్రాతపూర్వక వైఫల్యం, repmgr, AWS RDS, Patroni.
స్వయంగా వ్రాసిన స్క్రిప్ట్లు
వారు మాస్టర్ యొక్క పనిని పర్యవేక్షించగలరు మరియు అది విఫలమైతే, మాస్టర్కు ప్రతిరూపాన్ని ప్రచారం చేయండి మరియు PgBouncer కాన్ఫిగరేషన్ను నవీకరించవచ్చు.
ఈ విధానం యొక్క ప్రయోజనాలు గరిష్ట సరళత, ఎందుకంటే మీరు స్క్రిప్ట్లను మీరే వ్రాసి, అవి ఎలా పని చేస్తాయో అర్థం చేసుకోండి.
కాన్స్:
- మాస్టర్ మరణించి ఉండకపోవచ్చు; బదులుగా, నెట్వర్క్ వైఫల్యం జరిగి ఉండవచ్చు. ఫెయిల్ఓవర్, దీని గురించి తెలియకుండా, మాస్టర్కు ప్రతిరూపాన్ని ప్రమోట్ చేస్తుంది మరియు పాత మాస్టర్ పని చేస్తూనే ఉంటారు. ఫలితంగా, మేము ప్రధాన పాత్రలో రెండు సర్వర్లను పొందుతాము మరియు వాటిలో ఏది తాజా ప్రస్తుత డేటాను కలిగి ఉందో తెలియదు. ఈ పరిస్థితిని స్ప్లిట్-మెదడు అని కూడా పిలుస్తారు;
- స్పందన లేకుండా పోయాం. మా కాన్ఫిగరేషన్లో మాస్టర్ మరియు ఒక ప్రతిరూపం ఉంది, ప్రతిరూపం మారిన తర్వాత మాస్టర్గా ప్రమోట్ చేయబడుతుంది మరియు మా వద్ద ప్రతిరూపాలు లేవు, కాబట్టి మనం కొత్త ప్రతిరూపాన్ని మాన్యువల్గా జోడించాలి;
- ఫెయిల్ఓవర్ ఆపరేషన్పై మాకు అదనపు పర్యవేక్షణ అవసరం మరియు మా వద్ద 12 PostgreSQL షార్డ్లు ఉన్నాయి, అంటే మనం 12 క్లస్టర్లను పర్యవేక్షించాలి. ముక్కల సంఖ్యను పెంచేటప్పుడు, మీరు ఫెయిల్ఓవర్ను నవీకరించాలని కూడా గుర్తుంచుకోవాలి.
స్వీయ-వ్రాతపూర్వక వైఫల్యం చాలా క్లిష్టంగా కనిపిస్తుంది మరియు చిన్నవిషయం కాని మద్దతు అవసరం. ఒక PostgreSQL క్లస్టర్తో, ఇది సరళమైన ఎంపికగా ఉంటుంది, కానీ ఇది స్కేల్ చేయదు, కాబట్టి ఇది మాకు తగినది కాదు.
ప్రజాప్రతినిధి
PostgreSQL క్లస్టర్ల కోసం రెప్లికేషన్ మేనేజర్, ఇది PostgreSQL క్లస్టర్ యొక్క ఆపరేషన్ను నిర్వహించగలదు. అదే సమయంలో, ఇది బాక్స్ వెలుపల ఆటోమేటిక్ వైఫల్యాన్ని కలిగి ఉండదు, కాబట్టి పని చేయడానికి మీరు రెడీమేడ్ సొల్యూషన్ పైన మీ స్వంత "రేపర్" ను వ్రాయవలసి ఉంటుంది. కాబట్టి ప్రతిదీ స్వీయ-వ్రాతపూర్వక స్క్రిప్ట్లతో పోలిస్తే మరింత క్లిష్టంగా మారవచ్చు, అందుకే మేము Repmgrని కూడా ప్రయత్నించలేదు.
AWS RDS
ఇది మనకు అవసరమైన ప్రతిదానికీ మద్దతు ఇస్తుంది, బ్యాకప్లను చేయగలదు మరియు కనెక్షన్ల సమూహానికి మద్దతు ఇస్తుంది. ఇది స్వయంచాలక మార్పిడిని కలిగి ఉంటుంది: మాస్టర్ చనిపోయినప్పుడు, ప్రతిరూపం కొత్త మాస్టర్ అవుతుంది మరియు AWS DNS రికార్డ్ను కొత్త మాస్టర్గా మారుస్తుంది, అయితే ప్రతిరూపాలు వేర్వేరు AZలలో ఉంటాయి.
ప్రతికూలతలు చక్కటి సెట్టింగులు లేకపోవడం. ఫైన్-ట్యూనింగ్ యొక్క ఉదాహరణగా: మా ఉదాహరణలు tcp కనెక్షన్ల కోసం పరిమితులను కలిగి ఉన్నాయి, దురదృష్టవశాత్తు, RDSలో దీన్ని చేయడం సాధ్యం కాదు:
net.ipv4.tcp_keepalive_time=10
net.ipv4.tcp_keepalive_intvl=1
net.ipv4.tcp_keepalive_probes=5
net.ipv4.tcp_retries2=3
అదనంగా, AWS RDS సాధారణ ఉదాహరణ ధర కంటే దాదాపు రెండు రెట్లు ఖరీదైనది, ఇది ఈ పరిష్కారాన్ని వదిలివేయడానికి ప్రధాన కారణం.
పాత్రోని
ఇది మంచి డాక్యుమెంటేషన్, ఆటోమేటిక్ ఫెయిల్ఓవర్ మరియు గిథబ్లో సోర్స్ కోడ్తో PostgreSQLని నిర్వహించడానికి పైథాన్ టెంప్లేట్.
పాత్రోని యొక్క ప్రయోజనాలు:
- ప్రతి కాన్ఫిగరేషన్ పరామితి వివరించబడింది, ఇది ఎలా పని చేస్తుందో స్పష్టంగా తెలుస్తుంది;
- ఆటోమేటిక్ ఫెయిల్ఓవర్ బాక్స్ వెలుపల పనిచేస్తుంది;
- పైథాన్లో వ్రాయబడింది, మరియు మనమే పైథాన్లో చాలా వ్రాస్తాము కాబట్టి, సమస్యలను ఎదుర్కోవడం మాకు సులభం అవుతుంది మరియు బహుశా ప్రాజెక్ట్ అభివృద్ధికి కూడా సహాయపడుతుంది;
- PostgreSQLని పూర్తిగా నియంత్రిస్తుంది, క్లస్టర్ యొక్క అన్ని నోడ్లలోని కాన్ఫిగరేషన్ను ఒకేసారి మార్చడానికి మిమ్మల్ని అనుమతిస్తుంది మరియు కొత్త కాన్ఫిగరేషన్ని వర్తింపజేయడానికి క్లస్టర్ని పునఃప్రారంభించాల్సిన అవసరం ఉన్నట్లయితే, ఇది Patroniని ఉపయోగించి మళ్లీ చేయవచ్చు.
కాన్స్:
- PgBouncerతో సరిగ్గా ఎలా పని చేయాలో డాక్యుమెంటేషన్ నుండి స్పష్టంగా లేదు. దీనిని మైనస్ అని పిలవడం కష్టం అయినప్పటికీ, Patroni యొక్క పని PostgreSQLని నిర్వహించడం మరియు Patroniకి కనెక్షన్లు ఎలా పని చేస్తాయి అనేది ఇప్పటికే మా సమస్య;
- పెద్ద ప్రమాణాలలో పాత్రోని అమలుకు కొన్ని ఉదాహరణలు ఉన్నాయి, అయితే మొదటి నుండి అమలుకు అనేక ఉదాహరణలు ఉన్నాయి.
ఫలితంగా, మేము ఫెయిల్ఓవర్ క్లస్టర్ని సృష్టించడానికి పాట్రోనిని ఎంచుకున్నాము.
పాట్రోని అమలు ప్రక్రియ
Patroniకి ముందు, మేము ఒక మాస్టర్లో 12 PostgreSQL షార్డ్లను కలిగి ఉన్నాము మరియు అసమకాలిక ప్రతిరూపణతో ఒక ప్రతిరూప కాన్ఫిగరేషన్ను కలిగి ఉన్నాము. అప్లికేషన్ సర్వర్లు నెట్వర్క్ లోడ్ బ్యాలెన్సర్ ద్వారా డేటాబేస్లను యాక్సెస్ చేశాయి, దాని వెనుక PgBouncerతో రెండు సందర్భాలు ఉన్నాయి మరియు వాటి వెనుక అన్ని PostgreSQL సర్వర్లు ఉన్నాయి.
Patroniని అమలు చేయడానికి, మేము పంపిణీ చేయబడిన క్లస్టర్ కాన్ఫిగరేషన్ నిల్వను ఎంచుకోవాలి. etcd, Zookeeper, Consul వంటి పంపిణీ చేయబడిన కాన్ఫిగరేషన్ నిల్వ వ్యవస్థలతో Patroni పనిచేస్తుంది. మేము ఉత్పత్తిలో పూర్తి స్థాయి కాన్సుల్ క్లస్టర్ని కలిగి ఉన్నాము, ఇది వాల్ట్తో కలిసి పని చేస్తుంది మరియు మేము దానిని ఇకపై ఉపయోగించము. దాని ఉద్దేశించిన ప్రయోజనం కోసం కాన్సుల్ను ఉపయోగించడం ప్రారంభించడానికి గొప్ప కారణం.
పాట్రోని కాన్సుల్తో ఎలా పని చేస్తారు
మాకు మూడు నోడ్లతో కూడిన కాన్సుల్ క్లస్టర్ మరియు లీడర్ మరియు రెప్లికాతో కూడిన పాత్రోని క్లస్టర్ ఉన్నాయి (పాట్రోనిలో, మాస్టర్ను క్లస్టర్ లీడర్ అని పిలుస్తారు మరియు బానిసలను ప్రతిరూపాలు అంటారు). ప్రతి పాట్రోని క్లస్టర్ ఉదాహరణ నిరంతరం క్లస్టర్ స్థితి గురించి సమాచారాన్ని కాన్సుల్కు పంపుతుంది. అందువల్ల, కాన్సుల్ నుండి మీరు ఎల్లప్పుడూ Patroni క్లస్టర్ యొక్క ప్రస్తుత కాన్ఫిగరేషన్ను కనుగొనవచ్చు మరియు ప్రస్తుతానికి ఎవరు నాయకుడు.
Patroniని కాన్సుల్కి కనెక్ట్ చేయడానికి, మేము కాన్సుల్తో ఎలా పని చేస్తాము మరియు ఐచ్ఛికంగా కనెక్షన్ రేఖాచిత్రం ఆధారంగా మీరు హోస్ట్ని http లేదా https ఆకృతిలో పేర్కొనాలని చెప్పే అధికారిక డాక్యుమెంటేషన్ను అధ్యయనం చేయండి:
host: the host:port for the Consul endpoint, in format: http(s)://host:port
scheme: (optional) http or https, defaults to http
ఇది సరళంగా కనిపిస్తుంది, కానీ ఇక్కడే ఆపదలు ప్రారంభమవుతాయి. కాన్సుల్తో మేము https ద్వారా సురక్షిత కనెక్షన్తో పని చేస్తాము మరియు మా కనెక్షన్ కాన్ఫిగర్ ఇలా కనిపిస్తుంది:
consul:
host: https://server.production.consul:8080
verify: true
cacert: {{ consul_cacert }}
cert: {{ consul_cert }}
key: {{ consul_key }}
కానీ అది ఆ విధంగా పనిచేయదు. ప్రారంభంలో, Patroni కాన్సుల్కి కనెక్ట్ కాలేదు ఎందుకంటే ఇది ఇప్పటికీ http ద్వారా వెళ్లడానికి ప్రయత్నిస్తుంది.
Patroni సోర్స్ కోడ్ సమస్యను పరిష్కరించడంలో సహాయపడింది. కొండచిలువలో రాయడం బాగుంది. హోస్ట్ పరామితి ఏ విధంగానూ అన్వయించబడలేదని మరియు స్కీమ్లో ప్రోటోకాల్ తప్పనిసరిగా పేర్కొనబడాలని ఇది మారుతుంది. కాన్సుల్తో పని చేయడానికి వర్కింగ్ కాన్ఫిగరేషన్ బ్లాక్ మాకు ఇలా కనిపిస్తుంది:
consul:
host: server.production.consul:8080
scheme: https
verify: true
cacert: {{ consul_cacert }}
cert: {{ consul_cert }}
key: {{ consul_key }}
కన్సల్-టెంప్లేట్
కాబట్టి, మేము కాన్ఫిగరేషన్ నిల్వను ఎంచుకున్నాము. Patroni క్లస్టర్లో నాయకుడు మారినప్పుడు PgBouncer దాని కాన్ఫిగరేషన్ను ఎలా మారుస్తుందో ఇప్పుడు మనం అర్థం చేసుకోవాలి. డాక్యుమెంటేషన్లో ఈ ప్రశ్నకు సమాధానం లేదు, ఎందుకంటే... సూత్రప్రాయంగా, PgBouncerతో పని చేయడం అక్కడ వివరించబడలేదు.
పరిష్కారం కోసం అన్వేషణలో, మేము ఒక కథనాన్ని కనుగొన్నాము (దురదృష్టవశాత్తూ, నాకు పేరు గుర్తులేదు), అక్కడ PgBouncer మరియు Patroni కలపడంలో కాన్సుల్-టెంప్లేట్ చాలా సహాయకారిగా ఉందని వ్రాయబడింది. ఇది కన్సల్-టెంప్లేట్ యొక్క పనిని అధ్యయనం చేయడానికి మమ్మల్ని ప్రేరేపించింది.
కాన్సుల్లోని PostgreSQL క్లస్టర్ కాన్ఫిగరేషన్ను కాన్సుల్-టెంప్లేట్ నిరంతరం పర్యవేక్షిస్తుందని తేలింది. లీడర్ మారినప్పుడు, అది PgBouncer కాన్ఫిగరేషన్ను అప్డేట్ చేస్తుంది మరియు దానిని రీలోడ్ చేయడానికి ఒక ఆదేశాన్ని పంపుతుంది.
టెంప్లేట్ యొక్క పెద్ద ప్రయోజనం ఏమిటంటే ఇది కోడ్గా నిల్వ చేయబడుతుంది, కాబట్టి కొత్త షార్డ్ను జోడించేటప్పుడు, కొత్త కమిట్ను చేసి, టెంప్లేట్ను స్వయంచాలకంగా అప్డేట్ చేస్తే సరిపోతుంది, ఇన్ఫ్రాస్ట్రక్చర్ను కోడ్ సూత్రంగా సపోర్ట్ చేస్తుంది.
పాత్రోనితో కొత్త ఆర్కిటెక్చర్
ఫలితంగా, మేము ఈ క్రింది పని పథకాన్ని అందుకున్నాము:
అన్ని అప్లికేషన్ సర్వర్లు బాలన్సర్ను యాక్సెస్ చేస్తాయి → దాని వెనుక PgBouncer యొక్క రెండు సందర్భాలు ఉన్నాయి → ప్రతి సందర్భంలో ఒక కాన్సుల్-టెంప్లేట్ నడుస్తుంది, ఇది ప్రతి Patroni క్లస్టర్ యొక్క స్థితిని పర్యవేక్షిస్తుంది మరియు PgBouncer కాన్ఫిగరేషన్ యొక్క ఔచిత్యాన్ని పర్యవేక్షిస్తుంది, ఇది ప్రస్తుత నాయకుడికి అభ్యర్థనలను నిర్దేశిస్తుంది. ప్రతి క్లస్టర్.
మాన్యువల్ పరీక్ష
దీన్ని ఉత్పత్తికి ప్రారంభించే ముందు, మేము ఈ పథకాన్ని చిన్న పరీక్ష వాతావరణంలో ప్రారంభించాము మరియు ఆటోమేటిక్ స్విచింగ్ యొక్క ఆపరేషన్ను తనిఖీ చేసాము. వారు బోర్డుని తెరిచి, స్టిక్కర్ను కదిలించారు మరియు ఆ సమయంలో క్లస్టర్ నాయకుడిని "చంపారు". AWSలో, మీరు చేయాల్సిందల్లా కన్సోల్ ద్వారా ఉదాహరణను ఆఫ్ చేయడం.
స్టిక్కర్ 10-20 సెకన్లలోపు తిరిగి వచ్చింది, ఆపై మళ్లీ సాధారణంగా కదలడం ప్రారంభించింది. దీనర్థం Patroni క్లస్టర్ సరిగ్గా పని చేసింది: ఇది నాయకుడిని మార్చింది, కాన్సుల్కు సమాచారాన్ని పంపింది మరియు కాన్సుల్-టెంప్లేట్ వెంటనే ఈ సమాచారాన్ని కైవసం చేసుకుంది, PgBouncer కాన్ఫిగరేషన్ను భర్తీ చేసింది మరియు రీలోడ్ చేయడానికి ఆదేశాన్ని పంపింది.
అధిక భారం కింద జీవించడం మరియు తక్కువ సమయ వ్యవధిని ఎలా నిర్వహించడం?
ప్రతిదీ ఖచ్చితంగా పనిచేస్తుంది! కానీ కొత్త ప్రశ్నలు తలెత్తుతాయి: అధిక లోడ్లో ఇది ఎలా పని చేస్తుంది? ఉత్పత్తిలో ప్రతిదీ త్వరగా మరియు సురక్షితంగా ఎలా బయటకు తీయాలి?
మేము లోడ్ పరీక్షను నిర్వహించే పరీక్ష వాతావరణం మొదటి ప్రశ్నకు సమాధానం ఇవ్వడంలో మాకు సహాయపడుతుంది. ఇది ఆర్కిటెక్చర్లో ఉత్పత్తికి పూర్తిగా సమానంగా ఉంటుంది మరియు పరీక్ష డేటాను రూపొందించింది, ఇది ఉత్పత్తికి వాల్యూమ్లో దాదాపు సమానంగా ఉంటుంది. మేము పరీక్ష సమయంలో PostgreSQL మాస్టర్లలో ఒకరిని "చంపాలని" నిర్ణయించుకున్నాము మరియు ఏమి జరుగుతుందో చూద్దాం. అయితే దీనికి ముందు, ఆటోమేటిక్ రోల్అవుట్ను తనిఖీ చేయడం చాలా ముఖ్యం, ఎందుకంటే ఈ వాతావరణంలో మనకు అనేక PostgreSQL షార్డ్లు ఉన్నాయి, కాబట్టి మేము ఉత్పత్తికి ముందు కాన్ఫిగరేషన్ స్క్రిప్ట్ల యొక్క అద్భుతమైన పరీక్షను పొందుతాము.
రెండు పనులు ప్రతిష్టాత్మకంగా కనిపిస్తున్నాయి, కానీ మనకు PostgreSQL 9.6 ఉంది. బహుశా మనం వెంటనే 11.2కి అప్డేట్ చేయగలమా?
మేము దీన్ని 2 దశల్లో చేయాలని నిర్ణయించుకున్నాము: ముందుగా సంస్కరణను 11.2కి నవీకరించండి, ఆపై Patroniని ప్రారంభించండి.
PostgreSQL నవీకరణ
PostgreSQL సంస్కరణను త్వరగా నవీకరించడానికి, మీరు తప్పనిసరిగా ఎంపికను ఉపయోగించాలి -k, దీనిలో హార్డ్ లింక్ డిస్క్లో సృష్టించబడుతుంది మరియు మీ డేటాను కాపీ చేయవలసిన అవసరం లేదు. 300-400 GB డేటాబేస్లలో, నవీకరణ 1 సెకను పడుతుంది.
మాకు చాలా ముక్కలు ఉన్నాయి, కాబట్టి నవీకరణ స్వయంచాలకంగా చేయాలి. దీన్ని చేయడానికి, మేము మా కోసం మొత్తం నవీకరణ ప్రక్రియను నిర్వహించే Ansible ప్లేబుక్ని వ్రాసాము:
/usr/lib/postgresql/11/bin/pg_upgrade
<b>--link </b>
--old-datadir='' --new-datadir=''
--old-bindir='' --new-bindir=''
--old-options=' -c config_file='
--new-options=' -c config_file='
నవీకరణను ప్రారంభించే ముందు, మీరు తప్పనిసరిగా పరామితితో దీన్ని నిర్వహించాలని ఇక్కడ గమనించడం ముఖ్యం --తనిఖీఅప్గ్రేడ్ సాధ్యమేనని నిర్ధారించుకోవడానికి. అప్గ్రేడ్ సమయంలో మా స్క్రిప్ట్ కాన్ఫిగర్లను కూడా భర్తీ చేస్తుంది. మా స్క్రిప్ట్ 30 సెకన్లలో పూర్తయింది, ఇది అద్భుతమైన ఫలితం.
పాత్రోని ప్రారంభం
రెండవ సమస్యను పరిష్కరించడానికి, కేవలం Patroni కాన్ఫిగరేషన్ను చూడండి. అధికారిక రిపోజిటరీ initdbతో ఉదాహరణ కాన్ఫిగరేషన్ను కలిగి ఉంది, ఇది Patroni మొదట ప్రారంభించబడినప్పుడు కొత్త డేటాబేస్ను ప్రారంభించే బాధ్యతను కలిగి ఉంటుంది. కానీ మేము ఇప్పటికే సిద్ధంగా ఉన్న డేటాబేస్ను కలిగి ఉన్నందున, మేము ఈ విభాగాన్ని కాన్ఫిగరేషన్ నుండి తొలగించాము.
మేము సిద్ధంగా ఉన్న PostgreSQL క్లస్టర్లో Patroniని ఇన్స్టాల్ చేయడం ప్రారంభించినప్పుడు మరియు దానిని ప్రారంభించినప్పుడు, మేము కొత్త సమస్యను ఎదుర్కొన్నాము: రెండు సర్వర్లు కూడా లీడర్గా ప్రారంభించబడ్డాయి. క్లస్టర్ యొక్క ప్రారంభ స్థితి గురించి ప్యాట్రోనికి ఏమీ తెలియదు మరియు రెండు సర్వర్లను ఒకే పేరుతో రెండు వేర్వేరు క్లస్టర్లుగా అమలు చేయడానికి ప్రయత్నిస్తుంది. ఈ సమస్యను పరిష్కరించడానికి, మీరు స్లేవ్లోని డేటా డైరెక్టరీని తొలగించాలి:
rm -rf /var/lib/postgresql/
ఇది బానిసపై మాత్రమే చేయాలి!
శుభ్రమైన ప్రతిరూపాన్ని కనెక్ట్ చేసినప్పుడు, Patroni ఒక బేస్బ్యాకప్ లీడర్ను తయారు చేసి, దానిని ప్రతిరూపానికి పునరుద్ధరిస్తుంది, ఆపై వాల్ లాగ్లను ఉపయోగించి ప్రస్తుత స్థితిని తెలుసుకుంటుంది.
మేము ఎదుర్కొన్న మరో ఇబ్బంది ఏమిటంటే, అన్ని PostgreSQL క్లస్టర్లు డిఫాల్ట్గా మెయిన్గా పిలువబడతాయి. ప్రతి క్లస్టర్కి మరొకదాని గురించి ఏమీ తెలియనప్పుడు, ఇది సాధారణం. కానీ మీరు Patroniని ఉపయోగించాలనుకున్నప్పుడు, అన్ని క్లస్టర్లకు తప్పనిసరిగా ప్రత్యేక పేరు ఉండాలి. PostgreSQL కాన్ఫిగరేషన్లో క్లస్టర్ పేరును మార్చడం పరిష్కారం.
లోడ్ పరీక్ష
బోర్డులపై వినియోగదారులు ఎలా పని చేస్తారో అనుకరించే పరీక్షను మేము ప్రారంభించాము. లోడ్ మా రోజువారీ సగటుకు చేరుకున్నప్పుడు, మేము అదే పరీక్షను పునరావృతం చేసాము, మేము లీడర్ PostgreSQLతో ఒక ఉదాహరణను ఆఫ్ చేసాము. ఆటోమేటిక్ ఫెయిల్ఓవర్ మేము ఊహించిన విధంగా పని చేసింది: Patroni నాయకుడిని మార్చింది, కాన్సుల్-టెంప్లేట్ PgBouncer కాన్ఫిగరేషన్ను నవీకరించింది మరియు రీలోడ్ చేయడానికి ఆదేశాన్ని పంపింది. గ్రాఫానాలోని మా గ్రాఫ్ల ప్రకారం, డేటాబేస్కు కనెక్షన్కు సంబంధించిన సర్వర్ల నుండి 20-30 సెకన్ల ఆలస్యం మరియు చిన్న మొత్తంలో లోపాలు ఉన్నాయని స్పష్టమైంది. ఇది ఒక సాధారణ పరిస్థితి, అటువంటి విలువలు మా వైఫల్యానికి ఆమోదయోగ్యమైనవి మరియు సర్వీస్ డౌన్టైమ్ కంటే ఖచ్చితంగా మెరుగ్గా ఉంటాయి.
ఉత్పత్తిలోకి పాత్రోని ప్రారంభం
ఫలితంగా, మేము ఈ క్రింది ప్రణాళికతో ముందుకు వచ్చాము:
- PgBouncer సర్వర్కు కాన్సుల్-టెంప్లేట్ని అమలు చేసి ప్రారంభించండి;
- PostgreSQL సంస్కరణ 11.2కి నవీకరణలు;
- క్లస్టర్ పేరు మార్చడం;
- Patroni క్లస్టర్ ప్రారంభం.
అదే సమయంలో, మా పథకం దాదాపు ఎప్పుడైనా మొదటి పాయింట్ని చేయడానికి అనుమతిస్తుంది; మేము ప్రతి PgBouncerని పని నుండి ఒక్కొక్కటిగా తీసివేసి, దానిపై కాన్సుల్-టెంప్లేట్ని అమలు చేయడం మరియు ప్రారంభించడం చేయవచ్చు. మేం చేసింది అదే.
శీఘ్ర పరీక్ష కోసం, మేము Ansibleని ఉపయోగించాము, ఎందుకంటే మేము ఇప్పటికే మొత్తం ప్లేబుక్ను టెస్ట్ వాతావరణంలో పరీక్షించాము మరియు పూర్తి స్క్రిప్ట్ కోసం అమలు సమయం ప్రతి షార్డ్కు 1,5 నుండి 2 నిమిషాల వరకు ఉంటుంది. మేము మా సేవను ఆపకుండానే ప్రతి ఒక్కటి ఒక్కో ముక్కకు అందజేస్తాము, అయితే మేము ప్రతి PostgreSQLని చాలా నిమిషాల పాటు ఆఫ్ చేయాల్సి ఉంటుంది. ఈ సందర్భంలో, ఈ షార్డ్లో డేటా ఉన్న వినియోగదారులు ఈ సమయంలో పూర్తిగా పని చేయలేరు మరియు ఇది మాకు ఆమోదయోగ్యం కాదు.
ఈ పరిస్థితి నుండి బయటపడే మార్గం ప్రణాళికాబద్ధమైన నిర్వహణ, ఇది మేము ప్రతి 3 నెలలకు చేస్తాము. మేము మా సేవను పూర్తిగా ఆపివేసి, డేటాబేస్ సందర్భాలను నవీకరించినప్పుడు, ఇది షెడ్యూల్ చేయబడిన పని కోసం విండో. తదుపరి విండోకు ఒక వారం మిగిలి ఉంది మరియు మేము వేచి ఉండి మరింత సిద్ధం చేయాలని నిర్ణయించుకున్నాము. నిరీక్షణ సమయంలో, మేము అదనంగా మా పందాలకు అడ్డుకట్ట వేసాము: తాజా డేటాను సేవ్ చేయడానికి, విఫలమైతే ప్రతి PostgreSQL షార్డ్ కోసం మేము విడి ప్రతిరూపాన్ని సేకరించాము మరియు ప్రతి షార్డ్కు ఒక కొత్త ఉదాహరణను జోడించాము, ఇది Patroniలో కొత్త ప్రతిరూపంగా మారుతుంది. క్లస్టర్, కాబట్టి డేటాను తొలగించడానికి ఆదేశాన్ని జారీ చేయకూడదు . ఇవన్నీ లోపం ప్రమాదాన్ని తగ్గించడంలో సహాయపడతాయి.
మేము మా సేవను పునఃప్రారంభించాము, ప్రతిదీ సరిగ్గా పని చేసింది, వినియోగదారులు పని చేయడం కొనసాగించారు, కానీ గ్రాఫ్లలో మేము కాన్సుల్ సర్వర్లలో అసాధారణంగా అధిక లోడ్ను గమనించాము.
పరీక్షా వాతావరణంలో మనం దీన్ని ఎందుకు చూడలేదు? ఇన్ఫ్రాస్ట్రక్చర్ను కోడ్ సూత్రంగా అనుసరించడం మరియు పరీక్షా వాతావరణాల నుండి ఉత్పత్తి వరకు మొత్తం మౌలిక సదుపాయాలను మెరుగుపరచడం అవసరమని ఈ సమస్య చాలా చక్కగా వివరిస్తుంది. లేకపోతే, మనకు వచ్చిన సమస్యను పొందడం చాలా సులభం. ఏం జరిగింది? కాన్సుల్ మొదట ఉత్పత్తిలో కనిపించాడు, ఆపై పరీక్ష వాతావరణంలో కనిపించాడు; ఫలితంగా, పరీక్ష వాతావరణాలలో కాన్సుల్ వెర్షన్ ఉత్పత్తి కంటే ఎక్కువగా ఉంది. కేవలం ఒక విడుదలలో, కాన్సుల్-టెంప్లేట్తో పని చేస్తున్నప్పుడు CPU లీక్ పరిష్కరించబడింది. కాబట్టి మేము కాన్సుల్ను అప్డేట్ చేసాము, తద్వారా సమస్యను పరిష్కరించాము.
Patroni క్లస్టర్ని పునఃప్రారంభించండి
అయితే, మేము కూడా అనుమానించని కొత్త సమస్య వచ్చింది. కాన్సుల్ను అప్డేట్ చేస్తున్నప్పుడు, మేము కాన్సుల్ లీవ్ కమాండ్ → పాట్రోని మరొక కాన్సుల్ సర్వర్కు కనెక్ట్ చేస్తుంది → ప్రతిదీ పని చేస్తుంది ఉపయోగించి క్లస్టర్ నుండి కాన్సుల్ నోడ్ను తీసివేస్తాము. కానీ మేము కాన్సుల్ క్లస్టర్ యొక్క చివరి ఉదాహరణకి వచ్చినప్పుడు మరియు కాన్సుల్ లీవ్ కమాండ్ను పంపినప్పుడు, అన్ని Patroni క్లస్టర్లు కేవలం పునఃప్రారంభించబడ్డాయి మరియు లాగ్లలో మేము ఈ క్రింది దోషాన్ని చూశాము:
ERROR: get_cluster
Traceback (most recent call last):
...
RetryFailedError: 'Exceeded retry deadline'
ERROR: Error communicating with DCS
<b>LOG: database system is shut down</b>
Patroni క్లస్టర్ దాని క్లస్టర్ గురించి సమాచారాన్ని పొందలేకపోయింది మరియు పునఃప్రారంభించబడింది.
పరిష్కారాన్ని కనుగొనడానికి, మేము గితుబ్లో సమస్య ద్వారా Patroni రచయితలను సంప్రదించాము. వారు మా కాన్ఫిగరేషన్ ఫైల్లకు మెరుగుదలలను సూచించారు:
consul:
consul.checks: []
bootstrap:
dcs:
retry_timeout: 8
మేము పరీక్ష వాతావరణంలో సమస్యను పునరావృతం చేయగలిగాము మరియు అక్కడ ఈ సెట్టింగ్లను పరీక్షించాము, కానీ దురదృష్టవశాత్తు అవి పని చేయలేదు.
సమస్య ఇప్పటికీ పరిష్కారం కాలేదు. మేము ఈ క్రింది పరిష్కారాలను ప్రయత్నించాలని ప్లాన్ చేస్తున్నాము:
- Patroni క్లస్టర్ యొక్క ప్రతి సందర్భంలో కన్సల్-ఏజెంట్ని ఉపయోగించండి;
- కోడ్లో సమస్యను పరిష్కరించండి.
లోపం ఎక్కడ జరిగిందో మేము అర్థం చేసుకున్నాము: బహుశా డిఫాల్ట్ గడువును ఉపయోగించడంలో సమస్య ఉండవచ్చు, ఇది కాన్ఫిగరేషన్ ఫైల్ ద్వారా భర్తీ చేయబడదు. క్లస్టర్ నుండి చివరి కాన్సుల్ సర్వర్ తొలగించబడినప్పుడు, మొత్తం కాన్సుల్ క్లస్టర్ స్తంభింపజేస్తుంది, ఇది సెకను కంటే ఎక్కువసేపు ఉంటుంది; దీని కారణంగా, ప్యాట్రోని క్లస్టర్ స్థితిని పొందలేరు మరియు మొత్తం క్లస్టర్ను పూర్తిగా రీస్టార్ట్ చేస్తుంది.
అదృష్టవశాత్తూ, మేము ఇకపై ఎలాంటి లోపాలను ఎదుర్కోలేదు.
Patroni ఉపయోగించి ఫలితాలు
Patroni విజయవంతంగా ప్రారంభించిన తర్వాత, మేము ప్రతి క్లస్టర్లో అదనపు ప్రతిరూపాన్ని జోడించాము. ఇప్పుడు ప్రతి క్లస్టర్కు కోరం యొక్క సారూప్యత ఉంది: ఒక నాయకుడు మరియు రెండు ప్రతిరూపాలు, మారేటప్పుడు స్ప్లిట్-మెదడు నుండి రక్షించడానికి.
పాత్రోని మూడు నెలలకు పైగా ఉత్పత్తిలో పని చేస్తున్నారు. ఈ సమయంలో, అతను ఇప్పటికే మాకు సహాయం చేయగలిగాడు. ఇటీవల, క్లస్టర్లలో ఒకదాని నాయకుడు AWS లో మరణించాడు, ఆటోమేటిక్ ఫెయిల్ఓవర్ పనిచేసింది మరియు వినియోగదారులు పని చేయడం కొనసాగించారు. పాత్రోని తన ప్రధాన విధిని నెరవేర్చాడు.
Patroniని ఉపయోగించడం యొక్క సంక్షిప్త సారాంశం:
- కాన్ఫిగరేషన్ మార్పుల సౌలభ్యం. కాన్ఫిగరేషన్ను ఒక సందర్భంలో మార్చడం సరిపోతుంది మరియు ఇది మొత్తం క్లస్టర్కు వర్తిస్తుంది. కొత్త కాన్ఫిగరేషన్ని వర్తింపజేయడానికి రీబూట్ అవసరమైతే, Patroni మీకు దీని గురించి తెలియజేస్తుంది. Patroni ఒక ఆదేశంతో మొత్తం క్లస్టర్ను పునఃప్రారంభించవచ్చు, ఇది కూడా చాలా సౌకర్యవంతంగా ఉంటుంది.
- ఆటోమేటిక్ ఫెయిల్ఓవర్ పని చేస్తోంది మరియు ఇప్పటికే మాకు సహాయం చేసింది.
- అప్లికేషన్ డౌన్టైమ్ లేకుండా PostgreSQLని నవీకరిస్తోంది. మీరు ముందుగా ప్రతిరూపాలను కొత్త వెర్షన్కి అప్డేట్ చేయాలి, ఆపై పాట్రోని క్లస్టర్లోని లీడర్ని మార్చాలి మరియు పాత లీడర్ని అప్డేట్ చేయాలి. ఈ సందర్భంలో, ఆటోమేటిక్ ఫెయిల్ఓవర్ యొక్క అవసరమైన పరీక్ష జరుగుతుంది.
మూలం: www.habr.com