जैसा कि हमने पहले देखा, कंपनियों के लिए MySQL के लिए अपने डेटा को RDS से बाहर ले जाना चुनौतीपूर्ण हो सकता है। इस ब्लॉग के पहले भाग में, हमने आपको दिखाया कि कैसे EC2 पर अपना लक्षित वातावरण सेट करें और अपने अनुप्रयोगों और RDS के बीच एक प्रॉक्सी परत (ProxySQL) डालें। इस दूसरे भाग में, हम आपको दिखाएंगे कि अपने सर्वर पर डेटा का वास्तविक माइग्रेशन कैसे करें, और फिर अपने एप्लिकेशन को बिना डाउनटाइम के नए डेटाबेस इंस्टेंस पर रीडायरेक्ट करें।
RDS से डेटा कॉपी करना
एक बार जब हमारे पास हमारा डेटाबेस ट्रैफ़िक ProxySQL के माध्यम से चल रहा है, तो हम अपने डेटा को RDS से कॉपी करने की तैयारी शुरू कर सकते हैं। RDS और EC2 पर चलने वाले हमारे MySQL इंस्टेंस के बीच प्रतिकृति स्थापित करने के लिए हमें ऐसा करने की आवश्यकता है। एक बार यह हो जाने के बाद, हम RDS से हमारे MySQL/EC2 पर ट्रैफ़िक पुनर्निर्देशित करने के लिए ProxySQL को कॉन्फ़िगर करेंगे।
जैसा कि हमने इस श्रृंखला के पहले ब्लॉग पोस्ट में चर्चा की थी, आप RDS से डेटा प्राप्त करने का एकमात्र तरीका लॉजिकल डंप के माध्यम से प्राप्त कर सकते हैं। इंस्टेंस तक पहुंच के बिना, हम xtrabackup जैसे किसी भी हॉट, फिजिकल बैकअप टूल का उपयोग नहीं कर सकते। हम स्नैपशॉट का उपयोग नहीं कर सकते क्योंकि स्नैपशॉट से नए आरडीएस इंस्टेंस के अलावा और कुछ भी बनाने का कोई तरीका नहीं है।
हम तार्किक डंप टूल तक सीमित हैं, इसलिए तार्किक विकल्प डेटा को संसाधित करने के लिए mydumper/myloader का उपयोग करना होगा। सौभाग्य से, mydumper लगातार बैकअप बना सकता है ताकि हम अपने नए दास से जुड़ने के लिए बिनलॉग निर्देशांक प्रदान करने के लिए उस पर भरोसा कर सकें। आरडीएस प्रतिकृतियां बनाते समय मुख्य मुद्दा बिनलॉग रोटेशन नीति है - लॉजिकल डंप और लोड में बड़े (सैकड़ों गीगाबाइट) डेटासेट पर भी दिन लग सकते हैं और आपको इस पूरी प्रक्रिया की अवधि के लिए आरडीएस इंस्टेंस पर बिनलॉग रखने की आवश्यकता है। ज़रूर, आप आरडीएस पर बिनलॉग रोटेशन रिटेंशन बढ़ा सकते हैं (कॉल mysql.rds_set_configuration('binlog रिटेंशन घंटे', 24); - आप उन्हें 7 दिनों तक रख सकते हैं) लेकिन इसे अलग तरीके से करना ज्यादा सुरक्षित है।
डंप लेने के साथ आगे बढ़ने से पहले, हम अपने आरडीएस इंस्टेंस में एक प्रतिकृति जोड़ देंगे।
अमेजन आरडीएस डैशबोर्ड आरडीएस में रेप्लिका डीबी बनाएंएक बार जब हम "क्रिएट रीड रेप्लिका" बटन पर क्लिक करते हैं, तो "मास्टर" आरडीएस प्रतिकृति पर एक स्नैपशॉट शुरू हो जाएगा। इसका उपयोग नए दास को प्रावधान करने के लिए किया जाएगा। इस प्रक्रिया में घंटों लग सकते हैं, यह सब वॉल्यूम के आकार पर निर्भर करता है, पिछली बार कब स्नैपशॉट लिया गया था और वॉल्यूम का प्रदर्शन (io1/gp2? चुंबकीय? एक वॉल्यूम में कितने pIOPS हैं?)।
मास्टर आरडीएस प्रतिकृतिजब स्लेव तैयार हो जाता है (इसकी स्थिति "उपलब्ध" में बदल गई है), तो हम इसके आरडीएस एंडपॉइंट का उपयोग करके इसमें लॉग इन कर सकते हैं।
RDS स्लेवएक बार लॉग इन करने के बाद, हम अपने दास पर प्रतिकृति बंद कर देंगे - यह सुनिश्चित करेगा कि आरडीएस मास्टर बाइनरी लॉग को शुद्ध नहीं करेगा और हमारे डंप/रीलोड प्रक्रिया को पूरा करने के बाद भी वे हमारे ईसी 2 दास के लिए उपलब्ध रहेंगे।
mysql> CALL mysql.rds_stop_replication;
+---------------------------+
| Message |
+---------------------------+
| Slave is down or disabled |
+---------------------------+
1 row in set (1.02 sec)
Query OK, 0 rows affected (1.02 sec)
अब, डेटा को EC2 में कॉपी करने का समय आ गया है। सबसे पहले, हमें mydumper स्थापित करने की आवश्यकता है। आप इसे जीथब से प्राप्त कर सकते हैं:https://github.com/maxbube/mydumper। रीडमी फ़ाइल में इंस्टॉलेशन प्रक्रिया काफी सरल और अच्छी तरह से वर्णित है, इसलिए हम इसे यहां कवर नहीं करेंगे। सबसे अधिक संभावना है कि आपको कुछ पैकेज (रीडमी में सूचीबद्ध) स्थापित करने होंगे और कठिन हिस्सा यह पहचानना है कि किस पैकेज में mysql_config है - यह MySQL स्वाद (और कभी-कभी MySQL संस्करण) पर भी निर्भर करता है।
एक बार जब आप mydumper संकलित कर लेते हैं और जाने के लिए तैयार हो जाते हैं, तो आप इसे निष्पादित कर सकते हैं:
[email protected]:~/mydumper# mkdir /tmp/rdsdump
[email protected]:~/mydumper# ./mydumper -h rds2.cvsw8xpajw2b.us-east-1.rds.amazonaws.com -p tpccpass -u tpcc -o /tmp/rdsdump --lock-all-tables --chunk-filesize 100 --events --routines --triggers
.
कृपया ध्यान दें --lock-all-tables जो सुनिश्चित करता है कि डेटा का स्नैपशॉट सुसंगत रहेगा और दास बनाने के लिए इसका उपयोग करना संभव होगा। अब, हमें mydumper द्वारा अपना कार्य पूरा करने तक प्रतीक्षा करनी होगी।
एक और कदम की आवश्यकता है - हम mysql स्कीमा को पुनर्स्थापित नहीं करना चाहते हैं, लेकिन हमें उपयोगकर्ताओं और उनके अनुदानों की प्रतिलिपि बनाने की आवश्यकता है। हम उसके लिए पीटी-शो-अनुदान का उपयोग कर सकते हैं:
[email protected]:~# wget http://percona.com/get/pt-show-grants
[email protected]:~# chmod u+x ./pt-show-grants
[email protected]:~# ./pt-show-grants -h rds2.cvsw8xpajw2b.us-east-1.rds.amazonaws.com -u tpcc -p tpccpass > grants.sql
पीटी-शो-अनुदान का नमूना इस तरह दिख सकता है:
-- Grants for 'sbtest'@'%'
CREATE USER IF NOT EXISTS 'sbtest'@'%';
ALTER USER 'sbtest'@'%' IDENTIFIED WITH 'mysql_native_password' AS '*2AFD99E79E4AA23DE141540F4179F64FFB3AC521' REQUIRE NONE PASSWORD EXPIRE DEFAULT ACCOUNT UNLOCK;
GRANT ALTER, ALTER ROUTINE, CREATE, CREATE ROUTINE, CREATE TEMPORARY TABLES, CREATE USER, CREATE VIEW, DELETE, DROP, EVENT, EXECUTE, INDEX, INSERT, LOCK TABLES, PROCESS, REFERENCES, RELOAD, REPLICATION CLIENT, REPLICATION SLAVE, SELECT, SHOW DATABASES, SHOW VIEW, TRIGGER, UPDATE ON *.* TO 'sbtest'@'%';
यह आप पर निर्भर करता है कि आपके MySQL/EC2 इंस्टेंस पर किन उपयोगकर्ताओं को कॉपी करने की आवश्यकता है। उन सभी के लिए ऐसा करने का कोई मतलब नहीं है। उदाहरण के लिए, रूट उपयोगकर्ताओं के पास आरडीएस पर 'सुपर' विशेषाधिकार नहीं है, इसलिए उन्हें स्क्रैच से फिर से बनाना बेहतर है। आपको जो कॉपी करने की आवश्यकता है वह आपके एप्लिकेशन उपयोगकर्ता के लिए अनुदान है। हमें ProxySQL (हमारे मामले में प्रॉक्सीस्क्ल-मॉनिटर) द्वारा उपयोग किए गए उपयोगकर्ताओं की प्रतिलिपि बनाने की भी आवश्यकता है।
अपने MySQL/EC2 उदाहरण में डेटा सम्मिलित करना
जैसा कि ऊपर कहा गया है, हम सिस्टम स्कीमा को पुनर्स्थापित नहीं करना चाहते हैं। इसलिए हम उन स्कीमा से संबंधित फाइलों को हमारी mydumper निर्देशिका से बाहर ले जाएंगे:
[email protected]:~# mkdir /tmp/rdsdump_sys/
[email protected]:~# mv /tmp/rdsdump/mysql* /tmp/rdsdump_sys/
[email protected]:~# mv /tmp/rdsdump/sys* /tmp/rdsdump_sys/
जब हम इसके साथ हो जाते हैं, तो डेटा को MySQL/EC2 इंस्टेंस में लोड करना शुरू करने का समय आ गया है:
[email protected]:~/mydumper# ./myloader -d /tmp/rdsdump/ -u tpcc -p tpccpass -t 4 --overwrite-tables -h 172.30.4.238
कृपया ध्यान दें कि हमने चार थ्रेड्स (-t 4) का उपयोग किया है - सुनिश्चित करें कि आपने इसे अपने परिवेश में जो कुछ भी समझ में आता है, उसे सेट किया है। यह लक्ष्य MySQL इंस्टेंस को संतृप्त करने के बारे में है - या तो सीपीयू या आई / ओ, अड़चन के आधार पर। हम डेटा को लोड करने के लिए सभी उपलब्ध संसाधनों का उपयोग सुनिश्चित करने के लिए जितना संभव हो उतना निचोड़ना चाहते हैं।
मुख्य डेटा लोड होने के बाद, दो और कदम उठाने होंगे, दोनों आरडीएस आंतरिक से संबंधित हैं और दोनों हमारी प्रतिकृति को तोड़ सकते हैं। सबसे पहले, RDS में mysql स्कीमा में कुछ rds_* टेबल होते हैं। यदि उनमें से कुछ आरडीएस द्वारा उपयोग किए जाते हैं तो हम उन्हें लोड करना चाहते हैं - अगर हमारे दास के पास नहीं होगा तो प्रतिकृति टूट जाएगी। हम इसे निम्नलिखित तरीके से कर सकते हैं:
[email protected]:~/mydumper# for i in $(ls -alh /tmp/rdsdump_sys/ | grep rds | awk '{print $9}') ; do echo $i ; mysql -ppass -uroot mysql < /tmp/rdsdump_sys/$i ; done
mysql.rds_configuration-schema.sql
mysql.rds_configuration.sql
mysql.rds_global_status_history_old-schema.sql
mysql.rds_global_status_history-schema.sql
mysql.rds_heartbeat2-schema.sql
mysql.rds_heartbeat2.sql
mysql.rds_history-schema.sql
mysql.rds_history.sql
mysql.rds_replication_status-schema.sql
mysql.rds_replication_status.sql
mysql.rds_sysinfo-schema.sql
इसी तरह की समस्या टाइमज़ोन टेबल के साथ है, हमें आरडीएस इंस्टेंस से डेटा का उपयोग करके उन्हें लोड करने की आवश्यकता है:
[email protected]:~/mydumper# for i in $(ls -alh /tmp/rdsdump_sys/ | grep time_zone | grep -v schema | awk '{print $9}') ; do echo $i ; mysql -ppass -uroot mysql < /tmp/rdsdump_sys/$i ; done
mysql.time_zone_name.sql
mysql.time_zone.sql
mysql.time_zone_transition.sql
mysql.time_zone_transition_type.sql
जब यह सब तैयार हो जाए, तो हम RDS (मास्टर) और हमारे MySQL/EC2 इंस्टेंस (दास) के बीच प्रतिकृति सेट कर सकते हैं।
प्रतिकृति सेट करना
Mydumper, एक सुसंगत डंप करते समय, एक बाइनरी लॉग स्थिति लिखता है। हम इस डेटा को डंप निर्देशिका में मेटाडेटा नामक फ़ाइल में पा सकते हैं। आइए इसे देखें, फिर हम प्रतिकृति सेटअप करने के लिए स्थिति का उपयोग करेंगे।
[email protected]:~/mydumper# cat /tmp/rdsdump/metadata
Started dump at: 2017-02-03 16:17:29
SHOW SLAVE STATUS:
Host: 10.1.4.180
Log: mysql-bin-changelog.007079
Pos: 10537102
GTID:
Finished dump at: 2017-02-03 16:44:46
एक आखिरी चीज जो हमारे पास नहीं है वह एक उपयोगकर्ता है जिसका उपयोग हम अपने दास को स्थापित करने के लिए कर सकते हैं। आइए RDS उदाहरण पर एक बनाएं:
[email protected]:~# mysql -ppassword -h rds2.cvsw8xpajw2b.us-east-1.rds.amazonaws.com
mysql> CREATE USER IF NOT EXISTS 'rds_rpl'@'%' IDENTIFIED BY 'rds_rpl_pass';
Query OK, 0 rows affected (0.04 sec)
mysql> GRANT REPLICATION SLAVE ON *.* TO 'rds_rpl'@'%';
Query OK, 0 rows affected (0.01 sec)
अब हमारे MySQL/EC2 सर्वर को RDS इंस्टेंस से बंद करने का समय आ गया है:
mysql> CHANGE MASTER TO MASTER_HOST='rds2.cvsw8xpajw2b.us-east-1.rds.amazonaws.com', MASTER_USER='rds_rpl', MASTER_PASSWORD='rds_rpl_pass', MASTER_LOG_FILE='mysql-bin-changelog.007079', MASTER_LOG_POS=10537102;
Query OK, 0 rows affected, 2 warnings (0.03 sec)
mysql> START SLAVE;
Query OK, 0 rows affected (0.02 sec)
mysql> SHOW SLAVE STATUS\G
*************************** 1. row ***************************
Slave_IO_State: Queueing master event to the relay log
Master_Host: rds2.cvsw8xpajw2b.us-east-1.rds.amazonaws.com
Master_User: rds_rpl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin-changelog.007080
Read_Master_Log_Pos: 13842678
Relay_Log_File: relay-bin.000002
Relay_Log_Pos: 20448
Relay_Master_Log_File: mysql-bin-changelog.007079
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 10557220
Relay_Log_Space: 29071382
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 258726
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 1237547456
Master_UUID: b5337d20-d815-11e6-abf1-120217bb3ac2
Master_Info_File: mysql.slave_master_info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: System lock
Master_Retry_Count: 86400
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set:
Executed_Gtid_Set:
Auto_Position: 0
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:
1 row in set (0.01 sec)
अंतिम चरण हमारे ट्रैफ़िक को RDS इंस्टेंस से MySQL/EC2 पर स्विच करना होगा, लेकिन हमें इसे पहले पकड़ने देना होगा।
जब दास ने पकड़ लिया है, तो हमें एक कटओवर करने की आवश्यकता है। इसे स्वचालित करने के लिए, हमने एक छोटी बैश स्क्रिप्ट तैयार करने का निर्णय लिया जो ProxySQL से कनेक्ट होगी और वह करेगी जो करने की आवश्यकता है।
# At first, we define old and new masters
OldMaster=rds2.cvsw8xpajw2b.us-east-1.rds.amazonaws.com
NewMaster=172.30.4.238
(
# We remove entries from mysql_replication_hostgroup so ProxySQL logic won’t interfere
# with our script
echo "DELETE FROM mysql_replication_hostgroups;"
# Then we set current master to OFFLINE_SOFT - this will allow current transactions to
# complete while not accepting any more transactions - they will wait (by default for
# 10 seconds) for a master to become available again.
echo "UPDATE mysql_servers SET STATUS='OFFLINE_SOFT' WHERE hostname=\"$OldMaster\";"
echo "LOAD MYSQL SERVERS TO RUNTIME;"
) | mysql -u admin -padmin -h 127.0.0.1 -P6032
# Here we are going to check for connections in the pool which are still used by
# transactions which haven’t closed so far. If we see that neither hostgroup 10 nor
# hostgroup 20 has open transactions, we can perform a switchover.
CONNUSED=`mysql -h 127.0.0.1 -P6032 -uadmin -padmin -e 'SELECT IFNULL(SUM(ConnUsed),0) FROM stats_mysql_connection_pool WHERE status="OFFLINE_SOFT" AND (hostgroup=10 OR hostgroup=20)' -B -N 2> /dev/null`
TRIES=0
while [ $CONNUSED -ne 0 -a $TRIES -ne 20 ]
do
CONNUSED=`mysql -h 127.0.0.1 -P6032 -uadmin -padmin -e 'SELECT IFNULL(SUM(ConnUsed),0) FROM stats_mysql_connection_pool WHERE status="OFFLINE_SOFT" AND (hostgroup=10 OR hostgroup=20)' -B -N 2> /dev/null`
TRIES=$(($TRIES+1))
if [ $CONNUSED -ne "0" ]; then
sleep 0.05
fi
done
# Here is our switchover logic - we basically exchange hostgroups for RDS and EC2
# instance. We also configure back mysql_replication_hostgroups table.
(
echo "UPDATE mysql_servers SET STATUS='ONLINE', hostgroup_id=110 WHERE hostname=\"$OldMaster\" AND hostgroup_id=10;"
echo "UPDATE mysql_servers SET STATUS='ONLINE', hostgroup_id=120 WHERE hostname=\"$OldMaster\" AND hostgroup_id=20;"
echo "UPDATE mysql_servers SET hostgroup_id=10 WHERE hostname=\"$NewMaster\" AND hostgroup_id=110;"
echo "UPDATE mysql_servers SET hostgroup_id=20 WHERE hostname=\"$NewMaster\" AND hostgroup_id=120;"
echo "INSERT INTO mysql_replication_hostgroups VALUES (10, 20, 'hostgroups');"
echo "LOAD MYSQL SERVERS TO RUNTIME;"
) | mysql -u admin -padmin -h 127.0.0.1 -P6032
जब सब कुछ हो जाए, तो आपको mysql_servers तालिका में निम्न सामग्री दिखाई देनी चाहिए:
mysql> select * from mysql_servers;
+--------------+-----------------------------------------------+------+--------+--------+-------------+-----------------+---------------------+---------+----------------+-------------+
| hostgroup_id | hostname | port | status | weight | compression | max_connections | max_replication_lag | use_ssl | max_latency_ms | comment |
+--------------+-----------------------------------------------+------+--------+--------+-------------+-----------------+---------------------+---------+----------------+-------------+
| 20 | 172.30.4.238 | 3306 | ONLINE | 1 | 0 | 100 | 10 | 0 | 0 | read server |
| 10 | 172.30.4.238 | 3306 | ONLINE | 1 | 0 | 100 | 10 | 0 | 0 | read server |
| 120 | rds2.cvsw8xpajw2b.us-east-1.rds.amazonaws.com | 3306 | ONLINE | 1 | 0 | 100 | 10 | 0 | 0 | |
| 110 | rds2.cvsw8xpajw2b.us-east-1.rds.amazonaws.com | 3306 | ONLINE | 1 | 0 | 100 | 10 | 0 | 0 | |
+--------------+-----------------------------------------------+------+--------+--------+-------------+-----------------+---------------------+---------+----------------+-------------+
आवेदन पक्ष पर, आपको कुछ समय के लिए प्रश्नों को कतारबद्ध करने के लिए प्रॉक्सीएसक्यूएल की क्षमता के लिए धन्यवाद, अधिक प्रभाव नहीं देखना चाहिए।
इसके साथ हमने आपके डेटाबेस को RDS से EC2 में ले जाने की प्रक्रिया पूरी की। हमारे RDS गुलाम को हटाने के लिए अंतिम चरण है - इसने अपना काम किया और इसे हटाया जा सकता है।
अपने अगले ब्लॉग पोस्ट में, हम उस पर निर्माण करेंगे। हम एक ऐसे परिदृश्य से गुजरेंगे जिसमें हम अपने डेटाबेस को AWS/EC2 से अलग होस्टिंग प्रदाता में स्थानांतरित कर देंगे।