Cấu hình bảng đích và Engine InputLog cho luồng dữ liệu
Bước đầu tiên là chuẩn bị bảng đích (Destination Table) nơi lưu trữ dữ liệu cuối cùng sau khi được xử lý. Bạn cần tạo bảng này với Engine lưu trữ phù hợp, ví dụ MergeTree, để đảm bảo hiệu năng truy vấn.
Tại sao: ClickHouse yêu cầu dữ liệu phải nằm trong bảng vật lý để có thể thực hiện truy vấn (Query). Engine InputLog chỉ dùng để nhận stream, không dùng để lưu trữ lâu dài.
Kết quả mong đợi: Bảng đích được tạo thành công và sẵn sàng nhận dữ liệu từ các nguồn khác.
Thực hiện lệnh sau trong ClickHouse Client để tạo bảng đích:
clickhouse-client --query "CREATE TABLE IF NOT EXISTS logs_realtime (timestamp DateTime, level String, service String, message String, host String) ENGINE = MergeTree() ORDER BY (timestamp, service);"
Kết quả: Không có lỗi (no error), bảng logs_realtime được tạo với 5 cột và sắp xếp theo timestamp và service.
Thiết lập bảng InputLog để nhận dữ liệu từ HTTP
Tiếp theo, tạo bảng trung gian sử dụng Engine InputLog. Engine này đóng vai trò như một bộ đệm (buffer) để nhận dữ liệu thô từ HTTP Interface và chuyển tiếp ngay lập tức sang bảng đích.
Tại sao: InputLog cho phép ClickHouse nhận dữ liệu qua HTTP (POST request) mà không cần định dạng phức tạp, sau đó tự động đẩy vào bảng đích qua một Materialized View hoặc INSERT trực tiếp.
Kết quả mong đợi: Bảng logs_input được tạo, sẵn sàng nhận JSON từ HTTP endpoint.
Thực hiện lệnh tạo bảng InputLog và Materialized View tự động chuyển dữ liệu:
clickhouse-client --query "CREATE TABLE IF NOT EXISTS logs_input (timestamp DateTime, level String, service String, message String, host String) ENGINE = InputLog('JSONEachRow'); CREATE MATERIALIZED VIEW IF NOT EXISTS mv_logs_input TO logs_realtime AS SELECT * FROM logs_input;"
Kết quả: Bảng logs_input và View mv_logs_input được tạo. Dữ liệu gửi vào logs_input sẽ tự động xuất hiện trong logs_realtime.
Cấu hình ClickHouse HTTP Interface để nhận JSON Payload
Để nhận dữ liệu từ nguồn bên ngoài (như ứng dụng, IoT device, hoặc API gateway), bạn cần cấu hình HTTP Interface của ClickHouse để lắng nghe trên một cổng cụ thể và cho phép phương thức POST.
Tại sao: Mặc định ClickHouse chỉ mở cổng 8123 cho HTTP, nhưng cần cấu hình rõ ràng để đảm bảo an ninh và định dạng dữ liệu JSON được chấp nhận.
Kết quả mong đợi: ClickHouse lắng nghe trên cổng 8123 (hoặc cổng tùy chọn) và chấp nhận POST request chứa JSON.
Chỉnh sửa file cấu hình chính của ClickHouse tại đường dẫn đầy đủ:
sudo nano /etc/clickhouse-server/config.d/http_interface.xml
Nội dung hoàn chỉnh của file cấu hình để mở cổng HTTP và cấu hình bảo mật cơ bản:
<http>
<http_port>8123</http_port>
<https_port>0</https_port>
<enable>1</enable>
<use_http_cache>0</use_http_cache>
<send_logs_level>trace</send_logs_level>
</http>
Lưu lại file (Ctrl+O, Enter) và thoát (Ctrl+X).
Kết quả: File cấu hình được cập nhật. Cần khởi động lại ClickHouse Server để áp dụng.
Khởi động lại dịch vụ ClickHouse Server:
sudo systemctl restart clickhouse-server
Kết quả: Dịch vụ restart thành công, trạng thái là active (running).
Verify kết quả HTTP Interface
Thử gửi một payload JSON đơn giản vào bảng logs_input qua HTTP để xác nhận luồng dữ liệu hoạt động.
curl -X POST "http://localhost:8123/?query=INSERT INTO logs_input FORMAT JSONEachRow" -d '{"timestamp":"2024-05-20 10:00:00","level":"INFO","service":"auth-service","message":"User login success","host":"web-01"}'
Kết quả mong đợi: Trả về chuỗi "Ok." và không có lỗi. Dữ liệu sẽ xuất hiện ngay trong bảng logs_realtime.
Kiểm tra dữ liệu trong bảng đích:
clickhouse-client --query "SELECT * FROM logs_realtime;"
Kết quả: Hiển thị dòng dữ liệu vừa gửi với đúng các giá trị timestamp, level, service, message, host.
Triển khai ClickHouse Kafka Consumer để đồng bộ dữ liệu
Khi dữ liệu đến từ Kafka thay vì HTTP, bạn cần sử dụng Engine Kafka để đọc stream và đẩy vào bảng đích. Đây là mô hình phổ biến cho hệ thống lớn.
Tại sao: Kafka đóng vai trò là message broker trung gian, giúp giải tải cho ClickHouse khi có lượng dữ liệu lớn và đảm bảo không mất dữ liệu nếu ClickHouse tạm thời offline.
Kết quả mong đợi: ClickHouse tự động đọc từ topic Kafka và lưu vào bảng đích.
Chẩn đoán và cấu hình bảng Kafka
Tạo bảng nguồn sử dụng Engine Kafka. Bảng này sẽ chỉ đọc dữ liệu từ Kafka, không lưu trữ vật lý.
Tại sao: ClickHouse cần biết địa chỉ Kafka broker, topic name, và định dạng dữ liệu (JSON, Avro, etc.) để phân tích cú pháp.
Kết quả mong đợi: Bảng kafka_logs được tạo, sẵn sàng kết nối với Kafka cluster.
Giả sử bạn đã có Kafka cluster chạy trên localhost:9092 và topic là "clickhouse-logs". Thực hiện lệnh tạo bảng:
clickhouse-client --query "CREATE TABLE IF NOT EXISTS kafka_logs (timestamp DateTime, level String, service String, message String, host String) ENGINE = Kafka() SETTINGS kafka_broker_list = 'localhost:9092', kafka_topic_list = 'clickhouse-logs', kafka_group_name = 'clickhouse-consumer', kafka_format = 'JSONEachRow';"
Kết quả: Bảng kafka_logs được tạo. ClickHouse bắt đầu kết nối đến Kafka broker và chờ dữ liệu.
Tự động đồng bộ dữ liệu từ Kafka vào bảng đích
Sử dụng Materialized View để tự động chuyển dữ liệu từ bảng Kafka (chỉ đọc) sang bảng MergeTree (lưu trữ).
Tại sao: Engine Kafka không hỗ trợ truy vấn trực tiếp cho dữ liệu lịch sử hiệu quả như MergeTree. Materialized View đảm bảo dữ liệu được "bơm" (pump) liên tục vào bảng đích ngay khi Kafka có message mới.
Kết quả mong đợi: Dữ liệu từ Kafka topic tự động xuất hiện trong bảng logs_realtime.
Tạo Materialized View để đồng bộ:
clickhouse-client --query "CREATE MATERIALIZED VIEW IF NOT EXISTS mv_kafka_logs TO logs_realtime AS SELECT * FROM kafka_logs;"
Kết quả: View được tạo. ClickHouse bắt đầu đọc dữ liệu từ kafka_logs và INSERT vào logs_realtime.
Verify kết quả Kafka Consumer
Gửi dữ liệu vào Kafka topic để kiểm tra luồng đồng bộ.
kafka-console-producer --bootstrap-server localhost:9092 --topic clickhouse-logs --producer-property parse.key=true --producer-property key.separator=:
Kết quả mong đợi: Dữ liệu được gửi vào Kafka. Sau vài giây, kiểm tra bảng đích.
Truy vấn bảng đích để xác nhận:
clickhouse-client --query "SELECT count() FROM logs_realtime WHERE service = 'payment-gateway';"
Kết quả: Trả về số lượng 1, chứng tỏ dữ liệu đã được Kafka Consumer đọc và đẩy vào bảng đích thành công.
Giám sát trạng thái Kafka Consumer
Kiểm tra xem ClickHouse có đang đọc đúng offset và không bị lỗi khi kết nối Kafka.
clickhouse-client --query "SELECT topic, group, current_offset, log_pos, fetch_pos, last_error FROM system.kafka_consumers WHERE topic = 'clickhouse-logs';"
Kết quả mong đợi: Hiển thị thông tin offset hiện tại, không có lỗi (last_error rỗng), và trạng thái đang hoạt động.
Điều hướng series:
Mục lục: Series: Triển khai Database Real-time với ClickHouse trên Ubuntu 24.04
« Phần 4: Thiết lập cấu trúc dữ liệu và Engine lưu trữ
Phần 6: Xử lý dữ liệu và tối ưu hóa truy vấn thực thi »