Triển khai TiDB trên Docker: Mở rộng HTAP với Cơ sở dữ liệu NewSQL phân tán

Database tutorial - IT technology blog
Database tutorial - IT technology blog

Rào cản mở rộng và cái giá của ETL

Hầu hết chúng ta đều bắt đầu hành trình với một cơ sở dữ liệu quan hệ truyền thống. Sau khi làm việc với MySQL, PostgreSQL và MongoDB qua nhiều dự án khác nhau, tôi nhận thấy mỗi loại đều có thế mạnh riêng. MySQL thường là lựa chọn ưu tiên của tôi nhờ sự tin cậy và dễ sử dụng.

Tuy nhiên, tôi thường xuyên vấp phải rào cản khi dự án phát triển đến mức một instance MySQL duy nhất không thể gánh nổi tải ghi (write load). Theo cách truyền thống, giải pháp thường là sharding—một quy trình phức tạp bao gồm việc chia nhỏ dữ liệu trên nhiều máy chủ. Đây là một cơn ác mộng về bảo trì, làm phá vỡ các giao dịch xuyên shard (cross-shard transactions) và khiến việc truy vấn trở nên cực kỳ đau đầu.

Tiếp theo là khía cạnh phân tích. Khi bộ phận kinh doanh muốn các báo cáo thời gian thực, việc chạy các truy vấn tổng hợp nặng nề trên instance MySQL đang vận hành là công thức dẫn đến thảm họa hiệu năng. Để giải quyết vấn đề này, chúng ta thường xây dựng các đường ống ETL (Extract, Transform, Load) để chuyển dữ liệu sang một kho dữ liệu (data warehouse) riêng biệt như ClickHouse hoặc Snowflake. Việc này gây ra độ trễ dữ liệu và thêm nhiều thành phần hệ thống có nguy cơ bị lỗi.

TiDB thay đổi cục diện này. Đây là một cơ sở dữ liệu NewSQL có khả năng mở rộng ngang, hỗ trợ giao dịch ACID và sử dụng giao thức MySQL. Nhưng phép màu thực sự nằm ở HTAP (Hybrid Transactional/Analytical Processing). Nó cho phép bạn chạy cả khối lượng công việc giao dịch (OLTP) và phân tích (OLAP) trên cùng một cluster mà không làm ảnh hưởng lẫn nhau. Tôi nhận thấy đây là một bước ngoặt cho các đội ngũ cần thông tin phân tích thời gian thực mà không muốn gánh nặng từ các đường ống ETL phức tạp.

Các khái niệm cốt lõi: Cách TiDB đạt được điều không tưởng

Trước khi bắt tay vào thiết lập Docker, việc hiểu rõ kiến trúc là rất quan trọng. TiDB không phải là một file thực thi duy nhất; nó là một cụm gồm các thành phần chuyên biệt phối hợp với nhau:

  • TiDB Server: Lớp SQL không trạng thái (stateless). Nó xử lý các kết nối máy khách, phân tích cú pháp SQL và tối ưu hóa thực thi truy vấn. Bạn có thể mở rộng lớp này để xử lý nhiều kết nối đồng thời hơn.
  • PD (Placement Driver): Bộ não của cluster. Nó lưu trữ metadata, quản lý phân phối dữ liệu và xử lý cấp phát timestamp cho các giao dịch.
  • TiKV: Công cụ lưu trữ dạng dòng (row-based). Đây là nơi lưu trữ dữ liệu giao dịch của bạn. Nó sử dụng thuật toán đồng thuận Raft để đảm bảo tính sẵn sàng cao và tính nhất quán của dữ liệu.
  • TiFlash: Công cụ lưu trữ dạng cột (columnar). Đây là thứ biến TiDB thành một cơ sở dữ liệu HTAP. Nó cung cấp khả năng phân tích gần như thời gian thực bằng cách sao chép dữ liệu từ TiKV sang định dạng cột được tối ưu hóa cho việc quét và tổng hợp dữ liệu.

Vì TiDB tương thích với giao thức MySQL 5.7, các ứng dụng hiện tại của bạn thường có thể chuyển sang TiDB chỉ bằng cách thay đổi chuỗi kết nối. Không cần phải viết lại logic ORM hay các truy vấn phức tạp.

Thiết lập TiDB trên Docker

Để phát triển và thử nghiệm, Docker Compose là cách hiệu quả nhất để khởi chạy một cluster TiDB. Mặc dù TiDB cung cấp công cụ gọi là tiup cho việc triển khai thực tế (production), Docker mang lại cho chúng ta một môi trường sạch sẽ, cô lập để khám phá các tính năng HTAP.

1. Cấu hình Docker Compose

Tạo một thư mục cho dự án của bạn và lưu nội dung sau thành file docker-compose.yml. Thiết lập này bao gồm các thành phần cốt lõi: PD, TiKV, TiDB và TiFlash.

version: '3.8'

services:
  pd:
    image: pingcap/pd:latest
    ports:
      - "2379:2379"
    command:
      - --name=pd
      - --data-dir=/data/pd
      - --client-urls=http://0.0.0.0:2379
      - --advertise-client-urls=http://pd:2379
      - --peer-urls=http://0.0.0.0:2380
      - --advertise-peer-urls=http://pd:2380
      - --initial-cluster=pd=http://pd:2380
      - --log-file=/logs/pd.log

  tikv:
    image: pingcap/tikv:latest
    depends_on:
      - pd
    command:
      - --addr=0.0.0.0:20160
      - --advertise-addr=tikv:20160
      - --data-dir=/data/tikv
      - --pd-endpoints=http://pd:2379
      - --log-file=/logs/tikv.log

  tidb:
    image: pingcap/tidb:latest
    ports:
      - "4000:4000"
      - "10080:10080"
    depends_on:
      - pd
      - tikv
    command:
      - --store=tikv
      - --path=pd:2379
      - --log-file=/logs/tidb.log

  tiflash:
    image: pingcap/tiflash:latest
    depends_on:
      - pd
      - tikv
    command:
      - server
      - --config-file=/etc/tiflash/tiflash-learner.toml
    # Lưu ý: TiFlash yêu cầu các cấu hình cụ thể để chạy ổn định.
    # Đối với bản demo này, các thiết lập mặc định của image là đủ.

2. Khởi chạy Cluster

Chạy lệnh sau để khởi động các dịch vụ ở chế độ nền:

docker-compose up -d

Sẽ mất một hoặc hai phút để tất cả các thành phần khởi tạo và đăng ký với Placement Driver (PD). Bạn có thể kiểm tra trạng thái của các container bằng lệnh docker-compose ps.

Thử nghiệm khả năng HTAP

Sau khi cluster đã hoạt động, bạn có thể kết nối bằng bất kỳ MySQL client nào. Tôi sẽ sử dụng command-line client tiêu chuẩn ở đây. Cổng mặc định của TiDB là 4000, và người dùng mặc định là root không có mật khẩu.

mysql -h 127.0.0.1 -P 4000 -u root

Tạo bảng với TiFlash Replica

Để tận dụng các tính năng HTAP, bạn cần chỉ định cho TiDB biết bảng nào nên được sao chép sang bộ lưu trữ dạng cột (TiFlash). Hãy tạo một bảng mẫu và kích hoạt sao chép TiFlash.

CREATE DATABASE analytics_demo;
USE analytics_demo;

CREATE TABLE orders (
    id BIGINT PRIMARY KEY,
    customer_id INT,
    amount DECIMAL(10, 2),
    order_date DATETIME
);

-- Thêm một bản sao TiFlash cho bảng này
ALTER TABLE orders SET TIFLASH REPLICA 1;

Bạn có thể kiểm tra trạng thái sao chép bằng truy vấn này. Cột AVAILABLE sẽ chuyển thành 1 sau khi dữ liệu được đồng bộ hóa.

SELECT * FROM information_schema.tiflash_replica WHERE table_name = 'orders';

Truy vấn với đúng Engine

Bộ tối ưu hóa của TiDB đủ thông minh để quyết định nên sử dụng TiKV (dạng dòng) hay TiFlash (dạng cột) tùy thuộc vào truy vấn của bạn. Các truy vấn điểm (point select) và giao dịch nhỏ sẽ chuyển đến TiKV. Các truy vấn tổng hợp lớn sẽ chuyển đến TiFlash.

Bạn có thể ép buộc một truy vấn sử dụng TiFlash để thấy sự khác biệt về hiệu năng trên các tập dữ liệu lớn:

-- Ép buộc sử dụng TiFlash cho session này
SET @@session.tidb_isolation_read_engines = "tiflash";

SELECT SUM(amount), DATE(order_date) 
FROM orders 
GROUP BY DATE(order_date);

Kinh nghiệm thực tế

Sau khi thử nghiệm TiDB trong nhiều môi trường khác nhau, tôi đã đúc kết được một vài mẹo giúp bạn tiết kiệm thời gian khi triển khai và mở rộng.

Phân bổ tài nguyên

TiDB khá tiêu tốn tài nguyên. Trong môi trường thực tế, nếu có thể, đừng cố gắng đặt TiKV và TiFlash trên cùng một ổ đĩa vật lý. TiKV cần IO độ trễ thấp cho các giao dịch, trong khi TiFlash cần băng thông cao cho việc quét dữ liệu. Trên Docker, hãy đảm bảo bạn cấp đủ bộ nhớ (ít nhất 4GB cho bản demo, và nhiều hơn thế cho thực tế) nếu không các container có thể bị dừng đột ngột.

Giám sát không phải là tùy chọn

Một điều tôi thích ở hệ sinh thái TiDB là khả năng tích hợp sẵn với Prometheus và Grafana. Nếu bạn sử dụng phương thức triển khai tiup chính thức sau này, nó sẽ tự động thiết lập các công cụ này. Với Docker, tôi khuyên bạn nên thêm một container Grafana vào file compose để trực quan hóa thời gian chờ PD TSO (Timestamp Oracle) và các chỉ số của storage engine TiKV. Đó là cách duy nhất để thực sự hiểu điểm nghẽn của bạn nằm ở đâu.

Lưu ý về phiên bản

Hệ sinh thái TiDB phát triển rất nhanh. Luôn đảm bảo rằng các phiên bản TiDB, TiKV và PD của bạn khớp nhau hoàn toàn. Chạy một server TiDB v6.5 với một node TiKV v7.1 có thể dẫn đến những lỗi khó phát hiện trong lớp đồng thuận Raft và cực kỳ khó debug.

Lời kết

Chuyển từ thiết lập MySQL đơn lẻ sang một cơ sở dữ liệu NewSQL phân tán như TiDB cảm giác như một bước tiến khổng lồ, nhưng cách tiếp cận dựa trên Docker giúp lộ trình học tập trở nên dễ dàng hơn nhiều. Nó giải quyết hai vấn đề đau đầu nhất trong kỹ thuật dữ liệu hiện đại: mở rộng ngang và sự chia tách giữa OLTP/OLAP.

Bằng cách sử dụng TiFlash, bạn có được lợi ích của một kho dữ liệu với sự đơn giản của một kết nối cơ sở dữ liệu duy nhất. Nếu ứng dụng của bạn đang vượt quá khả năng của cơ sở dữ liệu quan hệ hiện tại, việc dùng thử TiDB trên Docker là một cách tuyệt vời để đánh giá xem nó có phù hợp cho giai đoạn tăng trưởng tiếp theo của bạn hay không.

Share: