MySQL Sharding ở quy mô lớn: Hướng dẫn thực tế về Vitess trên Kubernetes

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

Bức tường ngăn cách chúng ta với Single-Instance MySQL

Tôi nhớ đêm mà cơ sở dữ liệu chính của chúng tôi đạt 95% mức sử dụng CPU trong một đợt flash sale. Chúng tôi đang xử lý 3.000 truy vấn mỗi giây và thời gian phản hồi vốn chỉ 20ms đã vọt lên gần 4 giây. Chúng tôi đã làm theo các quy trình chuẩn: nâng cấp cấu hình instance, tinh chỉnh buffer pool và thêm các bản sao read replica. Nhưng mở rộng theo chiều dọc (vertical scaling) là một ngõ cụt. Cuối cùng, bạn sẽ chạm tới trần phần cứng mà không có số tiền nào có thể giải quyết được.

Sharding—quá trình chia nhỏ một tập dữ liệu khổng lồ thành các phần nhỏ hơn, dễ quản lý hơn—thường là “trùm cuối” trong kỹ thuật cơ sở dữ liệu. Sau khi từng vật lộn với việc sharding thủ công trong MySQL và PostgreSQL, tôi thấy nó thường là một mớ hỗn độn mong manh của các logic ở tầng ứng dụng. Vitess thay đổi điều đó. Nó hoạt động như một lớp cụm (clustering layer) nằm trên MySQL, hấp thụ sự phức tạp của việc sharding để ứng dụng của bạn có thể đối xử với hàng trăm node như một cơ sở dữ liệu duy nhất.

Tại sao nên chọn Vitess?

YouTube đã thiết kế Vitess để xử lý sự tăng trưởng thần tốc của họ, và hiện nó đang quản lý các cơ sở dữ liệu chứa hàng tỷ dòng. Nó cung cấp một lớp proxy có thể giao tiếp thành thạo giao thức MySQL. Mã nguồn của bạn không cần biết shard nào đang chứa một bản ghi cụ thể. Vitess xử lý connection pooling, định tuyến truy vấn và “resharding”—quá trình di chuyển dữ liệu giữa các shard—mà không làm ứng dụng của bạn ngừng hoạt động. Đó là sự khác biệt giữa lao động thủ công và một dây chuyền lắp ráp tự động.

Thiết lập môi trường

Tiêu chuẩn để triển khai Vitess hiện nay là Vitess Operator cho Kubernetes. Đối với hướng dẫn này, bạn sẽ cần một cụm K8s (Minikube là đủ cho việc thử nghiệm cục bộ) và helm. Trước khi bắt đầu, hãy đảm bảo môi trường của bạn có ít nhất 4 vCPU và 8GB RAM. Vitess hoạt động hiệu quả, nhưng quá trình điều phối (orchestration) ban đầu đòi hỏi một số tài nguyên hệ thống.

Đầu tiên, hãy thêm kho lưu trữ và triển khai operator:

# Thêm Vitess Helm repo
helm repo add vitess https://vitess.io/helm
helm repo update

# Cài đặt Vitess Operator
helm install vitess-operator vitess/vitess-operator

Operator đóng vai trò là bộ não cho cụm của bạn. Nó theo dõi các Custom Resource Definitions (CRDs) và đảm bảo các MySQL instance cũng như các thành phần Vitess luôn ở trạng thái khỏe mạnh và đồng bộ.

Cấu hình Keyspace đầu tiên

Trong thế giới Vitess, chúng ta vượt ra khỏi khái niệm về một “database” độc lập và nói về Keyspaces. Một keyspace là một nhóm logic có thể được chia thành nhiều shard. Nếu bạn chưa thực hiện sharding, một keyspace sẽ hoạt động chính xác như một schema MySQL tiêu chuẩn.

Hãy định nghĩa một cụm với một keyspace tên là commerce. Chúng ta sẽ bắt đầu với hai shard để trình diễn việc phân tách theo chiều ngang. Lưu cấu hình này thành vttest.yaml:

apiVersion: vitess.io/v2
kind: VitessCluster
metadata:
  name: production-cluster
spec:
  cells:
    - name: zone1
      gateway:
        replicas: 1
  keyspaces:
    - name: commerce
      turndownPolicy: Immediate
      partitionings:
        - equal:
            parts: 2
            shardTemplate:
              tabletPools:
                - cell: zone1
                  type: replica
                  replicas: 2

Triển khai cấu hình vào cụm của bạn:

kubectl apply -f vttest.yaml

Lệnh này sẽ kích hoạt operator để khởi tạo hai shard riêng biệt. Mỗi shard bao gồm một MySQL instance và một sidecar VTTablet quản lý tiến trình cơ sở dữ liệu bên dưới.

Phân tích kiến trúc

Trong khi các pod đang khởi tạo, hãy xem xét các thành phần đang hoạt động. Bạn sẽ thấy ba thành phần chính:

  • VTGate: Bộ điều khiển lưu lượng. Ứng dụng của bạn kết nối tại đây. Nó phân tích cú pháp SQL của bạn và định tuyến nó đến đúng shard.
  • VTTablet: Người bảo vệ. Một VTTablet nằm cạnh mọi MySQL instance, quản lý các pool kết nối và bảo vệ DB khỏi các “truy vấn tử thần” (queries of death).
  • Topology Service: Thường được hỗ trợ bởi etcd, đây là nguồn sự thật duy nhất về vị trí của mọi shard và tablet.

Sức mạnh của VSchema

Làm thế nào Vitess quyết định người dùng nào sẽ vào shard nào? Logic này nằm trong VSchema. Không có nó, Vitess chỉ là một proxy; có nó, nó là một cỗ máy sharding.

Nếu chúng ta có bảng users, chúng ta sử dụng một ‘Vindex’ (Vitess Index) để ánh xạ các dòng vào các shard. Dưới đây là một đoạn mã VSchema thực tế sử dụng phân phối dựa trên hash:

{
  "sharded": true,
  "vindexes": {
    "hash_vindex": {
      "type": "hash"
    }
  },
  "tables": {
    "users": {
      "column_vindexes": [
        {
          "column": "user_id",
          "name": "hash_vindex"
        }
      ]
    }
  }
}

Tôi khuyên dùng vindex loại hash cho hầu hết các khối lượng công việc đa khách thuê (multi-tenant). Nó phân phối dữ liệu đồng đều, ngăn chặn các “điểm nóng” (hot spots) nơi một máy chủ phải xử lý 90% lưu lượng trong khi những máy chủ khác vẫn rảnh rỗi.

Xác minh và Tích hợp ứng dụng

Khi các pod hiển thị trạng thái Running, bạn đã sẵn sàng để kết nối. VTGate mở ra một cổng trông giống hệt như một máy chủ MySQL tiêu chuẩn. Các ORM và database client hiện tại của bạn sẽ không nhận thấy sự khác biệt.

Chuyển tiếp cổng (port-forward) gateway tới môi trường cục bộ của bạn:

kubectl port-forward svc/production-cluster-zone1-vtgate 3306:3306

Bây giờ, hãy kết nối bằng một client tiêu chuẩn:

mysql -h 127.0.0.1 -P 3306 -u user commerce

Chiến thắng về mặt kỹ thuật ở đây là tính minh bạch. Bạn có thể chạy SELECT * FROM users, và Vitess sẽ truy vấn cả hai shard, hợp nhất kết quả và trả về chúng như một tập dữ liệu duy nhất. Các nhà phát triển của bạn có thể tập trung vào tính năng thay vì phải viết logic định tuyến dữ liệu phức tạp.

Giám sát và Khả năng sẵn sàng cao

Vận hành trên môi trường production mà không có sự giám sát là một thảm họa. Vitess bao gồm một bảng điều khiển web có tên là vtctld để trực quan hóa sức khỏe cụm của bạn.

# Truy cập bảng điều khiển vtctld
kubectl port-forward svc/production-cluster-zone1-vtctld 15000:15000

Truy cập vào http://localhost:15000 để giám sát các bản sao của bạn. Nếu một node chính (primary) bị lỗi, Vitess operator sẽ tự động thúc đẩy một replica lên làm primary. Tôi đã chứng kiến điều này xảy ra trong một sự cố lỗi node, nơi ứng dụng chỉ gặp chưa đầy 10 giây gián đoạn việc ghi và hoàn toàn không bị gián đoạn việc đọc.

Để có khả năng quan sát sâu hơn, tôi luôn thu thập dữ liệu từ endpoint /metrics vào Prometheus. Theo dõi các chỉ số như vttablet_query_countvttablet_query_error_count cho phép bạn phát hiện các hiện tượng suy giảm hiệu suất trước khi chúng ảnh hưởng đến người dùng.

Lời kết

Áp dụng Vitess là một sự chuyển đổi mang tính chiến lược. Mặc dù nó giới thiệu các thành phần kiến trúc mới, nhưng nó xóa bỏ giới hạn cứng đối với sự tăng trưởng dữ liệu của bạn. Khi bạn không còn lo sợ việc chạm ngưỡng lưu trữ 2TB hay nút thắt cổ chai 5.000 QPS, bạn có thể tự tin xây dựng hệ thống. Mở rộng theo chiều ngang trở nên đơn giản như việc cập nhật một tệp YAML và để operator xử lý những công việc nặng nhọc còn lại.

Share: