Tầm 8-9 về trước, thời Trái Đất vẫn còn chưa nóng lên, khủng long vẫn chạy ầm ầm ngoài phố. Mình vẫn còn trẻ trung, nhiều năng lượng tích cực, và đầy tham vọng phát triển bản thân. Một hôm, sếp gọi mình vào phòng và bảo: “Okay, so we are going to build a datalake”. Nghe cũng rất là cool ngầu, mình hớn hở về nhà nghiên cứu thử xem Data lake là cái gì; lên mạng research thì mỗi người nói một kiểu, và end up là chả hiểu cái gì cả.
Một hôm nọ, bạn mình lại hỏi mình một tí kiến thức căn bản về data, tại sao chúng nó có bảng nọ bảng kia rồi viết cái nọ compact cái kia. Rồi table format với file format loạn xạ cả lên thế là làm sao. Thôi thì mình cũng hứa là còn nhớ được cái gì thì viết lại, coi như là thử viết lại các thứ căn bản; cho ai chưa biết thì hy vọng là mình giúp được 1 chút gì đó.
Từ Data Warehouse đến Data Lake
Ngày xửa ngày xưa, khi dân IT nói đến cơ sở dữ liệu, thì mọi người luôn có tư duy đầu tiên đó là một database table trong một cái hệ thống DB nào đó. Các datasets sẽ được tổ chức thành dạng bảng, và khi mọi người xử lý dữ liệu thì sẽ sử dụng SQL, gần như là ngôn ngữ của Data, để truy vấn(query). Tương ứng với bài mình viết, thì sẽ có hệ thống vận hành tối ưu cho việc viết và lưu trữ dữ liệu(OLTP, thường lưu như MySQL, PostgreSQL), và hệ thống phân tích thì tối ưu cho việc đọc và tính toán(OLAP, có thể lưu trong các Datawarehouse như OracleDWH).
Người dùng tương tác với dữ liệu thông qua hệ thống cơ sở dữ liệu(database), mọi thứ bên trong đều là tables, và mọi người không biết được là ở đằng sau thì dữ liệu được lưu trữ như thế nào, định dạng file ra sao, vì những thứ này đã được database giải quyết hết phía sau. Một giới hạn lớn của những dữ liệu này, đó là hệ thống chỉ lưu trữ và xử lý được những định dạng dữ liệu nhất định, không lưu trữ được các định dạng như textfile, ảnh, logs. Những dữ liệu như thường sẽ được lưu trữ riêng và xử lý theo nghiệp vụ riêng biệt.
Tới những năm 2000, nhu cầu xử lý dữ liệu bắt đầu tăng cao, khi các Internet giant bắt đầu thu thập rất rất nhiều data về để xử lý và phân tích. Sự ra đời của hệ sinh thái Hadoop (gồm 2 phần là lưu trữ - HDFS và xử lý - Map-Reduce framework) đã đẩy mạnh sự phát triển của cluster computing: thay vì chỉ có thể lưu trữ và xử lý dữ liệu bằng những máy chủ xịn xò nhất(mà vẫn có giới hạn), dữ liệu bây giờ được lưu trữ và phân tán(distributed) ở trên commodity hardware và có thể scale (gần như) không giới hạn.
Những công ty tech lớn đầu tiên nắm bắt việc thâu tóm và xử lý dữ liệu đã đạt những thành công rực rỡ. Nhận thấy điều đó, tất cả các công ty lớn đều bắt đầu nhảy vào cuộc chơi Big Data: thu thập càng nhiều dữ liệu về càng tốt, bất kể định dạng, chất lượng; rồi sau khi có dữ liệu thì họ sẽ nghiên cứu và khai thác sau. Dần dần thay thế cho các bước xử lý dữ liệu truyền thống (ETL - Extract, Transform, Load), đó là ELT (Load trước và Transform sau). Đây có thể coi là tiền đề dẫn đến sự hình thành của Data Lake: một nơi chứa tất cả các dữ liệu mà bạn có thể thu thập được, dưới định dạng file; tất cả các dữ liệu sẽ được mang hết về một nguồn, sau đó sẽ được dần dần khai thác sử dụng phục vụ mục đích của business. Data ở trong lake sẽ nằm dưới dạng file, nên là khi sử dụng có thể xử lý thẳng từ file luôn.
Data Warehouse:
Dữ liệu được Cleaned, Structured and Organized thành table
ETL: Dữ liệu qua xử lý và được mang vào Data Warehouse
Truy vấn thực hiện bằng SQL
Data Lake:
Dữ liệu được collect dưới dạng file, các dataset cũng nằm dưới dạng file/folders
ELT: Dữ liệu được thu thập trước theo dạng raw, rồi tuỳ vào mục đích sử dụng mới được xử lý tiếp.
Xử lý thẳng trên file lưu trữ dữ liệu
Note thêm, là sau khi big data được mang lên Cloud, các cloud providers đã xây dựng hệ thống filesystem tương thích với HDFS (HDFS-compliant, có những file API tương thích với HDFS API nên là có thể sử dụng drop-in), như là S3, GCS, hay ABFS, ADLS2. Không chỉ handle được các dữ liệu lưu trư bằng hdfs, mà các hệ thống cùng hỗ trợ các lưu trữ trên s3:// hay gs://, vân vân và mây mây.
Hive Metastore và Logical Data Lake
Với sự phát triển của Hadoop và Map-Reduce, các thợ code của những năm 2000 đã trở nên mạnh mẽ hơn rất nhiều, khi họ bây giờ đã có thể xử lý những datasets ở tầm cỡ TBs, PBs. Tuy nhiên, truy vấn những datasets này bằng Map-Reduce không hề đơn giản, vì mọi người sẽ phải sử dụng low-level JAVA APIs để viết ra logic xử lý dữ liệu. Ngược lại, khi tư duy về dữ liệu của bạn đi theo dạng table, thì sử dụng SQL truy vấn lại thường thuận lợi hơn nhiều. Cấu trúc quản lý các bảng cũng là một thứ dễ nắm bắt hơn, khi bạn cần biết đến tên bảng chứ không cần biết đến địa chỉ của từng file dữ liệu bên trong.
Ví dụ:
Ở trong một hệ thống SQL, bạn có thể đếm tất cả users
`SELECT count(1) FROM db.users`
Với Hadoop, bạn phải: (1) biết nơi chứa dữ liệu `
s3://storage/raw/users`
(2) viết 1 đoạn Map-Reduce bằng Java để đọc và parse dữ liệu, rồi mới đếm.
Đó là chưa kể đến những vấn đề như khó quản lý những datasets (bạn không biết là có bao nhiều datasets được tạo ra, những datasets nằm ở đâu trên HDFS. Hậu quả có thể dẫn đến là bạn có rất nhiều dữ liệu rác, dữ liệu thừa, hoặc là dữ liệu không được quản trị tử tế.
Đến những năm 2010, Hive được ra đời, xây dựng một SQL interface lên việc xử lý dữ liệu lớn. Bạn viết SQL (thực tế gọi là HiveQL nhưng cũng khá gần như vậy), và đằng sau Hive sẽ dịch những câu truy vấn thành những lệnh xử lý phía sau. Đây là một bước tiến lớn về việc xử lý big data, vì SQL gần như là ngôn ngữ dân IT dùng để nói chuyện với dữ liệu, nên là nhiều người đã dễ dàng tiếp cận dữ liệu lớn hơn mà không cần biết viết Map-Reduce job.
Một thứ khác mà Hive mang đến, mà đến tất cả các hệ thống xử lý big data về sau đều có sử dụng (Spark, Presto/Trino etc), đó là Hive Metastore. Hive Metastore là nơi sẽ lưu trữ các metadata về các datasets ở trong Datalake: thay vì bạn phải biết physical location của một datasets ở trong lake, bạn đặt cho nó một cái logical table name, và bạn có thể sử dụng SQL để truy vấn nó. Rõ ràng, thay vì phải thuộc lòng 1 cái đoạn tên dài ngoằng `s3://company-datalake/storage/data/txn..
`, bây giờ bạn có thể đặt cho nó một cái lên `db.transactions`
, và xử lý từ đó sẽ dễ dàng hơn nhiều. Hive Metastore sẽ lưu thông tin về tên bảng, địa chỉ, cách partition, các cột trong bảng, định dạng file, số lượng partitions cũng như địa chỉ của từng partition ở đâu trên datalake của bạn.
Hive Metastore bao gồm 2 phần:
Hive Metastore DB: là một SQL database chứa các metadata information
Hive Metastore Service: là một hệ thống nhỏ, có các API để các hệ thống Query Engine bên ngoài có thể lấy được các thông tin metadata information ở bên trong. Serve được Thrift hoặc là HTTP Trafic (nhưng hầu hết là mọi người sử dụng Thrift để tối ưu volume traffic)
Có tất cả metadata information của Data Lake vô cùng tiện lợi, thế nên các Data Processing Engine trên Big Data cũng sẽ thường kết nối thẳng vào Hive Metastore service để có chung một view lên hệ thống Datalake. Cả Spark, Trino, Hive có thể dùng tên table để access cùng dữ liệu bên trong thông qua SQL API, mà không cần biết đến location của các file dữ liệu thực tế. Hive Metastore mang lại một logical, structured view của các datasets bên trong Data Lake.
Dĩ nhiên, sẽ có những dữ liệu thô hơn, khó có thể chuyển về dạng table, như file log, hay là text/image gì đó. Các dữ liệu đó sẽ vẫn được tính là dữ liệu của data lake, chỉ là nó không có logical name ở trong metadata. Những dữ liệu này thường sẽ được quản lý riêng biệt. Hoặc một dạng khác là log, thì có thể sẽ được parse để lấy những thông tin quan trọng nhất và lưu vào định dạng phù hợp để được tạo logical mapping.
File Format và một tỷ vấn đề của nó
Khi bạn lưu trữ đến hàng PBs dữ liệu ở trong Data Lake, thì lúc đó những định dạng file mà bạn sử dụng sẽ trở nên quan trọng. Khi nói đến những định dạng file ở trong Data Lake, thì chủ yếu là mọi người sẽ quan tâm đến những dữ liệu mang tính structured hơn, có định dạng format rõ ràng và có thể sử dụng dễ dàng hơn (bỏ tạm qua một bên các dữ liệu raw text hoặc image)
Dạng dữ liệu căn bản nhất cho dữ liệu structured thì chính CSV file (comma-separated values), là dữ liệu được viết dưới dạng raw text, các trường(field) được tách biệt bằng dấu phẩy(comma). Có một số biến thể của định dạng này như là TSV(thay dấu phẩy bằng dấu tab), hoặc là các loại delimiter khác(như là |).
Một vấn đề của định dạng này là tất cả thông tin được lưu trữ dưới dạng raw text, nên khi muốn sử dụng các loại định dạng dữ liệu khác nhau, bạn sẽ phải Cast(biến thể) nó về loại định dạng đúng: INTEGER, DECIMAL, hay TIMESTAMP. Khi bạn không cẩn thận với việc xử lý có thể dễ dẫn đến sai sót.
Một hướng xử lý đó là áp đặt typing lên những loại dữ liệu này. Bạn sẽ định dạng sẵn format của dữ liệu, rồi sử dụng các biện pháp serializing để giảm thiểu sai sót cũng như giảm dung lượng của dữ liệu. Hai hình thức tiêu biểu của trường phái này là AVRO hay protobuf protocol. Tuy nhiên hai hình thức trên lại hay được sử dụng để làm service-level communication hơn. Những biện pháp này được sắp xếp là row-oriented data serialization framework, hay là một cách chuyển hoá dữ liệu theo hàng ngang.
Ở trong môi trường big data, để tối ưu về lưu trữ cũng như di chuyển dữ liệu, column-oriented data serialization được dùng nhiều hơn rất nhiều. Đó là về hai đặc điểm của việc phân tích dữ liệu lớn: (1)bạn sẽ thường chỉ quan tâm đến 1 số columns nhất định trong phân tích của mình, và (2)khi ghép những dữ liệu tương tự với nhau lại, thì bạn sẽ có nhiều cách hơn để tối ưu việc lưu trữ dữ liệu. Sử dụng dữ liệu theo hàng dọc sẽ mang lại nhiều ưu điểm trong big data, và thế nên hầu hết các hệ thống xử lý dữ liệu lớn đều dùng default là dùng dữ liệu dọc. Nổi tiếng nhất và cũng được sử dụng nhiều nhất là Parquet, một định dạng được sáng tạo ra tại Twitter + Cloudera, và ORC, được sáng tạo tại Facebook + Hortonworks; và hai loại định dạng này là default cho tất cả các loại file được viết và đọc trong hệ thống Big Data. Ngoài ra, còn các nghiên cứu về columnar data nhưng dùng để communicate và transfer data giữa các hệ thống (tương tự như Protobuf ở trên nhưng cho data), ví dụ như Arrow.
Các định dạng columnar đều được thiết kế với một đoạn header chứa metadata information về dữ liệu, rồi sau đó đến các dữ liệu được compacted và xếp theo hàng dọc. Với dữ liệu metadata ở đầu, sẽ có các thông tin, statistics về dữ liệu để giúp cho việc đọc file dữ liệu nhanh hơn.
Một phần khác hay được quan tâm về dữ liệu lớn là về việc compress dữ liệu. 3 thể loại common nhất mọi người hay quan tâm đến đó là gzip
, bzip2
và xzip
, và tuỳ theo nhu cầu về CPU hay sizing của file, và đặc biệt là parallelism (cho các hệ thống parallel computing).
Các hệ thống xử lý big data đều sử dụng các file buffer để đọc dữ liệu. Để tối ưu quá trình viết và đọc file, giảm thiểu số lần phải đọc và viết, các file thường xuyên được khuyến cáo để tối ưu hoá, đạt được một dung lượng nhất định. Quá trình này được gọi là compaction, chuyển file về dung lượng ~256MB, theo khuyến cáo của các cloud provider.
Table Format và thời đại Delta Lake
Tất cả các thông tin ở phía trên, thì lại chỉ là liên quan đến định dạng của file (file format). Ở trong các hệ thống Big Data, chúng ta cần phải quan tâm đến dataset một cách tổng thể. Cấu trúc chung của cả Table thì chúng ta gọi nó là Table Format, là một thứ khác với File Format.
Một bảng dữ liệu với thông tin metadata của bảng ở trong Hive Metastore, và các file dữ liệu ở bên ngoài, kết hợp lại với nhau, thì được gọi chung là Hive Table Format. Ngoài những thông tin descriptive, mô tả về dataset, Hive còn thêm một chức năng nữa là Collect Table Statistics. Tương tự như File-level statistics của các định dạng Parquet, ORC, các statistics này của table sẽ được lưu cùng vào Metastore DB, và sẽ được sử dụng trong quá trình xây dựng query plan.
Khi các hệ thống Query Engine xử lý 1 dataset:
Đọc các thông tin về các Metadata của bảng ở trong Hive Metastore
Từ câu query ở trên để xây ra một Logical Query Plan
Dựa vào các thông tin đã có sẵn trong hệ thống, biến Logical Query Plan thành Physical Query Plan
Chuyển task về từng worker để xử lý Physical Query Plan.
Tuỳ vào hệ thống, sẽ có chút khác biệt giữa các đoạn ở trên nhưng có thể nói đó là cái khung chính của việc xử lý.
Hive Table Format, mặc dù rất tiện lợi và dễ sử dụng, nhưng nó lại có một số vấn đề giải quyết chưa đủ tốt. Metadata của Table bị chia cắt làm 2 phần, giữa Table-level và File-level, và thực sự chưa có cách nào thực sự đủ tốt để synchronize giữa những 2 phần này với nhau. Ở những dataset với tốc độ update nhanh, như các near-realtime dataset, hoặc những data có nhu cầu overwrite/upsert/versioning, Hive Table Format sẽ không xử lý được những vấn đề một cách mượt mà. Thay đổi partitioning scheme cũng vô cùng phức tạp và sẽ cần phải tạo lại dataset từ đầu.
Các table format thế hệ mới (Hudi, Delta, Iceberg) sẽ tìm cách để xử lý những vấn đề trên bằng cách mang cả table-level statistics về cùng với file-level statistics. Thay vì lưu các thông tin về partition vào trong Metastore DB, những metadata này sẽ được lưu vào cùng với table, thành 1 metadata folder trong data folder. Với việc có những metadata ở cùng 1 chỗ, các dataset này cũng có thể lưu thêm được những thông tin extra như action log, version information. Xử lý được thêm các bài toán của Data Warehouse như Data Versioning, Time Travel, Rolling Back, etc. Từ đó có thêm tên của thế hệ mới, đó là Lakehouse.
Kết
Những cái này mình cũng viết ra từ những gì mình ngộ ra được. Còn những thứ mới mà thế giới mới vẽ ra thì mình chưa học được (vì dạo này làm ở công ty không đụng đến các thứ này). Thôi biết được đến đâu thì đến, hy vọng mọi người thấy có ích là được.
Nếu bạn thấy bài viết này thú vị, bạn có thể xem thử:
vô tình đọc bài của a trên Thread, thấy a viết nhiều bài hay quá, cách viết hay cả nội dung đều hợp (vì e cũng đang làm DE) nên mò qua cả đây đọc. nếu có thể mong a viết nhiều hơn về mấy cái open table format hay cái s3 table mới ra. cảm ơn anh nhiều ạ hehe