Distributed relational database TiDB sử dụng kiến trúc tách biệt giữa phần tính toán và lưu trữ, cho phép mở rộng độc lập từng lớp, giúp giải quyết vấn đề một cách hiệu quả.
Từ sơ đồ kiến trúc tổng thể của TiDB, ta thấy lớp tính toán (TiDB Cluster) chịu trách nhiệm giao tiếp với các ứng dụng bên ngoài thông qua giao thức MySQL. Mỗi TiDB Server là một nút không trạng thái hoạt động độc lập, do đó kết nối tới bất kỳ nút TiDB nào cũng cho phép truy cập dữ liệu cơ sở dữ liệu. Điều này mang lại hai lợi ích:
- Thêm các nút TiDB đơn giản có thể nâng cao khả năng xử lý của cụm.
- Tách biệt yêu cầu TP và AP ở lớp tính toán, đảm bảo chúng hoạt động độc lập.
Tuy nhiên, việc này cũng gây ra vấn đề: nếu có nhiều nút TiDB trong cụm, ứng dụng nên kết nối tới đâu? Việc viết nhiều kết nối cơ sở dữ liệu trong ứng dụng, chẳng hạn như A sử dụng TiDB-1, B sử dụng TiDB-2, rõ ràng không thực tế. Đối với những người quen thuộc với kỹ thuật phân chia cơ sở dữ liệu và đọc/ghi riêng biệt, có thể nghĩ đến việc sử dụng các trung gian cơ sở dữ liệu như MyCat để chuyển tiếp yêu cầu.
Mục đích ban đầu của TiDB là loại bỏ hoàn toàn các mô hình phân chia cơ sở dữ liệu phức tạp, không phụ thuộc vào các trung gian cơ sở dữ liệu. Chúng ta cần một proxy đơn giản để tự động định tuyến các yêu cầu tới các nút TiDB. Trong trường hợp này, các thành phần cân bằng tải hoạt động ở lớp TCP trở nên phù hợp hơn.
Các giải pháp cân bằng tải TiDB
Sau khi nghiên cứu kỹ lưỡng, tôi đề xuất ba giải pháp cân bằng tải TiDB sau đây.
HAProxy
HAProxy là một proxy mã nguồn mở hoạt động ở cả lớp TCP (tầng 4) và HTTP (tầng 7), hỗ trợ nhiều chiến lược cân bằng tải và hiệu suất xuất sắc, được sử dụng rộng rãi. Đây là cách cân bằng tải mà TiDB đề xuất chính thức.
Khi triển khai HAProxy, nó trở thành điểm đơn điệu. Nếu gặp sự cố, toàn bộ cơ sở dữ liệu sẽ không thể truy cập. Do đó, việc xây dựng cân bằng tải đáng tin cậy là không thể tránh khỏi. Tôi đề xuất sử dụng cấu trúc Keepalived + VIP, như dưới đây:
! Configuration File for keepalived
global_defs {
router_id kad_01 # ID duy nhất của nút
}
vrrp_instance tidb_ha {
state MASTER # Vai trò của nút
interface eth0 # Tên card mạng, tùy chỉnh cho môi trường cụ thể
virtual_router_id 51 # ID router ảo, giống nhau trên cả hai nút chính và dự phòng
priority 100 # Mức độ ưu tiên, cao hơn ở nút chính
advert_int 1 # Tần suất kiểm tra giữa chính và dự phòng
authentication {
auth_type PASS
auth_pass tidb666 # Mật khẩu xác thực giữa chính và dự phòng
}
virtual_ipaddress {
10.3.65.200 # Địa chỉ IP ảo
}
}
Bắt đầu dịch vụ:
[root@localhost ~]# systemctl start keepalived
[root@localhost ~]# systemctl status keepalived
Đối với nút dự phòng, cấu hình tương tự nhưng thay đổi các giá trị như sau:
! Configuration File for keepalived
global_defs {
router_id kad_02 # ID duy nhất của nút
}
vrrp_instance tidb_ha {
state BACKUP # Vai trò của nút
interface eth0 # Tên card mạng, tùy chỉnh cho môi trường cụ thể
virtual_router_id 51 # ID router ảo, giống nhau trên cả hai nút chính và dự phòng
priority 50 # Mức độ ưu tiên, thấp hơn ở nút dự phòng
advert_int 1 # Tần suất kiểm tra giữa chính và dự phòng
authentication {
auth_type PASS
auth_pass tidb666 # Mật khẩu xác thực giữa chính và dự phòng
}
virtual_ipaddress {
10.3.65.200 # Địa chỉ IP ảo
}
}
LVS
LVS hỗ trợ ba chế độ hoạt động khác nhau, mỗi chế độ có nguyên tắc hoạt động riêng. Dưới đây tôi giới thiệu cách cấu hình ở chế độ DR (Direct Routing), phổ biến nhất.
Trước hết, cấu hình máy chủ LVS:
[root@localhost ~]# cd /etc/sysconfig/network-scripts
[root@localhost network-scripts]# cp ifcfg-eth0 ifcfg-eth0:1
[root@localhost network-scripts]# vi ifcfg-eth0:1
TYPE="Ethernet"
BOOTPROTO="static"
IPADDR=10.3.65.201 # Địa chỉ IP ảo
NETMASK=255.255.255.0
NAME="eth0:1"
DEVICE="eth0:1"
ONBOOT="yes"
Khởi động lại dịch vụ mạng:
[root@localhost network-scripts]# systemctl restart network
Tiếp theo, cấu hình các nút TiDB:
[root@localhost ~]# cd /etc/sysconfig/network-scripts
[root@localhost network-scripts]# cp ifcfg-lo ifcfg-lo:1
[root@localhost network-scripts]# vi ifcfg-lo:1
DEVICE=lo:1
IPADDR=10.3.65.201
NETMASK=255.255.255.255
ONBOOT=yes
NAME=loopback
Khởi động lại dịch vụ mạng và chỉnh sửa các tham số kernel:
[root@localhost network-scripts]# systemctl restart network
[root@localhost network-scripts]# vi /etc/sysctl.conf
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.default.arp_ignore = 1
net.ipv4.conf.lo.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2
net.ipv4.conf.default.arp_announce = 2
net.ipv4.conf.lo.arp_announce = 2
[root@localhost network-scripts]# sysctl -p
[root@localhost network-scripts]# route add -host 10.3.65.201 dev lo:1
Cài đặt và cấu hình ipvsadm:
[root@localhost ~]# yum install ipvsadm
[root@localhost ~]# ipvsadm -A -t 10.3.65.201:4000 -s wrr -p 5
[root@localhost ~]# ipvsadm -a -t 10.3.65.201:4000 -r 10.3.65.126:4000 -g
Lưu cấu hình và khởi động dịch vụ:
[root@localhost network-scripts]# ipvsadm --save > /etc/sysconfig/ipvsadm
[root@localhost network-scripts]# systemctl start ipvsadm
Weir
Weir là một dự án mở nguồn từ TiDB Incubator, hỗ trợ nhiều tính năng như kiểm tra SQL, giám sát, đa thuê bao, và tự điều chỉnh giới hạn luồng. Tuy nhiên, Weir không cung cấp hỗ trợ sẵn sàng cao. Để triển khai nhiều Weir, cần sử dụng các thành phần cân bằng tải như Nginx hoặc HAProxy ở trên.
Để cài đặt Weir, hãy thực hiện các bước sau:
[root@localhost ~]# git clone https://github.com/tidb-incubator/weir
[root@localhost ~]# cd weir
[root@localhost ~]# make weirproxy
Chỉnh sửa file cấu hình:
[root@localhost weir]# vi conf/namespace/test_namespace.yaml
version: "v1"
namespace: "test_namespace"
frontend:
allowed_dbs:
- "test"
slow_sql_time: 50
sql_blacklist:
denied_ips:
idle_timeout: 3600
users:
- username: "weir"
password: "111111"
backend:
instances:
- "10.3.65.126:4000"
username: "root"
password: ""
selector_type: "random"
pool_size: 10
idle_timeout: 60
Khởi động Weir:
[root@localhost weir]# ./bin/weirproxy &