Cấu hình tham số Memory Limit cho Session YSQL và YCQL
Để ngăn chặn các truy vấn phân tích (OLAP) tiêu thụ hết RAM và làm sập các giao dịch (OLTP), ta cần đặt giới hạn bộ nhớ riêng cho từng loại session trong YugabyteDB.
Tham số memory_limit trong YSQL (Postgres-based) và memory_limit trong YCQL (Cassandra-based) giúp kiểm soát lượng RAM mà một query hoặc một task có thể sử dụng. Nếu vượt quá, hệ thống sẽ tự động hủy query đó để bảo vệ cluster.
Thực hiện lệnh sau để đặt giới hạn bộ nhớ toàn cục cho các session YSQL mới, giới hạn ở mức 2GB cho mỗi query để ưu tiên cho các workload HTAP:
ydb-config --set memory_limit=2GB --apply
Kết quả mong đợi: Hệ thống trả về thông báo "Configuration updated successfully" và các session mới sẽ tuân thủ giới hạn 2GB.
Đối với YCQL, ta cần tinh chỉnh thông qua ycqlsh để đặt giới hạn bộ nhớ cho các task phân tích phức tạp, ngăn chặn OutOfMemoryError:
ycqlsh -u cassuser -p casspass -e "ALTER SYSTEM SET max_memory_per_task = '1073741824';"
Kết quả mong đợi: Lệnh thực thi thành công, không có lỗi cú pháp, và giá trị mới được áp dụng cho các session YCQL sau đó.
Để verify, truy cập vào ysql và kiểm tra giá trị hiện hành:
psql -U yugabyte -h 127.0.0.1 -d yugabyte -c "SHOW memory_limit;"
Kết quả mong đợi: Đầu ra hiển thị 2GB.
Tinh chỉnh Max Connections và Transaction Isolation Level
Trong môi trường HTAP, số lượng kết nối từ ứng dụng OLTP thường rất lớn, trong khi các job OLAP cần ít kết nối hơn nhưng chiếm nhiều tài nguyên. Cần tách biệt giới hạn kết nối và đặt mức độ cách ly giao dịch phù hợp.
Tham số max_connections trong YSQL cần được tăng lên để xử lý hàng nghìn kết nối từ ứng dụng, nhưng phải cân bằng với shared_buffers đã cấu hình ở phần trước.
Cập nhật file cấu hình postgresql.conf của YSQL (thường nằm trong thư mục data của yb-tserver) để tăng giới hạn kết nối:
sed -i 's/#max_connections = 100/max_connections = 500/' /var/lib/ycdb/data/0/node/postgres.conf
Kết quả mong đợi: File cấu hình được ghi lại, dòng max_connections thay đổi thành 500.
Để áp dụng thay đổi này mà không cần restart toàn bộ cluster, ta sử dụng lệnh reload config trên master node:
yb-masterctl --master_addresses=127.0.0.1:7100 --command=reload_config
Kết quả mong đợi: Console hiển thị thông báo "Config reloaded successfully" và các node tserver nhận diện cấu hình mới.
Đối với Transaction Isolation Level, trong môi trường HTAP, OLTP cần REPEATABLE_READ để đảm bảo tính nhất quán, còn OLAP có thể dùng SNAPSHOT_READ (đặc thù của YugabyteDB) để đọc dữ liệu nhất quán tại một thời điểm mà không lock bảng.
Thiết lập mức mặc định cho session YSQL trong ứng dụng hoặc trực tiếp qua psql:
psql -U yugabyte -h 127.0.0.1 -d yugabyte -c "SET transaction_isolation = 'REPEATABLE READ';"
Kết quả mong đợi: Lệnh trả về SET và các transaction tiếp theo trong session này sẽ chạy ở chế độ Repeatable Read.
Đối với YCQL, YugabyteDB mặc định sử dụng consistency level LOCAL_QUORUM. Để tối ưu cho OLAP (đọc nhiều, chấp nhận delay nhỏ), ta có thể chuyển sang ONE hoặc LOCAL_ONE trong code ứng dụng, nhưng để test ngay trên server, ta cấu hình mặc định cho keyspace:
ycqlsh -u cassuser -p casspass -e "ALTER KEYSPACE analytics_keyspace WITH DURABLE_WRITES = false AND replication = { 'class': 'NetworkTopologyStrategy', 'dc1': 1 };"
Kết quả mong đợi: Keyspace analytics_keyspace được cập nhật, giảm độ trễ ghi cho workload phân tích.
Verify kết quả bằng cách kiểm tra số lượng kết nối hiện tại và mức độ cách ly:
psql -U yugabyte -h 127.0.0.1 -d yugabyte -c "SELECT count(*) FROM pg_stat_activity; SELECT current_setting('transaction_isolation');"
Kết quả mong đợi: Đếm số session đang hoạt động và trả về giá trị repeatable read.
Sử dụng Explain để phân tích kế hoạch thực thi của truy vấn phức tạp
Trong HTAP, các truy vấn JOIN nhiều bảng hoặc Aggregation nặng có thể gây nghẽn cổ chai nếu không có index phù hợp hoặc nếu planner chọn sai thuật toán join. Ta dùng EXPLAIN (ANALYZE, BUFFERS) để xem chi tiết.
Tạo một bảng mẫu có dữ liệu lớn để mô phỏng workload thực tế (nếu chưa có):
psql -U yugabyte -h 127.0.0.1 -d yugabyte -c "CREATE TABLE orders (order_id BIGSERIAL, customer_id BIGINT, amount DECIMAL, created_at TIMESTAMPTZ, PRIMARY KEY (order_id)); INSERT INTO orders (customer_id, amount, created_at) SELECT generate_series(1, 1000000), random()*10000, now() - interval '1 year' * random();"
Kết quả mong đợi: Bảng orders được tạo và chèn 1 triệu dòng dữ liệu giả lập.
Thực hiện lệnh Explain trên một truy vấn phức tạp (JOIN + Aggregation) để phân tích kế hoạch:
psql -U yugabyte -h 127.0.0.1 -d yugabyte -c "EXPLAIN (ANALYZE, BUFFERS, FORMAT TEXT) SELECT c.name, SUM(o.amount) FROM customers c JOIN orders o ON c.customer_id = o.customer_id WHERE o.created_at > now() - interval '30 days' GROUP BY c.name;"
Kết quả mong đợi: Đầu ra hiển thị cây thực thi (Query Plan) với chi tiết Actual Time, Rows, Buffers. Chú ý các dòng có Actual Time cao bất thường hoặc Buffers Hit thấp (cho thấy I/O disk).
Nếu phát hiện truy vấn dùng Seq Scan (Quét toàn bộ bảng) thay vì Index Scan, ta cần tạo index phù hợp. Trong YugabyteDB, index được tạo bằng cú pháp Postgres nhưng lưu trữ phân tán:
psql -U yugabyte -h 127.0.0.1 -d yugabyte -c "CREATE INDEX CONCURRENTLY idx_orders_created ON orders (created_at);"
Kết quả mong đợi: Index được tạo thành công. Lệnh CONCURRENTLY đảm bảo không lock bảng trong quá trình tạo.
Chạy lại EXPLAIN để verify sự thay đổi trong kế hoạch thực thi:
psql -U yugabyte -h 127.0.0.1 -d yugabyte -c "EXPLAIN (ANALYZE, BUFFERS) SELECT * FROM orders WHERE created_at > now() - interval '30 days';"
Kết quả mong đợi: Trong output, dòng Index Scan hoặc Bitmap Index Scan xuất hiện thay thế cho Seq Scan, và Actual Time giảm đáng kể.
Đối với YCQL, việc phân tích thực thi phức tạp hơn vì không có EXPLAIN trực tiếp như Postgres. Ta dùng DESCRIBE để xem cấu trúc và kiểm tra trace nếu cần debug:
ycqlsh -u cassuser -p casspass -e "DESCRIBE TABLE orders;"
Kết quả mong đợi: Hiển thị cấu trúc bảng, phân vùng key (Partition Key) và Clustering Key. Nếu truy vấn chậm, kiểm tra xem Partition Key có được sử dụng trong điều kiện WHERE không.
Cấu hình các tham số Buffer Pool cho các loại Workload khác nhau
YugabyteDB sử dụng RocksDB (cho YCQL) và PostgreSQL (cho YSQL) với cơ chế caching khác nhau. Để tối ưu HTAP, ta cần cân bằng giữa bộ nhớ dành cho cache dữ liệu nóng (hot data) và buffer pool.
Đối với YSQL, tham số shared_buffers là nơi lưu trữ cache page. Trong môi trường HTAP, ta nên tăng giá trị này lên 25-30% tổng RAM của node để tăng tốc độ đọc OLTP.
Cập nhật file postgresql.conf (đường dẫn đầy đủ):
sed -i 's/#shared_buffers = 128MB/shared_buffers = 4GB/' /var/lib/ycdb/data/0/node/postgres.conf
Kết quả mong đợi: File cấu hình được ghi lại với giá trị 4GB (giả sử server có 16GB RAM).
Đối với YCQL (RocksDB), tham số quan trọng là block_cache_size và memtable_size. Ta cấu hình qua file yb_conf hoặc command line khi khởi động yb-tserver. Giả sử ta dùng file cấu hình /etc/yugabyte/config/yb.conf:
echo "tserver_flags: --rocksdb_block_cache_size=4GB --rocksdb_memtable_size=1GB" >> /etc/yugabyte/config/yb.conf
Kết quả mong đợi: Các tham số được thêm vào file cấu hình. Lưu ý: Cần restart yb-tserver để áp dụng.
Để áp dụng cấu hình mới cho toàn bộ cluster, ta cần restart dịch vụ yb-tserver trên các node:
systemctl restart yb-tserver
Kết quả mong đợi: Dịch vụ khởi động lại, và trong log /var/log/yugabyte/yb-tserver.log sẽ thấy các dòng Setting block_cache_size to 4GB.
Verify hiệu quả của buffer pool bằng cách kiểm tra cache hit ratio trong YSQL:
psql -U yugabyte -h 127.0.0.1 -d yugabyte -c "SELECT name, num_hits, num_misses FROM pg_stat_user_tables ORDER BY num_hits DESC LIMIT 5;"
Kết quả mong đợi: Các bảng có tần suất truy vấn cao (OLTP) sẽ có num_hits lớn hơn nhiều so với num_misses, chứng tỏ buffer pool đang hoạt động tốt.
Đối với YCQL, kiểm tra thống kê RocksDB qua ycqlsh hoặc yb-admin:
yb-admin --master_addresses=127.0.0.1:7100 --command=stats --tablet_id= --key=rocksdb_block_cache_hit_rate
Kết quả mong đợi: Trả về một giá trị thập phân (ví dụ: 0.95), nghĩa là 95% các lần đọc được phục vụ từ cache RAM.
Đánh giá hiệu năng với các công cụ Benchmark (ycsb, tpcc) trên HTAP
Để xác nhận các tinh chỉnh trên mang lại hiệu quả, ta cần chạy benchmark chuẩn. YCSB dùng cho YCQL (NoSQL) và TPCC dùng cho YSQL (Relational). Trong môi trường HTAP, ta chạy song song để xem hệ thống chịu tải như thế nào.
Cài đặt YCSB client và cấu hình cho YugabyteDB YCQL:
git clone https://github.com/brianfrankcooper/YCSB.git && cd YCSB && ./build.sh && cd ycsb-core && mvn package -DskipTests
Kết quả mong đợi: Build thành công, tạo ra file ycsb.jar.
Chạy YCSB với workload A (50% Read/50% Write) để test khả năng chịu tải OLTP của YCQL:
java -jar dist/ycsb.jar cassandre -p cass_host_list=127.0.0.1 -p cass_port=9042 -p cass_keyspace=ycsb -p workload=A -p record_count=100000 -p operation_count=100000 -p threads=16
Kết quả mong đợi: In ra bảng thống kê với Throughput (ops/sec) và Latency (ms). Giá trị Throughput cao và Latency thấp (dưới 10ms) là mục tiêu.
Đối với YSQL, sử dụng TPCC (TPC-C) là chuẩn ngành cho OLTP. YugabyteDB cung cấp script tpcc trong thư mục contrib. Ta cần chuẩn bị schema và chạy benchmark:
cd /var/lib/ycdb/bin && ./tpcc --warehouse=100 --terminals=100 --duration=300 --host=127.0.0.1 --port=5433 --user=yugabyte --db=yugabyte
Kết quả mong đợi: Script chạy trong 300 giây và in ra báo cáo cuối cùng với số tpmC (transactions per minute). So sánh con số này với baseline (trước khi tối ưu).
Để test khả năng HTAP (đọc phân tích song song với giao dịch), ta chạy YCSB (OLTP) trên YSQL và một truy vấn SELECT nặng (OLAP) song song trên terminal khác:
psql -U yugabyte -h 127.0.0.1 -d yugabyte -c "SELECT COUNT(*) FROM orders;" & java -jar dist/ycsb.jar postgres -p postgres_host=127.0.0.1 -p postgres_port=5433 -p postgres_db=yugabyte -p workload=A -p record_count=10000 -p operation_count=10000 -p threads=8
Kết quả mong đợi: Cả hai tiến trình chạy song song. Quan sát xem Latency của YCSB có tăng đột biến không khi chạy query COUNT(*). Nếu các tối ưu buffer và memory limit đã hiệu quả, latency sẽ chỉ tăng nhẹ hoặc không đổi.
Verify kết quả tổng hợp bằng cách so sánh các chỉ số trước và sau khi tối ưu:
echo "YCSB Throughput: $(grep 'Throughput' ycsb_output.txt | head -n1); TPCC tpmC: $(grep 'tpmC' tpcc_output.txt | head -n1)"
Kết quả mong đợi: Hiển thị các con số throughput và tpmC cuối cùng, chứng minh hiệu năng đã được cải thiện sau khi cấu hình memory limit, connection, buffer pool và index.
Điều hướng series:
Mục lục: Series: Triển khai Database HTAP với YugabyteDB và Linux Kernel Tuning trên Ubuntu 24.04
« Phần 5: Cấu hình kiến trúc HTAP: Phân tách giao dịch và truy vấn phân tích
Phần 7: Xử lý sự cố, giám sát và các mẹo nâng cao cho cụm HTAP »