Thuật toán Ứng dụng — DP, String, Big Data & hơn nữa
~13 phútPattern matching & StringAll-Access

Case study: Lucene index và ClamAV signature

Ba hệ thống thật, ba cách chọn: ClamAV quét nhiều chữ ký bằng Aho-Corasick, GNU grep tìm một chuỗi bằng Boyer-Moore, Lucene tra term bằng FST.

TL;DR: Ba hệ thống, ba bài toán khác nhau nên ba lựa chọn khác nhau. ClamAV phải đối chiếu file với rất nhiều chữ ký virus, nên dựng một automaton Aho-Corasick và đọc file một lần thay vì chạy KMP từng chữ ký. GNU grep tìm một chuỗi trong file lớn bằng họ Boyer-Moore: so từ phải sang trái và nhảy cóc, nên phần lớn byte không bao giờ bị đọc. Lucene cần tra term trong từ điển khổng lồ, kể cả theo tiền tố, nên dùng FST (finite state transducer, một dạng trie nén) trong index của nó. Câu hỏi chọn nằm ở: bao nhiêu pattern, cố định hay đổi liên tục, có cần tìm theo tiền tố không.

ClamAV
ClamAV

Aho-Corasick, quét đồng thời nhiều chữ ký trong một lần đọc file

Lucene
Lucene

FST + inverted index, tra term nhanh trong tập document lớn

Phần A: ClamAV quét nhiều chữ ký thế nào?

1. Vấn đề: một file, rất nhiều chữ ký

ClamAV (Clam AntiVirus) là antivirus mã nguồn mở, hay chạy trong mail server và gateway. Cơ sở dữ liệu của nó gồm nhiều loại chữ ký: băm của cả file, và chữ ký theo nội dung (body-based) là những chuỗi byte đặc trưng của file nhiễm. Tài liệu ClamAV không công bố một con số tổng, nên bài này lấy 8 triệu chữ ký làm ví dụ minh hoạ để tính toán, không phải số đo. Cơ sở chữ ký đủ lớn để quét từng chữ ký một lượt trên mỗi file là không khả thi.

Phương án naive là chạy KMP cho từng chữ ký, tốn O(|file| × số chữ ký): với file 1 MB và 8 triệu chữ ký giả định, khoảng 8 × 10¹² phép so sánh.

Mã nguồn libclamav cho thấy ClamAV không dùng một thuật toán duy nhất. matcher-ac.c là bộ khớp Aho-Corasick: hàm cli_ac_addpatt thêm từng chữ ký vào trie, cli_ac_buildtrie (qua ac_maketrans) tính failure link bằng duyệt theo tầng, cli_ac_scanbuff đi trên trie theo từng byte. matcher-bm.c là một bộ khớp kiểu Boyer-Moore nhiều pattern, dùng bảng nhảy trên khối 3 byte và từ chối chữ ký ngắn hơn 3 byte. Ý của Aho-Corasick (đã học ở bài 05) là gom toàn bộ chữ ký vào một automaton rồi duyệt file đúng một lần: build tốn O(tổng độ dài chữ ký) một lần khi nạp database, quét tốn O(|file| + số lần khớp).

Trie của bốn pattern he, she, his, hers với ký tự trên cạnh; bốn cung nét đứt là failure link khác root: sh về h, she về he, his về s, hers về s

Hình là cấu trúc đó trên bốn pattern nhỏ; phần build và quét giống pseudocode ở bài 05.

2. Chữ ký có wildcard: cắt đoạn rồi kiểm lại khoảng cách

Chữ ký ClamAV không chỉ là chuỗi cố định. Chúng là chuỗi hex có wildcard và khoảng cách:

Plain Text
-- Ví dụ chữ ký dạng đơn giản:
-- "4D5A{10-80}50450000" nghĩa là:
--   4D 5A (header MZ của file PE)
--   rồi 10 đến 80 byte bất kỳ
--   rồi 50 45 00 00 (chữ ký PE)

Trong matcher-ac.c, một chữ ký như vậy được xử lý như chữ ký nhiều phần (partial signature): trie chỉ khoá trên đoạn cố định, và khi một đoạn khớp, cli_ac_scanbuff kiểm tra thêm đoạn trước đó đã khớp chưa, với giới hạn khoảng cách mindist và maxdist giữa hai đoạn.

Chữ ký có wildcard bị cắt thành hai đoạn cố định, automaton quét đoạn, rồi một bước kiểm lại khoảng cách giữa chúng

Automaton không hiểu wildcard và cũng không cần hiểu: nó chỉ trả về vị trí các đoạn cố định. Phần {10-80} được kiểm sau, trên vài vị trí tìm được chứ không phải trên cả file.

Thử ngẫmmột chữ ký mới có 5 đoạn cố định xen kẽ thay vì 2. Bước kiểm khoảng cách sau khi automaton báo vị trí có còn rẻ như minh hoạ ở trên không?

All-Access Pass

Phần còn lại của bài dành cho All-Access Pass

Bạn vừa đọc phần xem trước. Hai bài đầu của mỗi khoá luôn đọc trọn miễn phí.

  • Đọc trọn mọi bài trong 6 khoá System Design và dữ liệu phân tán
  • AI Mentor trả lời theo toàn bộ nội dung bài
  • Trả một lần, không tự gia hạn, không tự trừ tiền

Trọn đời

1.690.000 ₫

Trả một lần, dùng mãi mãi

Gói năm

699.000 ₫

365 ngày · ≈ 58.000 ₫/tháng

Thanh toán bằng thẻ Visa/Master/JCB qua Polar. Xem bảng giá

Đã mua? Đăng nhập để đọc tiếp

Bài này có giúp bạn hiểu bản chất không?

Bài này đáng gửi cho bạn học cùng?

Copy link đã gắn nguồn — dán group, chat, hoặc LinkedIn.

Thảo luận & góp ý

Hỏi đáp về bài này

Bài tiếp theo

Tổng kết module Pattern matching và cheat sheet