Access Hub Collector
Đồng bộ từ mã nguồn lúc 10:57, 03/10/2026
Skip to content

Mô hình dữ liệu ​

11 phút đọcCập nhật 02/10/2026access-hub-collector, docs/04-data-model.md

1. Redis (hoặc Valkey) ​

Tiền tố ah:. Mọi khóa có TTL trừ khi ghi khác. Redis là trạng thái nóng, mất Redis không được làm mất dữ liệu số liệu, chỉ làm suy giảm tạm thời (xem 08-scaling-ha).

KhóaKiểuNội dungTTL
ah:reg:tok:{sha256(token)}hashagent_id, company_id, server_id, state, rate_class (registry)1 giờ, làm mới khi dùng
ah:reg:neg:{sha256(token)}stringCache âm token không tồn tại60 giây
ah:reg:agent:{agent_id}hashĐảo ngược: token_hashes (hiện tại và cũ), server_id, company_id1 giờ
ah:seenzsetmember agent_id, score last_seen_mskhông, dọn theo agent thu hồi
ah:agent:{agent_id}:sthashstate (up/down), since_ms, version, protokhông
ah:rl:{agent_id}:{class}stringBộ đếm token bucket10 phút
ah:series:{agent_id}hyperloglogƯớc lượng số series hoạt động để áp max_series1 giờ
ah:rules:{collector_id}:rulesstring (JSON)Snapshot bộ luật thô đang chạy và con trỏ since (COL-8). Nạp lại khi khởi động để chạy được lúc Access Hub sậpkhông
ah:rules:{collector_id}:statestring (JSON)Snapshot trạng thái đánh giá (pha, mốc for, đỉnh, seq) của mọi cặp luật-máy-series, ghi mỗi 30 giây và khi tắt êm (COL-8)không
ah:rules:{collector_id}:silencesstring (JSON)Snapshot bộ silence thô và con trỏ since (COL-9)không
ah:rules:{collector_id}:groupsstring (JSON)Snapshot các nhóm group_down đang mở (COL-9)không
ah:silences:reloadstring (số)Bộ đếm tín hiệu nạp lại silence, cùng cơ chế ah:rules:reload (COL-9)không
ah:rules:reloadstring (số)Bộ đếm tín hiệu nạp lại luật: admin tách tiến trình tăng, worker thăm dò mỗi 2 giâykhông
ah:collector:{id}hashHeartbeat của node collector, dùng để chia shard30 giây
ob:q, ob:e, ob:deadzset, hash, hashOutbox sự kiện gửi tới Access Hub dùng chung trong Redis: hàng đợi theo thời gian, nội dung sự kiện, sự kiện chết (ADR 0012). Khóa outbox:sender là lease của bộ gửitheo outbox

Ghi chú triển khai (COL-3): registry Redis không đặt TTL cho reg:tok và reg:agent (đồng bộ từ Access Hub qua agents?since= là nguồn xóa, mất mục do TTL sẽ buộc gọi lại hub với mỗi agent), và thêm ba tập chỉ mục reg:srv:{server_id}, reg:co:{company_id}, reg:all phục vụ đếm, thu hồi theo server và purge theo công ty. Client Redis là internal/redisx tự viết (RESP2, không thêm thư viện).

Registry là bản sao đọc của Access Hub. Khi Redis mất hoặc miss, ingest hỏi Access Hub (GET /api/v1/monitoring/collector/agents?token_hash=) tối đa một lần cho mỗi token trong 60 giây, có giới hạn tốc độ toàn cục để tránh bão truy vấn.

2. Bus ​

Interface Go:

go
type Bus interface {
    Publish(ctx context.Context, shard int, batch *SampleBatch) error
    Subscribe(ctx context.Context, shards []int, h Handler) error
}
Triển khaiGiai đoạnĐặc điểm
inproc (channel có giới hạn)1Một node, không bền vững. Đầy thì ingest trả 503 kèm Retry-After
redis (Redis Streams)1 đến 2Một stream mỗi shard (bus:s:<shard>), consumer group workers, ít nhất một lần, tiến trình chết được nhận lại bằng XAUTOCLAIM sau bus.claim_idle. Cho phép tách ingest và worker thành các tiến trình riêng (ADR 0012)
jetstreamchưa cóDự kiến thay Redis khi cần quy mô lớn hơn, giữ interface Bus. Chưa cài đặt

Số shard logic cố định 64 (hash(server_id) mod 64). Worker sở hữu tập shard, tất cả mẫu của một máy chủ luôn tới cùng một worker, nên trạng thái đánh giá nằm trong bộ nhớ mà không cần khóa phân tán. Khi chạy nhiều worker dùng chung một Redis, mỗi worker phải sở hữu một tập shard riêng: worker.shard_count và worker.shard_index (env AHC_WORKER_SHARD_COUNT, AHC_WORKER_SHARD_INDEX) chia shard theo s mod shard_count == shard_index, hoặc liệt kê worker.shards tường minh (không dùng cùng lúc). Không cấu hình gì thì worker đọc cả 64 shard, chỉ an toàn khi có một worker duy nhất, và collector ghi cảnh báo khi bật động cơ luật. Phân chia là tĩnh: worker chết thì các shard của nó chờ trong Redis đến khi worker đó chạy lại, không có failover tự động (đã chấp nhận, xem docs/08).

3. Chuỗi thời gian (VictoriaMetrics) ​

Quy tắc đặt tên ​

  • Tên chỉ số ghi vào TSDB có tiền tố ah_: agent gửi cpu_usage_percent, TSDB lưu ah_cpu_usage_percent.
  • Nhãn hệ thống do collector gắn: company_id, server_id. Không dùng agent_id và hostname làm nhãn vì đổi khi enroll lại hoặc đổi tên, gây bùng nổ cardinality.
  • Nhãn do agent gửi chỉ thuộc danh sách trắng theo chỉ số (ví dụ mount, fstype cho đĩa; iface cho mạng; name cho dịch vụ; port, proto cho port). Nhãn lạ bị bỏ.

Danh mục chỉ số chuẩn và danh sách nhãn cho phép nằm trong bản máy đọc được internal/catalog/metrics.yaml của Collector, đồng bộ với danh mục mà Agent triển khai theo hợp đồng docs/03-protocol.md.

Nhóm chỉ số phục vụ biểu đồ máy chủ (thêm cùng Agent, đều là gauge, không có nhãn trừ khi ghi khác):

Chỉ sốĐơn vịNhãnÝ nghĩa
mem_free_bytes, mem_cached_bytes, mem_buffers_bytes, mem_slab_bytes, mem_page_tables_bytesbytekhôngPhân rã bộ nhớ từ /proc/meminfo (MemFree, Cached, Buffers, Slab, PageTables)
swap_cached_bytesbytekhôngSwapCached
net_rx_packets_per_sec, net_tx_packets_per_secgói/giâyifaceTốc độ gói nhận và gửi theo giao diện mạng
psi_cpu_some_percent, psi_memory_some_percent, psi_io_some_percentphần trămkhôngÁp lực tài nguyên (PSI, some avg10) của CPU, bộ nhớ, I/O

Collector chỉ kiểm tên và nhãn theo catalog. Khoảng giá trị (phần trăm 0 đến 100, byte và tốc độ không âm) do Agent bảo đảm khi đo. Luật rollup 5 phút và 1 giờ cho chỉ số mới được sinh từ catalog bằng collector -rollup-rules (bản dev: deploy/dev/gen-vmalert-rules.sh), không cần sửa tay. Mỗi giao diện mạng thêm 2 series (gói nhận và gửi) vào hạn mức max_series.

Kiểm soát cardinality ​

  1. Agent lọc mount và interface ngay từ nguồn (bỏ tmpfs, overlay, docker, loopback, veth).
  2. Collector áp max_series mỗi agent (mặc định 500) và bỏ series mới vượt mức.
  3. Cảnh báo nội bộ khi số series tổng tăng đột biến (xem 10-observability).
  4. Giá trị nhãn bị cắt 128 byte. Không cho nhãn có giá trị tự do do người dùng nhập ngoài name của dịch vụ đã khai báo.

Ghi ​

Collector ghi bằng API import dạng JSON line của VictoriaMetrics (POST /api/v1/import, mỗi dòng một series với values và timestamps, trả 204), thay cho remote-write để tránh phụ thuộc thư viện nén snappy và protobuf của Prometheus (lệch so với bản thiết kế đầu, không đổi ngữ nghĩa). Nhãn company_id, server_id luôn được đặt sau cùng và thắng mọi nhãn do agent gửi. Worker gom lô theo max_batch=5000 mẫu hoặc 500 ms (cấu hình tsdb.max_batch_samples, tsdb.max_batch_wait). Lỗi tạm thời (5xx, 408, 429, timeout, lỗi mạng): thử lại có backoff từ 200 ms đến tsdb.retry_max, giữ lô, bộ đệm quá 4 lần cỡ lô thì worker dừng nhận từ bus để hàng đợi bus đầy và ingest trả 503. Lỗi vĩnh viễn (4xx khác): bỏ lô, tăng ahc_tsdb_batches_dropped_total, ghi log có mẫu. Khi tắt, worker rút cạn bus rồi flush lần cuối với thời hạn worker.shutdown_flush. Khi tsdb.url trống, collector dùng kho trong bộ nhớ (chỉ dev và kiểm thử).

Bus in-process (bus.queue_per_shard, mặc định 256 lô mỗi shard) chỉ nối ingest và worker trong cùng một tiến trình. Tách vai trò ingest và worker sang tiến trình khác dùng bus.backend: redis (Redis Streams, ADR 0012); cấu hình tách vai trò với inproc bị từ chối khi nạp. JetStream chưa làm, chỉ cân nhắc khi Redis không đủ.

Retention và rollup ​

Bản OSS của VictoriaMetrics áp một retention duy nhất cho mỗi instance và không có downsampling (đây là tính năng bản trả phí, cần kiểm tra lại khi triển khai). Vì vậy dùng hai instance:

InstanceNội dungRetention mặc địnhNguồn
vm-rawMẫu thô 30 giây30 ngàyWorker ghi trực tiếp
vm-longRollup 5 phút và 1 giờ, dạng avg, min, max, last400 ngàyvmalert chạy recording rules từ vm-raw rồi remote-write sang vm-long

Tên rollup: ah_cpu_usage_percent:5m_avg, :5m_min, :5m_max, :5m_last, :1h_avg, ... Luật sinh bằng collector -rollup-rules từ catalog nhúng trong binary (cùng mã mà API series dùng để đọc rollup, nên tên không thể lệch), 8 luật cho mỗi chỉ số: nhóm rollup_5m chạy mỗi 5 phút, rollup_1h mỗi 1 giờ, biểu thức <agg>_over_time(ah_<metric>[5m|1h]). vmalert căn thời điểm đánh giá theo chu kỳ nhóm và mặc định lùi 30 giây (-rule.evalDelay) để bù -search.latencyOffset của vm-raw, nên mẫu mới nhất không bị bỏ sót. Thêm chỉ số vào catalog thì sinh lại luật và nạp lại vmalert (xem 14 mục 5).

API truy vấn tự chọn nguồn (COL-10):

Điều kiệnNguồnBiểu thức
Không có vm-long, hoặc from cách hiện tại không quá 7 ngàyvm-raw<agg>_over_time(ah_m{company_id,server_id}[step])
from xa hơn 7 ngày, step dưới 1 giờvm-long, ô 5 phút<agg>_over_time(ah_m:5m_<agg>{...}[step]), step làm tròn lên bội 5 phút
from xa hơn 7 ngày, step từ 1 giờvm-long, ô 1 giờ<agg>_over_time(ah_m:1h_<agg>{...}[step]), step làm tròn lên bội 1 giờ

Gộp lại các ô bằng cùng hàm là đúng với min, max, last; với avg là trung bình các ô bằng trọng số nhau (ô thiếu mẫu có trọng số như ô đủ, chấp nhận). Rollup trống trong khi khoảng còn chạm retention thô thì collector đọc lại vm-raw (bảo vệ khi vm-long mới thêm hoặc vmalert dừng). Phần cuối của một khoảng dài có thể thiếu tối đa một ô (5 phút hoặc 1 giờ) vì rollup chưa được ghi.

Retention vật lý toàn cụm là trần: vm-raw 30 ngày, vm-long 400 ngày. Retention theo gói (Q17, ADR 0016) áp bên dưới trần đó:

  • Nhãn ngày. Mỗi mẫu được ghi kèm ah_day=YYYYMMDD (ngày UTC của mẫu, collector tự đặt, nhãn cùng tên từ agent bị bỏ), nên mỗi ngày của một series là một series riêng; rollup của vmalert giữ nguyên nhãn. Mọi truy vấn gộp nhãn này (without(ah_day), avg bằng tổng chia số đếm, last ghép theo thời điểm mẫu cuối), nhãn không bao giờ ra khỏi collector. Chi phí đo được: chỉ mục cộng khoảng 40 phần trăm, ghi chậm khoảng 15 phần trăm, truy vấn gần như không đổi.
  • Ân hạn là thời gian để khách tự export dữ liệu của mình qua Access Hub (đọc API series). Hết ân hạn dữ liệu bị xóa vật lý, không có xóa mềm, không có khôi phục từ nền tảng.
  • Đọc bị cắt theo giới hạn đọc của công ty (retention cũ khi còn ân hạn 30 ngày sau lần giảm, retention hiện tại sau đó), ghi không bao giờ vào vùng cũ hơn retention hiện tại (vùng khóa chỉ đọc).
  • Xóa vật lý do janitor ở vai trò admin chạy mỗi giờ: hỏi Access Hub chính sách mới nhất, xóa cả ngày nằm ngoài cửa sổ bằng delete_series{company_id, ah_day} ở cả hai kho, rồi force_merge phân vùng tháng bị ảnh hưởng (tối đa 1 lần mỗi ngày) để dữ liệu rời đĩa. Lưới an toàn ở 03-protocol.md mục 5.1.
  • Dữ liệu trước khi có nhãn ngày: ở vm-raw hết hạn tự nhiên trong 30 ngày; ở vm-long janitor gắn nhãn ngày (xuất, nhập lại, xóa bản cũ) khi series cũ đã ngừng nhận mẫu 3 giờ.

Dung lượng ước tính ​

Xem bảng ở 08-scaling-ha. Cơ sở tính: khoảng 1 byte mỗi mẫu sau nén, 70 series mỗi máy ở cấu hình chuẩn, 2.880 mẫu mỗi series mỗi ngày.

4. Outbox sự kiện ​

Mọi sự kiện gửi Access Hub đi qua outbox bền vững: worker ghi sự kiện vào outbox trước, bộ gửi đọc từ outbox, gửi lô tối đa 200 sự kiện hoặc 1 giây, xác nhận thành công mới xóa.

  • Khóa idempotency: event_id (UUIDv7).
  • Thứ tự: mỗi (server_id, rule_id) có seq tăng dần. Access Hub bỏ sự kiện có seq nhỏ hơn hoặc bằng seq đã xử lý.
  • Access Hub lỗi hoặc không liên lạc được: thử lại backoff tối đa 5 phút, outbox giữ tối thiểu 24 giờ (giới hạn bằng dung lượng, có cảnh báo khi vượt 50%).
  • Access Hub trả 5xx liên tiếp 3 lần cho một lô nhiều sự kiện: bộ gửi giảm một nửa cỡ lô để một lô quá lớn hoặc có sự kiện độc không chặn cả hàng đợi, rồi tăng gấp đôi trở lại sau mỗi lần được nhận đến khi về outbox.batch_max.
  • Sự kiện quá hạn 24 giờ mà chưa gửi được: chuyển sang kho dead-letter và tăng metric để người vận hành xử lý.

5. Bảng trong Access Hub (MySQL) ​

Không nằm trong collector, ghi ở đây để đối chiếu. Đầy đủ cột ở 06-access-hub-integration. Nguyên tắc: không có bảng nào chứa mẫu số liệu.

Trang này có giúp được bạn không?
Sửa trang này

Nội dung đồng bộ từ kho mã access-hub-collector lúc 10:57, 03/10/2026. Khi tài liệu và mã khác nhau, mã thắng.