ในภาคที่ 1 ของบทความนี้ "ทำไมต้องย้ายฐานข้อมูล Dynomite ไป Redis Enterprise Active-Active?" เราได้เปรียบเทียบสถาปัตยกรรมและฟีเจอร์ของ Dynomite และ Redis Enterprise แสดงให้เห็นว่า Redis Enterprise ช่วยกระจายข้อมูลข้ามภูมิภาค (geo-distribute) ได้อย่างสมบูรณ์ จัดการง่าย และไม่ต้องกังวลเรื่องข้อขัดแย้งจากการเขียนพร้อมกัน (concurrent writes)
ภาคที่ 2 นี้จะอธิบายตัวเลือกการย้ายข้อมูล (migration options) จาก Dynomite ไป Redis Enterprise
หมายเหตุ: ต่อจากนี้ Redis Enterprise แบบจัดการเอง (self-managed) จะเรียกว่า "Redis Enterprise Software" และแบบบริการจัดการ (managed) จะเรียกว่า "Redis Enterprise Cloud" หรือ "Cloud subscription"
การย้ายฐานข้อมูล Dynomite
มาเริ่มต้นปฏิบัติจริงกับ 2 วิธีการย้าย:
- การย้ายด้วยฟีเจอร์ Import/Export ของ Redis Enterprise
- การย้ายด้วยฟีเจอร์ ReplicaOf ของ Redis Enterprise เรียกอีกอย่างว่า Active-Passive
เพื่อความเข้าใจง่าย สมมติว่ามีคลัสเตอร์ Dynomite ครอบคลุม 2 ศูนย์ข้อมูล (datacenters): dc-a และ dc-b แต่ละศูนย์มี 1 rack และแต่ละ rack ประกอบด้วย 2 โหนด (nodes) ที่กระจายข้อมูลระหว่างกัน
ตามสถาปัตยกรรมของ Dynomite แต่ละ rack จะมีข้อมูลชุดเต็ม (full dataset) ดังนั้นเราสามารถจำกัดขอบเขตการย้าย (Import/Export หรือ Active-Passive) ให้อยู่ที่ rack เดียวในระบบ Dynomite
เลือก rack-1-dc-a และสมมติ IP ของโหนด 2 ตัวคือ:
- a1: 10.0.0.1
- a2: 10.0.0.2
ไฟล์ yaml การตั้งค่า Dynomite สำหรับการทดสอบ:
#a1 dyn_o_mite: datacenter: dc-a dyn_listen: 10.0.0.1:7379 dyn_port: 7379 dyn_seed_provider: simple_provider dyn_seeds: - 10.0.0.3:7379:rack1:dc-a:4294967294 - 10.0.0.4:7379:rack1:dc-b:4294967294 - 10.0.0.2:7379:rack1:dc-b:2147483647 listen: 0.0.0.0:8379 rack: rack1 servers: - 127.0.0.1:6379:1 timeout: 150000 tokens: 2147483647 secure_server_option: datacenter pem_key_file: /root/dynomite/conf/dynomite.pem data_store: 0 stats_listen: 127.0.0.1:22222 read_consistency : DC_QUORUM write_consistency : DC_QUORUM #a2 dyn_o_mite: datacenter: dc-a dyn_listen: 10.0.0.3:7379 dyn_port: 7379 dyn_seed_provider: simple_provider dyn_seeds: - 10.0.0.1:7379:rack1:dc-a:2147483647 - 10.0.0.4:7379:rack1:dc-b:4294967294 - 10.0.0.2:7379:rack1:dc-b:2147483647 listen: 0.0.0.0:8379 rack: rack1 servers: - 127.0.0.1:6379:1 timeout: 150000 tokens: 4294967294 secure_server_option: datacenter pem_key_file: /root/dynomite/conf/dynomite.pem data_store: 0 stats_listen: 127.0.0.1:22222 read_consistency : DC_QUORUM write_consistency : DC_QUORUM #b1 dyn_o_mite: datacenter: dc-b dyn_listen: 10.0.0.2:7379 dyn_port: 7379 dyn_seed_provider: simple_provider dyn_seeds: - 10.0.0.4:7379:rack1:dc-b:4294967294 - 10.0.0.1:7379:rack1:dc-a:4294967294 - 10.0.0.3:7379:rack1:dc-a:2147483647 listen: 0.0.0.0:8379 rack: rack1 servers: - 127.0.0.1:6379:1 timeout: 150000 tokens: 2147483647 secure_server_option: datacenter pem_key_file: /root/dynomite/conf/dynomite.pem data_store: 0 stats_listen: 127.0.0.1:22222 read_consistency : DC_QUORUM write_consistency : DC_QUORUM #b2 dyn_o_mite: datacenter: dc-b dyn_listen: 10.0.0.4:7379 dyn_port: 7379 dyn_seed_provider: simple_provider dyn_seeds: - 10.0.0.2:7379:rack1:dc-b:2147483647 - 10.0.0.1:7379:rack1:dc-a:4294967294 - 10.0.0.3:7379:rack1:dc-a:2147483647 listen: 0.0.0.0:8379 rack: rack1 servers: - 127.0.0.1:6379:1 timeout: 150000 tokens: 4294967294 secure_server_option: datacenter pem_key_file: /root/dynomite/conf/dynomite.pem data_store: 0 stats_listen: 127.0.0.1:22222 read_consistency : DC_QUORUM write_consistency : DC_QUORUM
ข้อสังเกตเกี่ยวกับการตั้งค่าและสภาพแวดล้อมทดสอบ:
- VM 4 ตัวบน GCP รัน Ubuntu 18.04
- VM อยู่ใน VPC เดียวกัน ครอบหลาย region
- เปิดพอร์ต 7379 และ 7380 สำหรับการจำลองข้อมูลของ Dynomite ("dyn_port" ใน yaml)
- Redis OSS รันบนแต่ละโหนดที่พอร์ต 6379 (ดู "servers" ใน yaml)
- Dynomite รับคำขอจากไคลเอนต์ที่พอร์ต 8379 (เช่น redis-cli -h 10.0.0.1 -p 8379) (ดู "listen" ใน yaml)
เข้าใจสภาพแวดล้อมและเลือก rack สำหรับการย้ายแล้ว มาสร้างฐานข้อมูล Redis Enterprise Active-Active กัน
สร้างฐานข้อมูล Redis Enterprise Active-Active
เนื่องจากบทความนี้ไม่ได้เน้นการตั้งค่าคลัสเตอร์หรือสร้างฐานข้อมูล โปรดอ้างอิงเอกสารด้านล่างเพื่อเริ่มต้นใช้งาน Active-Active database:
- Redis Enterprise Software cluster
- Cloud subscription
- Software database creation
- Software Active-Active Database creation
- Cloud database creation
สำหรับทดสอบ 2 สถานการณ์การย้าย ผมสร้าง Active-Active database ครอบ 2 คลัสเตอร์ Redis Enterprise Software – หนึ่งในยุโรป และอีกหนึ่งในสหรัฐอเมริกา แต่ละคลัสเตอร์มี VM 3 ตัวรัน Ubuntu 18.04 หากสร้างฐานข้อมูลโดยไม่มี Active-Active ขั้นตอนการย้ายจะเหมือนกัน เว้นแต่จะระบุไว้ในบทความนี้
เริ่มต้นกับวิธีการย้ายแรกกันเลย
การย้ายด้วยฟีเจอร์ Import/Export
Redis OSS มีตัวเลือก persistence เรียกว่า Redis Database Backup Files (RDB) ทำ snapshot จุดเวลา (point-in-time) ของชุดข้อมูล ไม่ว่าจะเป็นช่วงเวลาที่กำหนดหรือกระตุ้นด้วยคำสั่ง SAVE หรือ BGSAVE
Snapshot ถูกบันทึกในไฟล์ .rdb (RDB files) เราจะ export จากเซิร์ฟเวอร์ Dynomite และ import เข้า Redis Enterprise database ด้วยวิธีนี้ โปรดทราบว่าไม่สามารถทำ delta migration ได้ และการ import อาจใช้เวลานาน ขึ้นอยู่กับขนาดข้อมูล
สำคัญ: มีความแตกต่างใหญ่ระหว่างฐานข้อมูล Redis Enterprise ที่ไม่ได้กระจายข้ามภูมิภาค (non-geo-distributed) และ Active-Active databases:
- Non geo-distributed databases: เมื่อ import ไฟล์ RDB เนื้อหาฐานข้อมูลเดิมจะถูกลบทั้งหมด
- Active-Active databases: สามารถ import ไฟล์ RDB และรวม (merge) เข้ากับชุดข้อมูลที่มีอยู่ได้ หมายความว่าคุณสามารถส่งการเขียน (write traffic) ไปที่ Active-Active database ก่อนและระหว่างการ import ระวัง – หากคุณเขียนคีย์ที่มีอยู่ใน Dynomite แล้ว การ import ต่อไปอาจทับค่าใหม่ด้วยค่าเก่า! ต้องวางแผนอย่างระมัดระวัง
ขั้นตอนการย้ายข้อมูลจาก Dynomite ไป Redis Enterprise ด้วยไฟล์ RDB:
- หยุดการเข้าถึง (traffic) บนฐานข้อมูล Dynomite และ หากวางแผนการย้ายอย่างรอบคอบ และใช้ Active-Active database ให้ cutover ไปที่ Redis Enterprise database
- Export ข้อมูลของแต่ละโหนด (a1 และ a2 ในกรณีนี้) เป็นไฟล์ RDB
- อัปโหลดไฟล์ RDB ไปที่สตอเรจภายนอกที่เข้าถึงได้จากคลัสเตอร์ Redis Enterprise (เช่น Google Cloud Storage bucket, AWS S3 bucket, FTP server, ฯลฯ)
- Import ไฟล์ RDB เข้า Redis Enterprise database
- Cutover traffic ไปที่ Redis Enterprise database
มาเช็คขั้นตอนละเอียดกัน
ตัวเลือก: แก้ไขไฟล์ตั้งค่า Redis OSS บนแต่ละโหนด
Redis OSS instances บนโหนด Dynomite มีไฟล์ตั้งค่าอยู่ที่ /etc/redis โดยค่าเริ่มต้น (หากติดตั้งด้วย apt-get) หรือในโฟลเดอร์ Redis หาก build เอง ไฟล์ชื่อ "redis.conf"
เปิดไฟล์ด้วย text editor ที่ชอบ ค้นหา directive "dbfilename" เปลี่ยนชื่อไฟล์บนแต่ละโหนด เช่น
- "dump1.rdb" บน node1
- "dump2.rdb" บน node2
เพื่อให้ไฟล์ RDB ที่ export ไปสตอเรจภายนอกไม่มีชื่อซ้ำกัน คุณข้ามขั้นตอนนี้และเปลี่ยนชื่อหลัง snapshot ก็ได้
เพิ่มเติม คุณยังสามารถ:
- เปลี่ยนไดเรกทอรีที่เก็บไฟล์ RDB ด้วย directive "dir"
- เปลี่ยนช่วงเวลา snapshot หรือปิด automatic snapshotting ในบทความนี้จะใช้คำสั่ง SAVE ของ Redis เพื่อกระตุ้น snapshot เพื่อให้แน่ใจว่า dump ชุดข้อมูลเต็มหลังหยุด traffic
หมายเหตุ: หลังแก้ไขไฟล์ตั้งค่า Redis OSS ต้อง restart Redis OSS server เพื่อให้การเปลี่ยนแปลงมีผล
Dump ข้อมูล
หยุด traffic เข้าฐานข้อมูล Dynomite ผ่านพอร์ต 8379 อีกครั้ง หาก import ไป Active-Active database และวางแผนอย่างรอบคอบ ไม่เสี่ยงการทับซ้อนขณะ import สามารถ cutover traffic ไป Active-Active database ได้
เปิด redis-cli อย่าใช้พอร์ต 8379 (พอร์ตฟังของ Dynomite) ใช้พอร์ต 6379 แทน เพราะเราต้องเชื่อมต่อกับ Redis OSS instance บนโหนด ไม่ใช่ Dynomite cluster ซึ่งไม่รองรับคำสั่ง SAVE สามารถรัน redis-cli โดยไม่ต้องใส่ argument
บนแต่ละโหนด รันคำสั่ง DBSIZE จะได้จำนวนคีย์ที่จัดเก็บบนแต่ละ Redis OSS instance ผลรวมควรเท่ากับจำนวนคีย์ในฐานข้อมูล Dynomite
#a1 127.0.0.1:6379> dbsize (integer) 1323 #a2 127.0.0.1:6379> dbsize (integer) 1371
รันคำสั่ง SAVE และตรวจสอบว่าไฟล์ RDB ถูกสร้างใน /var/lib/redis หรือไดเรกทอรีที่ระบุ
Export ไฟล์ dump ทั้งสองไปที่สตอเรจภายนอก
พร้อม export ไฟล์ RDB 2 ไฟล์ไปสตอเรจภายนอกแล้ว
ในบทความนี้จะ export ไป Google Cloud Storage แต่ก็ใช้ตัวเลือกอื่นได้ เช่น FTP Server, cloud storage อื่น, หรือ external disk ที่เข้าถึงได้จากคลัสเตอร์ Redis Enterprise ดูรายละเอียดเพิ่มเติม:
- Redis Enterprise Software
- Redis Enterprise Cloud
บน Google Cloud ได้สร้าง:
- Service account พร้อม JSON key
- Cloud storage bucket มอบสิทธิ์ Storage Legacy Object Reader ให้ service account
รันคำสั่งต่อไปนี้สำหรับแต่ละโหนด:
gsutil cp path_to_dump_file gs://your_bucket
ตอนนี้เห็นไฟล์ RDB 2 ไฟล์ใน bucket แล้ว:
พร้อม import เข้า Active-Active database แล้ว
Import ไฟล์ dump เข้า Redis Enterprise database
ล็อกอิน Redis Enterprise UI เลือก Active-Active database หากสร้าง Active-Active database ครอบหลายคลัสเตอร์ (เหมือนบทความนี้) สามารถเชื่อมต่อ UI ผ่านคลัสเตอร์ไหนก็ได้ ในที่นี้ใช้คลัสเตอร์ยุโรป (EU)
หากใช้ Cloud Active-Active database ให้เชื่อมต่อ Cloud UI และเลือก database
ไปที่หน้าตั้งค่าฐานข้อมูล กดปุ่ม Import เลือก Storage Type ที่เหมาะสม ในที่นี้คือ Google Cloud Storage
เพิ่ม path ของไฟล์ RDB 2 ไฟล์ เช่น:
- /helene-test/dump1.rdb
- /helene-test/dump2.rdb
เพิ่มข้อมูลต่อไปนี้:
- client ID
- client email
- private key ID
- private key
ข้อมูลเหล่านี้อยู่ในไฟล์ JSON key ที่ดาวน์โหลดตอนสร้าง key ให้ Google Cloud Service Account
Private key ใน JSON มีรูปแบบแปลก มี quotation marks และ newlines เพื่อจัดรูปแบบให้ Redis Enterprise UI ยอมรับ ให้เปิด python interpreter และ print:
print(WHOLE_COPIED_KEY)
ได้การตั้งค่า import ดังนี้:
กด Import และรอจนเสร็จ (ขึ้นอยู่กับขนาดฐานข้อมูล)
ตรวจสอบฐานข้อมูลและ Cutover
เชื่อมต่อ redis-cli ไปที่ endpoint ของ Redis Enterprise database ลองอ่านคีย์บางตัว และรัน DBSIZE เพื่อเช็คจำนวนคีย์ทั้งหมด
redis-12000.internal.helene-eu-cluster.demo.redislabs.com:12000> dbsize (integer) 2694
อย่าลืมเช็ค Active-Active Geo-Duplication ด้วย! เชื่อมต่อ endpoint ของคลัสเตอร์อีกตัว (ในที่นี้คือ U.S.) และเช็คจำนวนคีย์
การย้ายเสร็จสิ้น คุณสามารถ cutover traffic ไปที่ database ได้เลย หากยังไม่ได้ทำ
การย้ายด้วยฟีเจอร์ ReplicaOf
มาทำ continuous migration กัน
ฟีเจอร์ 'ReplicaOf' ของ Redis Enterprise (เรียกว่า Active-Passive ใน Redis Cloud UI) อนุญาตให้ replicate ข้อมูลระหว่าง 2 ฐานข้อมูล Redis อย่างต่อเนื่อง ข้อได้เปรียบหลักคือ replicate deltas หลัง initial synchronization เสร็จสิ้น ทำให้ application-side downtime เกือบเป็นศูนย์
ขั้นตอน:
- สร้างลิงก์ ReplicaOf ระหว่างฐานข้อมูล Dynomite และ Active-Active database
- รอจน initial synchronization เสร็จ
- หยุด traffic บนฐานข้อมูล Dynomite
- รอจน delta replicated เสร็จ
- ลบลิงก์ ReplicaOf ระหว่างฐานข้อมูล
- Cutover ไป Active-Active database
ReplicaOf ใช้แบบ Active-Passive หมายถึง target ถือว่า passive และต้องทนได้ว่า target จะถูก re-synchronized ใหม่ทั้งหมด (flush target database + sync จาก source database)
ก่อนเริ่มย้าย มาพูดถึงด้านความปลอดภัยก่อน
การตั้งค่าความปลอดภัยสำหรับ Redis OSS ใน Dynomite setup
ก่อนอื่น ต้องเพิ่ม inbound rule สำหรับ custom TCP พอร์ต 6379 สำหรับ network ที่ Dynomite rack อยู่
ต่อมา ไฟล์ตั้งค่า Redis OSS บนโหนด Dynomite ทั้งสองต้องอัปเดต โดยค่าเริ่มต้น Redis ฟังเฉพาะ loopback interface (IPv4 และ IPv6 ถ้ามี) หมายถึง Redis OSS จะรับ connection จาก host เดียวที่รันอยู่เท่านั้น ต้องอัปเดต directive "bind" ให้ Redis OSS ฟัง connection จาก Redis Enterprise cluster host
มี 2 วิธี:
- ให้ Redis OSS ฟังเฉพาะ connection จาก machine ใน peered VPC – แนะนำและปลอดภัยกว่า
- อนุญาตให้ Redis OSS เข้าถึงได้จากทุก host – ไม่ปลอดภัย โดยเฉพาะที่ Dynomite ไร้รองรับ database passwords
มาพิจารณา 2 ตัวเลือกนี้ละเอียด
ตัวเลือก 1 – พร้อม VPC Peering
Peering VPC ที่ Dynomite rack อยู่ กับ VPC ที่ Redis Enterprise cluster อยู่ โปรดทราบ Active-Active database อาจอยู่ในคลัสเตอร์ไหนก็ได้ ใช้คลัสเตอร์ยุโรป (EU) สำหรับสาธิต
หลัง peering networks แล้ว แก้ไข directive "bind" ใน redis.conf: เพิ่ม private IP ของเครื่อง Dynomite หลัง loopback interface addresses
ทำซ้ำสำหรับทุกโหนดใน rack และเสร็จแล้ว! อย่าลืม restart Redis OSS instances
ตัวเลือก 2 – ไม่มี VPC Peering
หากไม่สามารถหรือไม่อยาก peer networks ให้อัปเดตไฟล์ตั้งค่า Redis OSS บนแต่ละโหนด:
- Comment directive "bind" ซึ่งจะ expose Redis OSS instance ให้ทุกคนบนอินเทอร์เน็ต
- ตั้ง "protected-mode" เป็น "no" เพื่อให้ client จาก host อื่นเชื่อมต่อ Redis ได้ แม้ไม่มี authentication หรือ bind directive
สำคัญ: ขั้นตอนสุดท้ายนี้จำเป็น เพราะ Dynomite ไม่รองรับคำสั่ง AUTH ของ Redis OSS ทำให้ไม่สามารถตั้ง database password ได้ ดังนั้น หากไม่ใช้ firewall ควบคุมการเชื่อมต่อพอร์ตที่ใช้ ใครก็ตาม จะเชื่อมต่อ Redis OSS instance และเข้าถึง/เปลี่ยน/ลบข้อมูลได้ เปิดพอร์ต 6379 เฉพาะ host ของ Redis Enterprise cluster เท่านั้น
หากอยากใช้ password จริงๆ ก็ทำได้ แต่จะทำให้ continuous migration ไม่ได้ เพราะต้อง:
- หยุด traffic ไป Dynomite database
- แก้ directive "requirepass" ตั้ง password ตั้งแต่นี้ ไม่สามารถส่ง write traffic ไป Dynomite ผ่านพอร์ต 8379 ได้แล้ว เพราะต้องใช้คำสั่ง AUTH
- ทำ migration ด้วย ReplicaOf ตามที่อธิบาย
- Cutover traffic ไป Redis Enterprise database
อีกหนึ่งข้อพิจารณาด้านความปลอดภัย และพร้อมเริ่ม migration แล้ว!
ตัวเลือก – เปิดใช้งาน TLS
เพื่อป้องกันการเข้าถึงข้อมูลโดยไม่ได้รับอนุญาต Redis Enterprise รองรับโปรโตคอล TLS
หากใช้ Redis Enterprise Software สามารถตั้งค่า TLS โดยเฉพาะสำหรับการสื่อสาร ReplicaOf หากใช้ Redis Enterprise Cloud สามารถเปิด TLS แบบทั่วไป
ตั้งค่าลิงก์ ReplicaOf ระหว่างฐานข้อมูล
ใน Redis Enterprise UI ไปที่หน้าตั้งค่า Active-Active database กด Edit
มีตัวเลือกเปิดใช้งาน Active-Passive/ReplicaOf เปิดแล้วเพิ่ม sources ในรูปแบบ:
redis://:@IP:port
โปรดทราบ:
- ReplicaOf รองรับ source สูงสุด 32 ตัว หากกระจายข้อมูลข้ามมากกว่า 32 โหนดใน Dynomite rack จะใช้ตัวเลือกนี้ไม่ได้
- หากใช้ VPC Peering ให้ใช้ private IPs ของเครื่อง
- หากไม่ใช้ VPC Peering:
- ใช้ public IPs ของเครื่อง
- หากตั้ง password (และทำ one-time migration) ให้ระบุ password แบบ: redis://:password@IP:port
ในกรณีนี้ ใช้ VPC Peering sources จะเป็นดังภาพ:
เริ่มการย้าย
ทำตามขั้นตอน:
- กด Update ใน Redis Enterprise UI
- รอ initial synchronization เสร็จ
- หยุด traffic ไป Dynomite database
- รอ delta synchronized เสร็จ
- Update Active-Active database อีกครั้งเพื่อปิด ReplicaOf
- เริ่ม traffic บน Active-Active database
ตรวจสอบข้อมูล
เช่นเดิม เชื่อมต่อ database ด้วย redis-cli เช็คว่าข้อมูลย้ายครบ ตรวจสอบ Active-Active Geo-Duplication ด้วยการเชื่อมต่อ endpoint ของคลัสเตอร์อื่น/ local endpoints อื่น
สรุป
Redis ได้รับการเลือกเป็นฐานข้อมูลที่นักพัฒนาชื่นชอบมาหลายปี หากคุณใช้ Dynomite แสดงว่าคุณชอบ Redis เช่นกัน ที่ Redis – บ้านของทั้ง Redis OSS และ Redis Enterprise – เราช่วยองค์กรของคุณกระจาย Redis ข้ามภูมิภาคได้อย่างจัดการง่ายขึ้น พร้อมรักษามาตรฐานระดับสูงสุดสำหรับการแก้ไขข้อขัดแย้ง (conflict resolution)