Nhân rộng cơ sở dữ liệu với Docker Hình ảnh MySQL, ứng dụng Rails

Tram Ho

Hôm nay mình sẽ giới thiêu cho các bạn các config một ứng dụng web sử dụng kiến trúc database replication.

Trước khi bắt đầu thì đảm bảo rằng máy tính của bạn đã cài những chương trình sau:

  • Docker
  • Ruby on Rails v6.0
  • MySQL Workbench

References

Nếu bạn không biết kiến trúc database replication là gì thì có thể tham khảo bài viết sau để hiểu thêm
https://kipalog.com/posts/Gioi-thieu-MySQL-Replication

Ngoài ra, bài viết này mình còn tham khảo thêm ở các link sau:
https://github.com/wagnerjfr/mysql-master-slaves-replication-docker
https://tomkadwill.com/multiple-databases-in-rails

1. Overview

Mình sẽ build một ví dụ về ứng dụng web bằng framework Rails, có database sử dụng kiến trúc Replication, gồm 1 master và 2 slave. Công việc mà chúng ta cần phải làm sẽ gồm 2 công việc chính:

  • Thiết lập kiến trúc Replication ở tầng Database
  • Xây dựng Web app có thể đọc và ghi dữ liệu với kiến trúc database đã xây dựng.

2. Xây dựng kiến trúc Master Slave với MySQL

Trên thực tế, khi xây dựng kiến trúc Master Slave, thì mỗi instance sẽ nằm ở mỗi host khác nhau, tuy nhiên lúc thực hiện demo này mình chỉ có thể sử dụng 1 máy tính mà thôi, cho nên mình sẽ sử dụng docker để có thể tạo ra các intance Mysql server để xây dựng.

2.1 Cài đặt Mysql Server docker container

Khởi tạo một docker network

Để xem các docker network đang có, sử dụng câu lệnh

Sử dụng các dòng lệnh dưới đây để khởi tạo 3 MySQL container.

Có thể kiếm tra các container đã start hay chưa bằng câu lệnh

Chờ đến khi các container đạt trạng thái healthy thì mới tiếp tục.

2.2 Configuring Master và Slave

2.2.1 Cài đặt Master Node

[Optional] Nếu như bạn muốn sử dụng cơ chế semisynchronous replication, thì hãy chạy câu lệnh bên dưới

Việc cài đặt plugin semisynchronous nhầm mục đích giảm thiểu việc lag dữ liệu trong quá trình đồng bộ data giữa master và slave.

Nếu cài thành công thì sẽ có output như sau

Khởi tạo ở master node một user replicate để các slave có thể access vào và lấy dữ liệu.

Output:

2.2.2 Cài đặt Slaves Node

Tương tự, để có thể sử dụng được cơ chế semisynchronous thì ở các node slave cần cài đặt plugin

Output

Thay đổi tên của log file ở Master Node mà chúng ta đã print ra trước khi chạy câu lệnh setting ở slave node

Giá trị cần thay đổi theo hệ thống trên máy của bản:

Chạy lệnh bên dưới để setting Slave Node

Kiểm tra trạng thái slave replication trên slave1slave2:

Nếu output tương tự như bên dưới thì thành công.

2.2.3 Testing kết quả cài đặt

Bây giờ mình sẽ kiểm tra xem kết quả cài đặt có thành công hay không bằng cách tạo một database mới ở Master Node, nếu đúng thì sẽ đồng bộ database đó sang Slave Node.
Thực hiện chạy câu lệnh bên dưới ở Master Node

Output:

Kiểm tra ở slave node đã được đồng bộ sang hay chưa

Nếu output ra ở 2 slave node đều tồn tại Database TEST thì xem như chúng ta đã cài đặt thành công.

2.3 Lưu ý nhỏ

Khi cài đặt các instance mysql server với docker, thì đê có thể access mysql từ môi trường bên ngoài vào trong docker container thì bạn cần tạo một account mysql vào cấp quyền cho nó như sau (sử dụng để access với mysql workbench hoặc một ứng dụng rails truy xuất vào như demo mà mình thực hiện bên dưới):

B1: Vào bash của docker container

B2: Mở terminal của mysql server

B3: Thực hiện các dòng lệnh sau:

Kí hiệu (%) nghĩa là allow tất cả ip có thể truy cập vào. Nếu bạn muốn hạn chế thì có thể thay đổi dấu % bằng ip mà bạn mong muốn truy cập đến database.

3. Xây dựng webapp với Rails framework

3.1 Sử dụng multiple database trong Rails 6

Có 1 điểm thú vị là từ Rails 6 trở đi, thì framework này đã hỗ trợ multiple database, cho nên chúng ta có thể dễ dàng cài đặt ứng dụng của mình sử dụng kiến trúc replication.

Đầu tiên mình khởi tạo web app với rails 6 như sau:

Sau đó dùng lệnh scaffold để generate nhanh một flow CRUD cơ bản

Bây giờ đến phần quan trọng nhất là tiến hành config database, sử dụng kiến trúc replication.

OK, tương tự như việc config multiple database với Rails 6 thì việc config cho database replication cũng tương tự, chỉ khác là chúng ta sẽ thêm vào option

để xác định node nào là node slave.

Sau đó tiến hành create và migrate database

Có 1 chỗ mà bạn nên chú ý, khi mình tiến hành create database thì log chỉ trả về một database master được tạo, nhờ vào option replica: true mà mình đã config. Trong trường hợp không config hoặc là set bằng false, thì sẽ có 3 database được khởi tạo đó là master, slave1 và slave2.

Sau đó trong model, chúng ta sẽ sử dụng hàm connects_to để chỉ định database nào dùng để write và databas nào dùng để đọc. Theo như kiến trúc master-slave thì dữ liệu sẽ được ghi vào master và đọc ở slave.

OK, bây giờ có 1 vấn đề đặt ra là, ở phần overview ban đầu, thì kiến trúc database của mình bao gồm 1 master và 2 slave cơ mà. Tại sao ở trong này mình lại config có 1 node slave mà thôi ?
Đây là một hạn chế khi sử dụng multiple database của Rails khi áp dụng với kiến trúc Replication. Chúng ta chỉ có thể setting 1 Node Master và 1 Node Slave mà thôi. Trong trường hợp sử dụng với 2 Slave trở lên thì mình sẽ tiếp tục hướng dẫn ở section tiếp theo.

Thêm vào đó, có một vấn đề mà Rails 6 đã support chúng ta đó là giải quyết việc lag dữ liệu bằng việc tự động switching read/write database.
Như chúng ta đã biết mỗi request ghi/chỉnh sửa dữ liệu sẽ đươc gửi đến node master, và request đọc dữ liệu sẽ gửi đến node slave. Tuy nhiên trong trường hợp có request gửi đến yêu cầu đọc dữ liệu trong vòng chưa tới 2s sau 1 request write, thì request read đó sẽ được gửi tới node master thay vì slave để đảm bảo có thể đọc được dữ liệu mới nhất thay vì dữ liệu cũ chưa được cập nhật ở slave. Mặc định sẽ là 2s, tuy nhiên chúng ta có thể setting ở file application.rb

Để enable thì chúng ta config như sau ở file application.rb

3.2 Sử dụng gem Makara

Như mình đã đề cập ở trên, thì khi sử dụng multiple với Rails 6, thì nó có 1 nhược điểm là không thể nào sử dụng 2 slave trở lên cho toàn bộ model. Tuy nhiên một số gem lại có thể làm được điều này đó là: OctopusMakara.

Theo như thông báo thì gem Octopus đang ở mode maitain do Rails 6 ra mắt đã có support multiple database. Cho nên mình sẽ sử dụng gem Makara để làm example. Mặc dù publish muộn hơn gem Octopus, nhưng Makara được người dùng đánh giá tốt hơn hẳn so với Octopus.

Còn việc cài đặt gem thì cực kì đơn giản, bạn chỉ cần vào trang document của gem thì hoàn toàn có thể làm đươc.

Ngoài việc cho phép người dùng có thể setup master slave dễ dàng, thì gem Makara còn cho phép chúng ta thêm nhiều tùy biến khác như là điều chỉnh trọng số nhận request của các slave, khả năng thông báo lỗi cũng rất rõ ràng.

Kết luận

Trên đây là phần hướng dẫn của mình về cách cài đặt một kiến trúc database replication, thêm vào đó là cách cấu hình để để sử dụng với một web app Rails cơ bản.
Và các bạn cần lưu ý là tùy vào ứng dụng của bạn và ưu nhược điểm của mỗi loại kiến trúc database để lựa chọn kiến trúc cho phù hợp với ứng dụng của mình.
Hy vọng bài viết mang lại cho bạn nhiều kiến thức bổ ích. Thân

Chia sẻ bài viết ngay

Nguồn bài viết : Viblo