Gặp cụm Hadoop cũ ở ngân hàng, viễn thông: đọc HDFS, YARN, MapReduce và HBase trước khi chạm vào
Hệ thống chạy dữ liệu giao dịch của khách hàng không cần bạn thích nó, nhưng bạn phải biết nó dễ hỏng ở đâu trước khi chạy job đầu tiên.
- MapReduce · HBase (song song)MapReduce xử lý lô qua YARN; HBase đứng cạnh, đọc/ghi ngẫu nhiên theo thời gian thực
- YARN (nhánh MapReduce)ResourceManager quyết định chia tài nguyên; NodeManager và ApplicationMaster chạy job
- HDFS (nền chung)NameNode giữ metadata, DataNode lưu block nhân bản; HBase cũng lưu trên đây
HDFS là nền chung: MapReduce chạy lô qua YARN, còn HBase đứng cạnh và lưu thẳng trên HDFS.
Đồ hoạ: FDE Times
Tóm tắt nhanh
- HDFS tách metadata (NameNode) khỏi dữ liệu (DataNode); ở Hadoop 1.x NameNode là điểm lỗi đơn.
- YARN quyết định ai được chạy, MapReduce quyết định chạy thế nào: map, shuffle theo key, rồi reduce.
- HDFS ghi một lần đọc nhiều lần; cần cập nhật ngẫu nhiên theo thời gian thực thì dùng HBase.
Thử hình dung ngày thứ hai của bạn ở một ngân hàng. Bạn được cấp quyền SSH vào một edge node, kèm đúng một lời dặn: toàn bộ lịch sử giao dịch nằm trên cụm Hadoop, đừng làm sập nó.
Không ai trong đội dự án còn nhớ cụm được dựng thế nào. Còn bạn phải kéo dữ liệu từ đó để huấn luyện một model phát hiện gian lận trong vòng hai tuần.
Nếu bạn định làm FDE cho ngân hàng hay nhà mạng, nên chuẩn bị tinh thần cho một cảnh như vậy. Bạn không cần thành chuyên gia Hadoop. Bạn chỉ cần đọc được bốn thành phần đủ nhanh để biết chạm vào đâu thì an toàn, chạm vào đâu thì gãy.
Bốn thành phần, hai câu hỏi: dữ liệu nằm đâu, ai được chạy?
Cách dễ nhớ nhất là xếp cụm thành từng tầng. Dưới cùng là HDFS, hệ thống file phân tán. Phía trên là YARN, nơi chia CPU và bộ nhớ. Trên YARN là MapReduce, mô hình xử lý theo lô. HBase đứng cạnh nhánh YARN/MapReduce, dùng thẳng HDFS làm nơi lưu trữ.
Với mỗi thành phần, bạn chỉ cần trả lời hai câu: dữ liệu thật sự nằm ở đâu, và ai có quyền quyết định việc gì được chạy. Hầu hết sự cố bạn gặp ở site đều quy về một trong hai câu đó.
Một file 1 GB trên HDFS thực ra là bao nhiêu mảnh?
HDFS theo kiến trúc master/slave. NameNode giữ namespace và theo dõi mọi file, quyền truy cập và vị trí của từng block. Các DataNode chỉ làm một việc: lưu block.
Giờ tính thử. Tài liệu Hadoop 1.x lấy 64 MB làm kích thước block điển hình. Một file giao dịch 1 GB, tức 1024 MB, sẽ bị cắt thành 16 block. Giả sử hệ số replication là 3, cụm sẽ giữ 48 bản sao block nằm rải trên các DataNode, và NameNode phải nhớ vị trí của cả 48 bản.
Con số này cho thấy hai điều. Về tải, hàng triệu file nhỏ nghĩa là hàng triệu mục metadata dồn lên một NameNode. Về độ bền, HDFS luôn giữ ít nhất một bản sao ở rack khác, nên mất cả một rack vẫn chưa mất dữ liệu.
Replication được đặt theo từng file và có thể đổi sau khi tạo. Vì thế đừng mặc định mọi thư mục có cùng mức an toàn. Cụm đời mới cũng thường dùng block lớn hơn 64 MB, nên hãy kiểm tra cấu hình thật thay vì tin con số trong sách.
Còn một nguyên tắc nền: HDFS ghi một lần, đọc nhiều lần. Bạn không sửa được một dòng ở giữa file. Nếu model của bạn cần cập nhật điểm rủi ro cho từng khách hàng, HDFS không phải nơi để làm việc đó.
Vì sao NameNode là thứ đầu tiên phải hỏi?
Ở Hadoop 1.x, máy chạy NameNode là điểm lỗi đơn của cả cụm. NameNode chết thì DataNode vẫn còn dữ liệu, nhưng không ai biết block nào thuộc file nào.
Thêm một hành vi hay gây hoảng: khi khởi động, NameNode vào trạng thái Safemode và chưa nhân bản block. Một cụm cũ vừa restart có thể đứng ở Safemode khá lâu, và job của bạn sẽ thất bại theo những cách khó hiểu. Đó không phải lỗi của code bạn viết.
Vì vậy, câu hỏi đầu tiên dành cho đội vận hành nên là: cụm này đã bật HA cho NameNode chưa, và lần restart gần nhất mất bao lâu? Câu trả lời cho bạn biết rủi ro thật sự của mọi việc bạn sắp làm.
YARN và MapReduce: job của bạn đang chờ ai?
YARN tách việc quản lý tài nguyên khỏi việc lập lịch và giám sát job, đặt chúng vào các daemon riêng: ResourceManager, NodeManager trên từng máy, và một ApplicationMaster cho mỗi ứng dụng. ResourceManager là nơi quyết định cuối cùng việc chia tài nguyên giữa mọi ứng dụng.
Khi job của bạn cứ nằm ở trạng thái chờ, đừng sửa code vội. Hãy xem ResourceManager đang cấp tài nguyên cho ai. Ở ngân hàng, rất có thể một job đối soát cuối ngày đang được ưu tiên hơn bạn.
MapReduce thì quyết định cách chạy. Ví dụ cụ thể: đếm số giao dịch theo chi nhánh. Đoạn dưới đây là mã giả viết theo kiểu Hadoop Streaming cho dễ đọc; job MapReduce gốc thường được viết bằng Java.
# Mã giả kiểu Hadoop Streaming (MapReduce gốc viết bằng Java)
# map: mỗi dòng giao dịch -> (ma_chi_nhanh, 1)
def map_fn(line):
cols = line.split(",")
yield cols[2], 1
# shuffle: hệ thống gom mọi cặp cùng key về một reducer
# reduce: cộng dồn theo chi nhánh
def reduce_fn(branch, counts):
yield branch, sum(counts)
Pha map biến dữ liệu thành cặp key/value. Pha shuffle đưa mọi cặp cùng key về cùng một reducer. Pha reduce khi đó nhận một chi nhánh kèm toàn bộ danh sách số 1 của nó, chẳng hạn (CN_HN01, [1, 1, 1, …]), rồi cộng lại thành tổng số giao dịch của chi nhánh đó.
Nếu một chi nhánh lớn chiếm phần lớn giao dịch, một reducer sẽ phải gánh phần đó, và bạn sẽ thấy cả job chờ đúng một task cuối cùng.
Hạn chế đáng nhớ nhất là MapReduce thường không giữ dữ liệu trong bộ nhớ giữa các bước. Job lặp nhiều vòng, như huấn luyện model, vì thế chậm hơn hẳn so với Spark. Hãy dùng MapReduce cho việc trích xuất và tổng hợp, đừng dùng nó cho vòng lặp huấn luyện.
Hadoop còn có một triết lý: đưa tính toán đến gần dữ liệu thay vì kéo dữ liệu đi. Phản xạ tải hết về laptop hay đẩy lên cloud thường vừa chậm vừa vướng quy định bảo mật. Hãy chạy bước lọc và tổng hợp ngay trên cụm, chỉ mang kết quả gọn ra ngoài.
HBase: khi cần tra từng khách hàng ngay lập tức
HDFS không cho sửa tại chỗ, nên khi cần đọc hay sửa từng bản ghi, đó là việc của HBase. Đây là kho dữ liệu wide-column phi quan hệ, mô phỏng Bigtable của Google, chạy trên HDFS hoặc Alluxio. Nó cho đọc/ghi ngẫu nhiên theo thời gian thực, tự failover và tự sharding.
Cách chia việc rõ ràng nhất cho dự án gian lận là thế này. Lịch sử giao dịch nhiều năm để trên HDFS, dùng cho huấn luyện theo lô. Hồ sơ rủi ro mới nhất của từng khách hàng, cần tra theo key khi có giao dịch, thì để trong HBase.
Năm việc cho tuần đầu ở site
Trước hết, đọc cấu hình thật. Vài lệnh chỉ đọc là đủ để bắt đầu mà không làm hỏng gì:
hdfs dfsadmin -safemode get
hdfs getconf -confKey dfs.blocksize
hdfs fsck /data/giaodich -files -blocks -locations
yarn application -list
Tiếp theo, hỏi về NameNode HA và lịch restart. Sau đó, tìm hiểu hàng đợi YARN nào dành cho đội bạn và khung giờ nào cụm rảnh. Kế đó, lập bản đồ dữ liệu: cái gì nằm trên HDFS, cái gì nằm trong HBase, mỗi thư mục có replication bao nhiêu. Cuối cùng, chạy một job nhỏ trên một phần dữ liệu trước khi đụng tới toàn bộ bảng.
Nếu bạn đang nhắm tới vị trí FDE, hãy để ý những JD ở ngân hàng hay viễn thông có nhắc Hadoop, HDFS, HBase. Trên CV, một dòng như “đọc fsck và xử lý cụm kẹt Safemode” có giá trị hơn nhiều so với “biết Hadoop”.
Những cú vấp quen thuộc
Cú vấp phổ biến nhất là ghi hàng nghìn file kết quả nhỏ lên HDFS. Mỗi file là thêm metadata cho NameNode, trong khi bạn đang làm việc trên một cụm mà NameNode có thể là điểm lỗi đơn.
Kế đến là coi HDFS như một database và cố cập nhật từng dòng. Rồi tin rằng block size vẫn là 64 MB, hoặc replication ở mọi nơi đều như nhau. Và đổ lỗi cho code khi job thật ra đang chờ tài nguyên hoặc cụm còn trong Safemode.
Lỗi đắt nhất lại không nằm ở kỹ thuật. Đó là chạy một job lớn vào giờ đối soát mà chưa hỏi ai. Ở một cụm mà cả ngân hàng dựa vào, sự tin tưởng của đội vận hành khó lấy lại hơn bất kỳ block nào.
FDE giỏi trên hệ thống cũ không phải người viết lại nó, mà là người hiểu nó đủ để mang được giá trị mới ra mà không làm gãy thứ gì đang chạy.