Real-Time Replication From DynamoDB to MongoDB

Posted by MinhHungTrinh on 2021-01-17
Estimated Reading Time 10 Minutes
Words 1.7k In Total
Viewed Times

Đây là bài mình viết cũng đã trình bày trên blog kaopiz.kipalog của công ty.

Cái tựa đề chắc hẳn cũng gây cho mọi người thắc mắc. Tại sao lại phải làm cái việc trời ơi đất hỡi này. Bởi vì Dynamo nó là kiểu dạng serverless. Data đặt trên nó được AWS đảm bảo là bền vững rồi. Việc chúng ta replicate tới 1 nơi thì nơi đó thì chưa chắc nơi chúng ta replicate có bền vững khi có thảm họa (chết region luôn chẳng hạn) xảy ra :))) . Cực chẳng đã phải làm, chả là dự án của mình vì đặc thù về license nên có nhiệm vụ phải replicate tất cả data ở production tới 1 onpremise server nhằm mục đích đặc thù của dự án. Hệ thống mình thì bảo gồm 2 loại data là SQL (MySQL) và NoSQL (Dynamo). Ở phần trước thì mình đã mô tả cách replicate thêm 1 con slave từ Aurora rồi. Hôm nay thì mình mô tả cách Replicate data ở DynamoDB.

1. Usecases

Thực ra thì ngoài lý do lấy licence của dự án mình mà phải replicate data từ Dynamo sang MongoDB. Thì chúng ta còn có vài usecases có thể để cho bạn áp dụng như sau:

  • Tạo riêng MongoDB để thực hiện queries các mà đánh indexs khác với DynamoDB. Việc truy vấn ở DynamoDB và MongoDB có nhiều điểm khác biệt nhé. Cá nhân mình thấy Mongo dễ dàng hơn nhiều. Chắc mình sẽ làm 1 bài so sánh về nó sau.
  • Bản Replicate sang MongoDB có thể bổ sung nhiều fields hơn hoặc các fields được convert (cái này được làm khi thực hiện replicate). Và chúng ta sử dụng MongoDB này cho 1 ứng dụng khác chẳng hạn.
  • Và case cuối là làm 1 bản backup data vì nhiều mục đích. Kiểu như gần giống case của mình

Cần phải clear lại là DynamoDB và MongoDB là 2 loại database khác hoàn toàn với nhau. Nó chỉ đơn giản cùng là NoSQL. Dynamo cũng chỉ support trên hệ infra của AWS thôi. Vì vậy chúng ta không có cách nào để tạo 1 replicate ở external server cả. Giải pháp của mình ở đây chỉ là migrate data của Dynamo sang Mongo (Insert, Update, Delete) qua Dynamo Stream, Lambda function. Hơn nữa việc migrate thông thường thì là migrate cả cục data, dễ gây ảnh hưởng đến hệ thống, downtime. Để đảm bảo tính realtime thì chúng ta sử dụng Dynamo Stream. Vậy ae cùng bắt tay vào sửa soạn cho 1 tâm hồn đẹp nhé.

main

  • Cần có Dynamo Table để test nhé
  • Cài đặt MongoDB trên External server (EC2 như hình hoặc Onpremise)
  • Enable Dynamo Stream
  • Tạo lambda function để stream data tới external server.

Cần phải nói thêm là việc giao tiếp giữa các Dynamo xong tới Lambda và đi ra 1 external server. Nếu external server là 1 EC2 thì đơn giản rồi. Cùng account thì giao tiếp qua private network, khác account thì VPC peering nó với nhau. Còn nếu External Server là 1 onpremise data center giống như case của mình. Mình nghĩ và đang làm để đảm bảo security, dự án mình đã thiết lập kết nối giữa hệ thống infra của AWS với onpremise qua hệ VPN Site to Site connection.

2. Practices

2.1. Cài đặt MongoDB trên External Server

Mình request Onpremise Server là ubuntu nên cái đặt theo hướng dẫn của ubuntu thôi. Cái này các bạn follow theo link này. Nhớ là phải thiết lập security và enable bindIP để access được từ remote nhé. Mặc định thì mongo nó k có security và chỉ truy cập từ localhost.
https://docs.mongodb.com/manual/tutorial/install-mongodb-on-ubuntu/ Mình thì xơi luôn bản latest
https://medium.com/mongoaudit/how-to-enable-authentication-on-mongodb-b9e8a924efac . Mình cũng khuyên là nên tạo 1 user cho mục đích replicator riêng (read write trên backup database) chứ không dùng admin user.

2.2. Dynamo

Điều kiện cần là bạn phải có sẵn DynamoDB nhé. Nếu bạn không có thì hãy vào tạo luôn 1 table ở console nhé hoặc CLI. Mình sẽ không viết chi tiết về mấy cái này.

Tiếp theo chúng ta cần Enable Dynamo Stream của table đó.
Click vào phần Overview => Manage Stream và thực hiện enable như hình nhé.

main

main

2.3. Tạo Role cho Lambda function

Chúng ta tạo 1 Role có attach các policies như hình dưới:

main

Tất nhiên với các policies ở trên permission vẫn đang rất rộng. Để securitty chúng ta có thể customize để giới hạn bớt permission đi. Nhưng theo mình chỉ nên giới hạn region, resource mà interact tới thôi. không nên loại bỏ bớt action.

2.4. Build code

Các bạn có thể pull code về từ github của mình: https://github.com/MinhHungTrinh/DynamoRepilcateMongo. Có hướng dẫn cài đặt luôn ở Readme luôn.

Vì code ví dụ này được code từ python nên ae cài sẵn python cho mình nhé. Nhảy và thư mục root nhé.

  • Cài đặt package:
    1
    2
    pip install --target ./package pymongo
    pip install --target ./package dynamodb_json
  • Zip cái thư mục package lại
    1
    2
    cd package
    zip -r9 ${OLDPWD}/function.zip .

Thêm file function code vào file zip. Vì muốn upload lên lambda function thì phải zip hết code và packages lại nên chúng ta phải làm thế này.

1
2
cd $OLDPWD
zip -g function.zip replicator.py

2.5 Tạo lambda function

Cần lưu ý đính kèm các thông tin như:

  • Role chúng ta tạo ở trên
  • VPC, Subnets, SecurityGroups cái mà chúng ta mong muốn đặt lambda serverless lên đó. Thực ra nếu các bạn giao tiếp với EC2 trong mạng AWS thì không cần config này. Nhưng như mình nói ở trên, hệ thống của mình replicate với onpremise qua VPN Site to Site. Vì vậy cần phải cung cấp đầy đủ để firewall của các site có thể allow cho việc giao tiếp.
  • Thay đổi timeout, mình đặt ở đây 60s chẳng hạn
  • Sửa cho handler trỏ tới hàm lambda_handler trong code lambda
  • Thêm các biến môi trường để phù hợp với source code nhé
1
2
3
database:   <database_name_of_mongo>
eventSourceARN: arn:aws:dynamodb:<region-name>:<account-id>
mongodburl: mongodb://<myuser>:<mypwd>@<IP_address_of_onpremise>:27017/<database_name_of_mongo>
  • Cuối cùng là upload file zip source code ở trên.
    Nếu bạn nào dùng CLI thì tham khảo command này cũng tiện :
1
2
3
4
5
6
7
8
aws lambda create-function --function-name Replicator \
--handler replicator.lambda_handler \
--zip-file fileb://function.zip \
--runtime python3.8 \
--timeout 60 \
--role arn:aws:iam::xxxxxxxxxxx:role/lambda-dynamodb-role \
--environment 'Variables={mongodburl="mongodb://<myuser>:<mypwd>@<IP_address_of_onpremise>:27017/<database_name_of_mongo>",database="<database_name_of_mongo>",eventSourceARN="arn:aws:dynamodb:<region-name>:<account-id>"}' \
--vpc-config 'SubnetIds=subnet-id1,subnet-id2,subnet-id3,SecurityGroupIds=sg-id'

2.6. Thêm Trigger cho lambda từ DynamoDB

  • Click Add trigger

main

  • Lựa chọn DynamoDB

main

  • Trỏ tất cả các tables bạn muốn replicate nhé

main

Bây giờ cứ update là ok r.

2.7. Thêm dữ liệu để test

Thêm data vào Dynamo và sang kiểm tra trên Mongo database xem đã có data chưa nhé. Bạn có thể vào phần monitor để theo dõi, trong đó có CloudwatchLogs. Nếu như có bất kỳ lỗi gì thì có thể đọc log để check xem còn bug chỗ nào không nhé.
main

Kết luận

Khi mình làm task thực tế này thì có tham khảo từ https://www.percona.com/blog/2020/05/20/real-time-replication-from-dynamodb-to-mongodb/ và customize từ đó. Bài viết còn sơ sài, có thể khi thực hành sẽ có bug nên ae đóng góp hoặc liên hệ mình nhé. Cảm ơn mọi người vì đã đọc đến tận đây :D


Đây là Blog cá nhân của MinhHungTrinh, nơi mình chia sẻ, lưu giữ kiến thức. Nếu các bạn có góp ý, thắc mắc thì vui lòng comment bên dưới cho mình biết nhé. Mình luôn là người lắng nghe và ham học hỏi. Các vấn đề đặc biệt hoặc tế nhị mọi người có thể gửi email tới minhhungtrinhvn@gmail.com. Cảm ơn Mọi Người đã đọc Blog của mình. Yolo!