Scaling website with Master Slave configuration

Chào các bạn, ở bài viết hôm nay mình sẽ nói về một giải pháp scale hệ thống khá phổ biến thường được áp dụng bên cạnh giải pháp cân bằng tải (Load balancing) đó là slave/master configuration.

1. Đặt vấn đề

Bài toán đặt ra là mình đang xây dựng một website cho nhiều người sử dụng và website của mình có dữ liệu có thể thay đổi nhiều lần mỗi giây và dữ liệu đó sẽ được cập nhật để hiển thị cho người dùng theo thời gian thực. (Đại loại như mấy website cập nhật giá trị cổ phiếu, chứng khoáng ấy).

2. Giải pháp

Như mọi người đã biết, không giống như MyISAM (một database engine của MySQL yêu cầu lock toàn bộ bảng khi có thao tác modify hay thêm mới dữ liệu) thì đối với InnoDB (một database engine khác của MySQL) nó cải tiến hơn với việc cho phép lock row-level, tức là chỉ có những row tương tác mới bị khóa, các row khác trong table vẫn cho phép truy cập. Tuy nhiên, bài toán đặt ra ban đầu là dữ liệu của mình có thể thay đổi nhiều lần mỗi giây, cùng với đó là một lượng lớn người dùng muốn truy cập để lấy giá trị mới nhất, do đó nếu chỉ sử dụng InnoDB thì độ trễ sẽ rất cao. Giải pháp mà mình lựa chọn đó là cấu hình database theo mô hình slave/master. Với master-slave configuration, các thao tác liên quan đến modify hay thêm mới dữ liệu (updates, deletes, inserts) sẽ được gửi đến master database, và nó sẽ ghi lại thay đổi đến một file binary log, nhiệm vụ của slave là đọc các queries từ file binary log và thực thi chúng. Khi slave starts up thì nó sẽ kết nối đến master, sau đó thực thi tuần tự các câu lệnh SQL để đảm bảo dữ liệu luôn được đồng bộ với master theo cách hoàn hảo nhất. Vậy làm sao để slave biết được có query mới được thực hiện trên master, cơ chế ở đây là khi có sự kiện modify hoặc thêm mới ở master, sự kiện đó sẽ được chuyển phát đến slave bằng việc ghi nó vào relay log, tiến trình này được gọi là replication I/O thread. Slave đọc sự kiện từ relay log và thực thi nó một cách tuần tự, tiến trình này được gọi là slave SQL thread. Tất nhiên, khi nhu cầu về khả năng đọc của website tăng lên chúng ta có thể add thêm slave, một ứng dụng web lớn có thể có đến hàng trăm slave cho một master, điều này giúp cải thiện hiệu năng đọc dữ liệu mà không tốn quá nhiều effort. Tuy nhiên, khi có hàng trăm slave như thế thì băng thông cần thiết cho master để phục vụ các slave tăng lên đáng kể, giải pháp cho vấn đề này là ta có thể chuyển đổi một slave nào đó thành master để chịu trách nhiệm trong việc cập nhật một số slave khác. Theo mô hình này, khối lượng công việc sẽ được truyền tải trên nhiều database servers và tất nhiên cần phải phân biệt truy vấn nào là modification và truy vấn nào là read-only.

3. Cấu hình trong Laravel

Laravel cho phép chúng ta cấu hình master/slave database thông qua việc cấu hình read/write. Điều này cho phép developer thoải mái viết Eloquent và Query Builder mà không cần lo lắng queries sẽ được thực thi như thế nào trong slave hay master table. Vì thế, nếu ứng dụng đã viết với non-master/slave configuration thì sau đó có thể dễ dàng setup master/slave. Bây giờ chúng ta sẽ cấu hình master/slave trong Laravel ở file config/database.php như sau:

'mysql' => array(
    'read' => array(
        // Return a random host
        'host' => $readHosts[array_rand($readHosts)],
        'password' => 'slave-Passw0rd',
    ),
    'write' => array(
        'host' => '196.168.1.2',
        'username' => 'dbhostusername'
    ),
    'driver'    => 'mysql',
    'database'  => 'database',
    'username'  => 'root',
    'password'  => '',
    'charset'   => 'utf8',
    'collation' => 'utf8_unicode_ci',
    'prefix'    => '',
),

4. Kết luận

Mặc dù có thể đối mặt với rủi ro data collision nhưng giải pháp slave/master configuration cho bài toán đặt ra ban đầu của mình có vẽ ổn. Ở bài viết sau mình sẽ nói về một giải pháp scale hệ thống khác, cảm ơn các bạn đã đọc.


All Rights Reserved