Mô hình MapReduce là một mô hình lập trình giúp các ứng dụng có thể xử lý nhanh hơn một lượng dữ liệu lớn dữ liệu trện các máy phần tán song song, độc lập với nhau từ đó giúp rút ngắn th
MÔ HÌNH MapReduce
Tổng quan về MapReduce
1.1.1 Sự quan trọng của MapReduce
Về tính thiết thực, MapReduce là công cụ rất hiệu quả để giải quyết các bài toán dữ liệu lớn, cho phép xử lý lượng dữ liệu khổng lồ thông qua phân tán và tính toán song song Bên cạnh đó, MapReduce đóng vai trò quan trọng trong việc thay đổi cách sắp xếp và thực thi các phép tính trên quy mô lớn, đặt nền móng cho các hệ thống xử lý dữ liệu phân tán hiện đại như Hadoop và các khung công tác tương tự.
MapReduce không phải là mô hình tính toán song song đầu tiên, dù nó là một trong những mô hình được áp dụng rộng rãi và thành công nhất trong xử lý dữ liệu lớn Mô hình cổ điển được xem như nền tảng là PRAM (Parallel Random Access Machine), xuất hiện từ nhiều thập kỷ trước và mô tả một hệ thống với nhiều vi xử lý chia sẻ một bộ nhớ chung để cùng xử lý lượng dữ liệu lớn Trong PRAM, các lõi xử lý hoạt động song song để tạo ra kết quả từ dữ liệu được chia sẻ Ngoài PRAM, các mô hình khác như LogP và BSP (Bulk Synchronous Parallel) cũng được nghiên cứu, nhưng cho tới nay chưa có mô hình nào đạt được mức độ thành công và phổ biến rộng như MapReduce.
MapReduce là mức trừu tượng thành công nhất cho xử lý dữ liệu trên các tài nguyên tính toán mở rộng cho tới nay Mức trừu tượng này giải quyết sự phức tạp bằng cách che giấu chi tiết và định hình hành vi để người dùng dễ làm việc với nó Tuy nhiên, mức trừu tượng này không hoàn hảo: nó làm cho một số công việc dễ dàng, nhưng lại khiến những công việc khác khó khăn hoặc đôi khi bất khả thi Vì vậy, việc áp dụng MapReduce vào một số bài toán có những hạn chế nhất định Điều này cho thấy MapReduce không phải là mô hình cuối cùng trong lớp các mô hình lập trình cho xử lý tính toán trên quy mô lớn, mà chỉ là một bước tiến trong thiết kế các hệ thống xử lý dữ liệu lớn hiệu quả.
1 http://en.wikipedia.org/wiki/Parallel_Random_Access_Machine
2 http://en.wikipedia.org/wiki/LogP_machine
3 http://en.wikipedia.org/wiki/Bulk_Synchronous_Parallel
Giải quyết các bài toán dữ liệu lớn đòi hỏi một cách tiếp cận đặc thù, thường đối lập với mô hình tính toán truyền thống MapReduce là một mô hình và khung xử lý phân tán cho các tập dữ liệu khổng lồ, thực hiện qua hai bước chính: map và reduce Trong quá trình này, dữ liệu được phân tách và xử lý song song trên một cụm máy tính, sau đó được ghép nối và sắp xếp trong bước shuffle để tối ưu việc di chuyển dữ liệu MapReduce giúp tách riêng logic xử lý khỏi hạ tầng, mang lại khả năng mở rộng theo quy mô dữ liệu và độ tin cậy cao nhờ cơ chế fault tolerance; nếu có sự cố, công việc có thể phục hồi Đây là lựa chọn phù hợp cho các tác vụ xử lý batch với các bài toán đếm, tổng hợp và phân tích dữ liệu phân tán, dù đôi khi không phải tối ưu cho các thuật toán lặp lại hoặc yêu cầu thời gian thực Các tối ưu như combiner, partitioner và tối ưu hoá sắp xếp dữ liệu có thể cải thiện hiệu suất và tối ưu hóa phân bổ công việc, giúp hệ thống MapReduce trở thành công cụ cốt lõi trong hệ sinh thái xử lý dữ liệu lớn.
Scale out chứ không nâng cấp: để tăng sức mạnh xử lý, thay vì nâng cấp bộ vi xử lý hay hệ thống lưu trữ, giải pháp tối ưu là tăng số lượng máy chủ thông dụng (low-end server) Việc mở rộng theo hướng này kinh tế hơn nhiều vì chỉ bổ sung thêm máy tính và tận dụng hạ tầng có sẵn, trong khi nâng cấp có thể đòi hỏi mua mới toàn bộ dàn server Thêm vào đó, chi phí cho một server chuyên dụng thường cao hơn nhiều so với một cụm máy tính thông thường có hiệu năng tương đương.
Trong một cluster với số lượng server ngày càng lớn, lỗi xảy ra là chuyện bình thường và không thể tránh khỏi Các dịch vụ phân tán trên nhiều máy chủ phải được thiết kế để đối phó với cả lỗi phần cứng lẫn lỗi phần mềm thường gặp, nhằm duy trì tính sẵn sàng và hiệu suất Mô hình MapReduce cung cấp khả năng chịu lỗi nhờ các cơ chế như tự động khởi động lại các task trên các nút cluster khác nhau, khôi phục tiến trình và tiếp tục xử lý dữ liệu một cách liên tục Nhờ đó hệ thống có thể hoạt động liên tục ngay cả khi một phần tài nguyên gặp sự cố, giảm downtime và tối ưu hóa đường đi dữ liệu trong môi trường đám mây hoặc trung tâm dữ liệu.
Trong các ứng dụng tính toán hiệu năng cao (HPC), các nút xử lý và nút lưu trữ thường được kết nối với nhau bằng một liên kết tốc độ cao Nhiều tác vụ xử lý dữ liệu nặng không đòi hỏi sức mạnh tính toán vượt trội, vì vậy việc tách rời lưu trữ dữ liệu khỏi quá trình tính toán có thể tạo ra bottleneck mạng và ảnh hưởng đến hiệu suất Do đó, chuyển sự thực thi xử lý đến dữ liệu thay vì di chuyển dữ liệu tới nơi xử lý trở nên hiệu quả hơn Kiến trúc MapReduce đặt bộ xử lý và đĩa lưu trữ gần nhau, cho phép tận dụng dữ liệu cục bộ bằng cách chạy mã trực tiếp trên khối dữ liệu cần xử lý Hệ thống tập tin phân tán đảm nhiệm quản lý dữ liệu mà MapReduce thao tác, giúp quản lý và tối ưu hóa quá trình xử lý dữ liệu lớn.
Xử lý dữ liệu tuần tự và tránh truy cập ngẫu nhiên là chiến lược tối ưu khi làm việc với lượng lớn dữ liệu, vì bộ nhớ có giới hạn nên dữ liệu được lưu trên đĩa và xử lý dần theo từng khối Truy cập ngẫu nhiên thường bị hạn chế bởi sự di chuyển của đầu đọc và tốc độ đĩa, khiến tiến trình xử lý chậm lại Vì vậy MapReduce được thiết kế để xử lý các khối dữ liệu của một tập dữ liệu lớn, tối ưu hóa hiệu quả bằng cách làm việc theo chuỗi và giảm thiểu truy cập ngẫu nhiên.
MapReduce che giấu các chi tiết hệ thống ở mức thấp khỏi nhà phát triển ứng dụng, giúp các lập trình viên dễ dàng viết các ứng dụng xử lý phân tán Thay vì phải đối mặt với triển khai phức tạp bên dưới, nó cung cấp một mô hình lập trình trừu tượng với các giao diện đơn giản được định nghĩa sẵn.
Phương pháp phân chia để trị là cách phổ biến để giải quyết các bài toán dữ liệu lớn hiện nay Ý tưởng là phân mảnh một bài toán phức tạp thành các bài toán con nhỏ, độc lập với nhau và có thể được giải song song bởi các workers khác nhau Các workers này có thể là các tiến trình trên CPU, các lõi của bộ xử lý đa nhân, các máy trong một máy tính, hoặc các máy thuộc một cụm máy tính Các kết quả trung gian từ từng worker được ghép lại để hình thành kết quả cuối cùng.
Hình 1.1 Mô hình chia để trị
MapReduce có nguồn gốc từ lập trình hàm (Functional Programming) Ví dụ điển hình cho lập trình hàm là các ngôn ngữ Lisp và ML, nơi khái niệm hàm bậc cao (higher-order functions) cho phép một hàm nhận tham số là một hàm Trong phạm vi này, hai hàm bậc cao thường được xây dựng sẵn là Map và Fold, đóng vai trò nền tảng trong xử lý dữ liệu theo mô hình Map và Reduce của MapReduce.
Như hình minh họa dưới đây, Map nhận tham số là một hàm f có một tham số và áp dụng f cho toàn bộ phần tử trong danh sách Fold nhận tham số là một hàm g có hai tham số và một giá trị khởi tạo: g được áp dụng lần đầu với giá trị khởi tạo và phần tử đầu tiên của danh sách, kết quả được lưu vào biến trung gian; sau đó biến trung gian này được dùng cho phần tử tiếp theo và quy trình này lặp đi lặp lại cho từng phần tử cho tới khi danh sách kết thúc, cho ra kết quả cuối cùng.
Trong quá trình xử lý, ta lấy lần lượt từng phần tử trong danh sách làm tham số cho hàm g Quá trình này lặp lại cho đến khi toàn bộ danh sách được xử lý Phép gập Fold trả về kết quả cuối cùng, chính là giá trị cuối cùng của biến trung gian sau khi mọi bước đã được thực thi.
Hình 1.2 Hàm Map và Fold trong Functional Programming
Hàm Map trong MapReduce tương ứng với hàm Map, hàm Reduce tương ứng với hàm Fold trong lập trình hàm
1.1.3 Cấu trúc dữ liệu trong MapReduce
Trong MapReduce, các cặp key-value là cấu trúc dữ liệu cơ bản dùng để tổ chức và truyền tải dữ liệu giữa các bước xử lý Key và value có thể nhận các giá trị thuộc các kiểu dữ liệu cơ bản như số nguyên, số thực và chuỗi, hoặc cũng có thể là các kiểu giá trị có cấu trúc do người dùng định nghĩa để đáp ứng các nhu cầu xử lý dữ liệu phức tạp.
MapReduce coi việc xác định cấu trúc key-value trên các tập dữ liệu cần xử lý là một phần cốt lõi Ví dụ với một tập các trang web, các key có thể là URL và giá trị là nội dung của trang HTML; với một đồ thị, key có thể là node id và giá trị là danh sách kề của node đó Trong một số thuật toán, key được dùng để phân biệt các bộ dữ liệu (tương tự khái niệm khóa trong cơ sở dữ liệu), trong khi ở một số thuật toán khác, các input key lại không quan trọng và thường bị bỏ qua.
Trong MapReduce, lập trình viên định nghĩa một lớp Mapper và một lớp Reducer với hai hàm cơ bản sau:
Bộ khung thực thi
Một trong những ý tưởng quan trọng nhất của MapReduce là tách biệt việc xử lý phân tán cái gì (what) ra khỏi việc xử lý phân tán như thế nào (how) Một MapReduce Job gồm mã cho Mapper, Reducer và có thể thêm Partitioner và Combiner, được đóng gói lại với nhau cùng các tham số cấu hình (ví dụ vị trí các tập tin đầu vào và nơi lưu trữ đầu ra) Nhà phát triển đưa chương trình lên cho node quản lý tác vụ trong cluster (trong Hadoop gọi là JobTracker) và execution framework xử lý tất cả những thứ khác: xử lý trong suốt các vấn đề của việc thực thi mã lệnh phân tán Các chức năng chính của Execution framework bao gồm quản lý và điều phối việc thực thi phân tán, theo dõi tiến trình và xử lý lỗi.
Mỗi chương trình MapReduce được chia nhỏ thành các đơn vị nhỏ gọi là tasks
Ví dụ, trong hệ thống MapReduce của Hadoop, một map task chịu trách nhiệm xử lý một khối các cặp key-value nhất định, được gọi là input split Tương tự, một reduce task xử lý một phần của không gian khóa và tổng hợp các kết quả từ các map task để tạo ra kết quả cuối cùng Việc phân chia công việc thành input splits và phân vùng không gian khóa giúp tối ưu hóa xử lý song song dữ liệu lớn và nâng cao hiệu suất tổng thể của quá trình xử lý.
1.2.2 Di chuyển dữ liệu và mã lệnh Ý tưởng của MapReduce là di chuyển mã lệnh, không phải di chuyển dữ liệu
Trong một số trường hợp, để các phép tính có thể thực thi, dữ liệu phải được đưa tới mã lệnh Trong MapReduce, quá trình này phụ thuộc rất nhiều vào hệ thống file phân tán Để tối ưu việc xử lý dữ liệu cục bộ, scheduler sẽ khởi động task tại node chứa khối dữ liệu cần thiết cho task đó Nếu điều này không thực hiện được do đang có quá nhiều task, một task mới sẽ được tạo tại node khác và dữ liệu sẽ được truyền qua mạng đến node đó để xử lý.
Việc đồng bộ hóa chỉ đến các cách thức để các tiến trình đang xử lý đồng thời có thể hợp lại (“join up”), ví dụ chia sẻ kết quả trung gian hoặc trao đổi thông tin trạng thái
Trong MapReduce, việc đồng bộ hóa xảy ra giữa pha map và reduce Các cặp key-value trung gian phải được gộp theo khóa, điều này đạt được bằng một phép toán sắp xếp phân tán lớn trên tất cả các node đã chạy map tasks và tất cả các node sẽ chạy reduce tasks
Dữ liệu trung gian được copy qua mạng, vì thế tiến trình này thường được gọi là
Shuffle and sort is a core phase in MapReduce In a job with m mappers and r reducers, the framework may perform up to m × r copy operations because each mapper can emit output to any or all reducers This shuffle step redistributes data so that all values with the same key are directed to the same reducer, enabling correct grouping and aggregation during the subsequent reduce phase Efficiently managing these copy operations is essential for performance, as excessive inter-node transfer can become a bottleneck in distributed processing.
MapReduce được thiết kế để đảm bảo hoàn thành mọi tác vụ ngay cả trong môi trường xảy ra lỗi thường xuyên Do hướng tới các cụm máy giá rẻ (low-end), quá trình thực thi có thể gặp sự cố, đặc biệt ở các cụm máy lớn nơi lỗi đĩa cứng và RAM thường xuyên xảy ra Vì vậy MapReduce phải có cơ chế xử lý và phục hồi lỗi hiệu quả, nhằm duy trì tiến độ và tính sẵn sàng của quá trình xử lý dữ liệu.
Hệ thống file phân tán
Chúng ta đã tập trung nhiều vào xử lý dữ liệu lớn và các công cụ công nghệ Tuy vậy, một yếu tố thiết essential khác không kém phần quan trọng là nguồn dữ liệu Nếu không có dữ liệu làm đầu vào, mọi quy trình xử lý dữ liệu sẽ không thể diễn ra và mục tiêu phân tích sẽ bị bỏ lỡ Vì vậy, chất lượng, sự phong phú và tính tin cậy của dữ liệu đóng vai trò nền tảng cho mọi chiến lược xử lý dữ liệu và quyết định kinh doanh Để khai thác tối đa giá trị từ dữ liệu, cần kết hợp quản trị dữ liệu tốt với công nghệ xử lý hiện đại và đảm bảo nguồn dữ liệu đầy đủ, có cấu trúc và dễ tích hợp.
Trong tính toán hiệu năng cao (HPC) và các kiến trúc cụm truyền thống, lưu trữ được xem như một thành phần riêng biệt với quá trình tính toán Mối quan hệ này ảnh hưởng trực tiếp đến hiệu suất I/O, khả năng mở rộng và độ tin cậy của hệ thống, bởi dữ liệu và thao tác lưu trữ phải đáp ứng tốc độ và đồng bộ hoá với tiến trình tính toán Vì vậy, tối ưu hoá lưu trữ và quản lý dữ liệu là yếu tố then chốt để tối đa hoá hiệu năng HPC, cân bằng giữa băng thông, độ trễ và khả năng xử lý đồng thời của các ứng dụng mô phỏng, phân tích dữ liệu lớn và tính toán song song.
Có nhiều cách cài đặt hệ thống lưu trữ và xử lý dữ liệu, trong đó NAS (Network-Attached Storage) và SAN (Storage Area Network) được sử dụng phổ biến Dù chọn NAS hay SAN, chu trình xử lý vẫn không đổi: các node tính toán lấy đầu vào từ nguồn lưu trữ, nạp dữ liệu vào bộ nhớ, xử lý dữ liệu và ghi kết quả ngược trở lại hệ thống lưu trữ Việc lựa chọn giữa NAS và SAN phụ thuộc vào yêu cầu về hiệu suất, khả năng mở rộng và mức truy cập đồng thời, nhưng bản chất chu trình xử lý dữ liệu vẫn là như vậy Hệ thống lưu trữ mạng giúp dữ liệu được truy cập nhanh chóng và hỗ trợ các tác vụ tính toán và phân tích dữ liệu hiệu quả hơn.
Khi kích thước dữ liệu càng tăng lên thì khả năng xử lý cũng phải tăng lên
Khi khả năng xử lý tăng, sự liên kết giữa các node lưu trữ và node xử lý có thể trở thành một rào cản về hiệu năng Để đạt hiệu suất cao, cần đường truyền mạng tốc độ cao (ví dụ: 10 gigabit Ethernet, InfiniBand), nhưng đây không phải giải pháp kinh tế tối ưu Một cách khác là bỏ qua sự tách biệt giữa lưu trữ và tính toán, chính là ý tưởng đằng sau các hệ thống file phân tán dưới MapReduce Google File System (GFS) là hệ thống file phân tán riêng của Google, trong khi Hadoop Distributed File System (HDFS) là một phiên bản mã nguồn mở của GFS Ý tưởng chính là chia dữ liệu thành các khối và sao lưu các khối đó trên đĩa của các node trong cluster (mặc định là 3 bản sao), với kích thước khối phổ biến là 64MB Hệ thống file phân tán dùng kiến trúc master-slave: master duy trì không gian tên (metadata, cấu trúc thư mục, ánh xạ file sang các block, vị trí các block, quyền truy cập) còn slave quản lý các khối dữ liệu Trong GFS, master được gọi là GFS Master và slave là GFS ChunkServer; trong Hadoop, master được gọi là NameNode và slave là DataNode Cả hai hệ thống hoạt động tương tự, tuy nhiên HDFS không cho phép ghi thêm vào file và hiệu suất của HDFS cũng hơi chậm hơn so với GFS.
Hình 1.5 Kiến trúc của HDFS
NameNode là thành phần chịu trách nhiệm quản lý không gian tên của hệ thống lưu trữ, bao gồm metadata, cấu trúc thư mục, ánh xạ từ file tới các block, vị trí của các block và quyền truy cập, nhằm đảm bảo dữ liệu được quản lý một cách có cấu trúc và an toàn Các dữ liệu liên quan được nạp vào bộ nhớ để truy cập nhanh và tối ưu hiệu suất hệ thống Bên cạnh đó, NameNode định vị và điều phối các phép toán trên file, điều khiển các ứng dụng khách và đảm bảo quá trình đọc ghi dữ liệu diễn ra một cách trơn tru.
Trong hệ thống HDFS, các client kết nối trực tiếp với các datanode để đọc dữ liệu và cấp phát các block phù hợp cho ghi Toàn bộ quá trình trao đổi diễn ra trực tiếp giữa client và datanode, không qua trung gian Khi một file bị xóa, HDFS không thu hồi ngay không gian lưu trữ mà các block được thu gom từ từ thông qua lazy garbage collection, tối ưu hóa quản lý không gian lưu trữ và hiệu suất hệ thống.
Để duy trì hoạt động ổn định của hệ thống file, namenode định kỳ gửi heartbeat đến datanode nhằm bảo đảm tính toàn vẹn của dữ liệu Khi phát hiện một block có số bản sao vượt quá giới hạn cho phép, namenode sẽ điều chỉnh và tạo ra các bản sao mới Namenode có trách nhiệm cân bằng hệ thống bằng cách phân phối lại các blocks để tối ưu hóa hiệu suất và sử dụng tài nguyên Trong các thao tác thông thường, một datanode có thể chứa nhiều blocks hơn các datanode khác; namenode sẽ thực hiện cân bằng bằng cách di chuyển các blocks từ datanode có nhiều blocks sang datanode có ít blocks hơn.
Kiến trúc của GFS và HDFS có một điểm yếu dễ nhận thấy là master (NameNode) có thể trở thành Single Point Of Failure (SPOF), khiến toàn bộ hệ thống và hàng loạt job MapReduce bị dừng khi NameNode bị lỗi Tuy nhiên, nhờ đặc thù vận hành của hệ thống tệp, dữ liệu không đi qua NameNode mà chỉ có metadata được trao đổi giữa client và DataNode, nên NameNode hiếm khi bị quá tải dữ liệu và không phải là nguyên nhân chính gây hỏng hệ thống Trong thực tế, SPOF này không phải là hạn chế quá lớn; với việc theo dõi NameNode liên tục, thời gian gián đoạn thường ngắn trong các triển khai thương mại Thêm vào đó, Hadoop còn được thiết kế với một NameNode dự phòng (Secondary NameNode) giúp chuyển đổi nhanh chóng khi NameNode gặp sự cố.
DataNode có nhiệm vụ đọc và ghi các block của HDFS vào hệ thống file cục bộ
Trong hệ thống lưu trữ HDFS, mỗi tập tin được chia nhỏ thành các block và được lưu trữ trên nhiều DataNode NameNode chịu trách nhiệm quản lý metadata và chỉ ra cho client DataNode nào nắm giữ từng block, giúp quá trình đọc hoặc ghi file diễn ra hiệu quả Khi cần xử lý dữ liệu, client sẽ trực tiếp truy cập DataNode chứa block tương ứng để lấy dữ liệu Đồng thời, các DataNode liên hệ với nhau để duy trì sao lưu và tái tạo dữ liệu, đảm bảo tính sẵn sàng và độ tin cậy cao của hệ thống.
Trong hệ thống Hadoop Distributed File System (HDFS), NameNode và DataNode đảm nhận vai trò quản lý và lưu trữ dữ liệu Hình ảnh mô tả hai file tại /user/chuck/data1 và /user/james/data2, với file 1 gồm 3 block (1, 2, 3) và file 2 gồm 2 block (4, 5) Nội dung các block được lưu phân tán giữa các DataNode, mỗi block được sao lưu 3 bản sao nhằm đảm bảo khả năng phục hồi và liên tục đọc dữ liệu ngay cả khi một DataNode bị lỗi Ví dụ, block 1 có ba bản sao trên các DataNode khác nhau, cho phép vẫn đọc được dữ liệu từ các DataNode còn lại nếu một DataNode gặp sự cố.
Hình 1.6 Vai trò của NameNode và DataNode trong HDFS
DataNode liên tục báo cáo lên NameNode, và sau khi khởi tạo mỗi DataNode sẽ gửi cho NameNode danh sách các block đang lưu trữ Khi quá trình khởi tạo kết thúc, DataNode tiếp tục liên lạc với NameNode để cung cấp thông tin về sự thay đổi dữ liệu cục bộ và nhận các chỉ thị để tạo, di chuyển hoặc xóa các block trên đĩa cục bộ.
1.3.4 Nhiệm vụ của Secondary NameNode
Hình 1.7 Kiến trúc HDFS đầy đủ
Secondary NameNode (SNN) là một tiến trình nền (daemon) để hỗ trợ cho việc datanode daemon
Trong một cluster HDFS, NameNode quản lý metadata và điều phối hệ thống, trong khi Secondary NameNode (SNN) hoạt động như một nút phụ trên một máy chủ riêng và không chạy DataNode hoặc TaskTracker SNN có nhiệm vụ theo dõi trạng thái của HDFS, nhưng khác với NameNode ở chỗ nó không nhận và lưu các thay đổi thời gian thực; thay vào đó, nó thực thi quá trình checkpoint bằng cách liên hệ trực tiếp với NameNode để lưu lại trạng thái của HDFS sau một khoảng thời gian được người dùng cấu hình.
NameNode là điểm yếu của Hadoop cluster, và Standby NameNode (SNN) giúp giảm thiểu thời gian ngừng hoạt động và rủi ro mất dữ liệu nhờ cơ chế sao lưu và chuyển đổi trạng thái Tuy nhiên, khi một NameNode gặp sự cố, cần có sự can thiệp của con người để cấu hình lại cluster nhằm cho SNN đảm nhận vai trò NameNode và thực hiện quá trình failover một cách nhanh chóng.
THUẬT TOÁN XỬ LÝ DỮ LIỆU VĂN BẢN VỚI
2.1 Thiết kế thuật toán MapReduce cơ bản
MapReduce có sức mạnh chủ yếu đến từ sự đơn giản: để chuẩn bị dữ liệu đầu vào, lập trình viên chỉ cần cài đặt mapper và reducer, hoặc thêm partitioner và combiner Toàn bộ phần thực thi được quản lý bởi một Execution framework, hoạt động trên các clusters từ một đến hàng nghìn node và xử lý các tập dữ liệu từ gigabytes đến petabytes.
Điều này đồng nghĩa với việc mọi thuật toán mà người phát triển muốn triển khai đều phải được mô tả một cách nghiêm ngặt theo các thành phần đã được xác định trước; do đó không phải bất kỳ thuật toán nào cũng có thể chuyển sang mô hình lập trình MapReduce Mục tiêu của chương này là cung cấp, chủ yếu qua các ví dụ, cách thiết kế thuật toán cho MapReduce Đồng bộ hóa được xem là phần khó nhất của việc thiết kế thuật toán cho MapReduce và nói chung cho các thuật toán song song hoặc phân tán Trong các bài toán xử lý song song, các tiến trình ở các nút khác nhau phải đồng thời dồn lại với nhau để phân phối và tập hợp kết quả từ các phần do các nút xử lý Với một MapReduce Job, chỉ có một lần đồng bộ hóa trên toàn cụm – giai đoạn sort và shuffle – khi các cặp key-value trung gian được sao chép từ mapper sang reducer và gộp theo khóa Ngoài thời điểm đó, mapper và reducer chạy độc lập và không có cơ chế liên lạc trực tiếp với nhau Hơn nữa, người lập trình có rất ít sự kiểm soát trên nhiều khía cạnh của quá trình thực thi.
Chỉ định Node cho một Mapper hoặc Reducer cụ thể
Chỉ định thời gian bắt đầu và kết thúc của Mapper hoặc Reducer Chỉ định Mapper sẽ xử lý cặp key-value cụ thể
Chỉ định Reducer sẽ xử lý các cặp key-value trung gian
Tuy nhiên, lập trình viên cũng có một số kĩ thuật để điều khiển việc thực thi và quản lý dòng dữ liệu trong MapReduce Bao gồm:
Khả năng xây dựng các cấu trúc dữ liệu phức tạp dùng làm keys và values để lưu trữ và giao tiếp các kết quả từng phần
Khả năng thực thi các đoạn mã của người dùng lúc bắt đầu và kết thúc map và reduce task
Khả năng bảo toàn trạng thái giữa các mapper và reducer qua nhiều khóa đầu vào hoặc trung gian
Khả năng điều khiển thứ tự sắp xếp của các keys trung gian, do đó có thể biết được thứ tự các key mà reducer sẽ nhận
Khả năng điều khiển phân mảnh không gian khóa, do đó có thể biết được thứ tự tập khóa mà một reducer nào đó sẽ nhận
Thuật toán tính chỉ mục ngược để tìm kiếm dữ liệu văn bản
Việc tìm kiếm web là một thách thức lớn về dữ liệu tinh túy, đòi hỏi hệ thống xử lý để trả về thông tin qua một truy vấn ngắn gồm vài từ khóa Nhiệm vụ của hệ thống là nhận diện và lấy các đối tượng web liên quan, sau đó trình bày chúng một cách rõ ràng và hữu ích cho người dùng Kích thước của web rất lớn và việc tính toán chính xác là khó khăn, dù ta có thể ước lượng ở mức terabytes văn bản Trong thực tế, người dùng kỳ vọng kết quả nhanh từ công cụ tìm kiếm; thời gian trễ vượt quá vài trăm mili giây sẽ thách thức sự kiên nhẫn của người dùng Việc xử lý các yêu cầu tìm kiếm như vậy là một kỳ công về công nghệ, và cần chú ý đến lượng dữ liệu liên quan để tối ưu hóa hiệu suất và độ chính xác.
Hầu như mọi động cơ truy hồi cho tìm kiếm văn bản ngày nay đều dựa trên một cấu trúc dữ liệu được gọi là chỉ số đảo ngược, cho phép tra cứu nhanh một thuật ngữ và trả về danh sách các 'tài liệu' chứa thuật ngữ đó Trong ngữ cảnh retrieval, đối tượng được trả về được gọi chung là 'tài liệu', dù thực tế chúng có thể là các trang web, tệp PDF hoặc thậm chí mã nguồn.
Cho một truy vấn của người dùng, các hệ thống tìm kiếm sử dụng chỉ mục nghịch đảo để ghi nhận và truy cập các tài liệu chứa các thuật ngữ của truy vấn, đồng thời áp dụng các mô hình xếp hạng nhằm đánh giá mức độ phù hợp dựa trên nhiều yếu tố Quá trình này xem xét sự phù hợp của thuật ngữ với nội dung tài liệu, khoảng cách giữa các thuật ngữ trong văn bản (term proximity), và các đặc tính của các thuật ngữ trong tài liệu như tần suất xuất hiện, vị trí và ngữ cảnh Việc kết hợp giữa chỉ mục nghịch đảo và các mô hình xếp hạng giúp trả về các kết quả liên quan cao hơn và tối ưu hóa hiệu suất tìm kiếm cho người dùng.
Vấn đề tìm kiếm web được phân tích thành ba thành phần chính: thu thập nội dung (crawling), xây dựng chỉ số đảo (indexing) và phục vụ kết quả cho truy vấn (retrieval) Crawling và indexing có tính chất và yêu cầu tương tự nhau nhưng khác biệt cơ bản với retrieval, vì thu thập nội dung và tạo chỉ số đảo thường áp dụng cho các bài toán offline và có thể mở rộng mà không cần phản hồi thời gian thực Indexing thường được thực hiện theo dạng batch, cập nhật theo chu kỳ tùy thuộc thiết kế của bộ máy tìm kiếm: một số trang như tổ chức tin tức cập nhật rất nhanh và cần truy cập liên tục, trong khi các trang gov hay nguồn cố định ít thay đổi Tuy nhiên, với cả hai trường hợp, việc chậm vài phút để nội dung được tìm thấy có thể được chấp nhận, và với lượng thay đổi tương đối nhỏ, cập nhật chỉ số ở quy mô nhỏ và tần suất cao có thể là một cách cân bằng Đối với tìm kiếm trực tuyến, yêu cầu thời gian đáp ứng dưới giây cho người dùng cá nhân đồng thời phải xử lý lưu lượng truy vấn biến động theo thời gian và có thể xuất hiện các đợt tăng đột biến khi có sự kiện tin tức mới; trong khi đó tiêu thụ tài nguyên cho indexing có thể dự đoán được hơn.
Trước khi xây dựng chỉ số đảo ngược, ta cần có một bộ sưu tập dữ liệu làm nền để xây dựng các chỉ số Trong học thuật và nghiên cứu, các bộ sưu tập chuẩn cho văn bản tin tức (newswire text) thường được dùng làm khung tham chiếu; đối với những nhà nghiên cứu muốn khám phá tìm kiếm ở quy mô web, bộ sưu tập ClueWeb09 với khoảng một tỷ trang web bằng mười ngôn ngữ (tổng cộng 25 terabyte) được Đại học Carnegie Mellon thu thập từ đầu năm 2009 là một nguồn dữ liệu nổi bật Việc tiếp cận các bộ sưu tập chuẩn thường đơn giản bằng cách ký kết giấy phép dữ liệu từ các nhà phân phối và trả chi phí hợp lý Tuy nhiên, đối với tìm kiếm web trong thực tế, dữ liệu có thể không sẵn có và cần crawling, quá trình duyệt qua các trang web qua các siêu liên kết và lưu trữ các trang tải về cho xử lý tiếp theo Về mặt khái niệm, quá trình này rất trực quan: bắt đầu với một danh sách hạt giống và một hàng đợi các trang, crawler tải các trang trong hàng đợi, trích xuất liên kết để mở rộng hàng đợi, lưu trữ các trang cho xử lý sau và lặp đi lặp lại Trong thực tế, một crawler thô sơ có thể được viết bằng vài trăm dòng mã.
Tuy nhiên, hiệu quả dò tìm web sao cho tối ưu vẫn phức tạp hơn nhiều so với dự đoán, bởi thực tế có nhiều thách thức mà trình thu thập dữ liệu web thực tế (real-world crawlers) phải đối mặt Các vấn đề này bao gồm giới hạn tốc độ và tần suất truy cập để tránh bị chặn, các biện pháp chống bot của nhiều trang web, sự biến đổi liên tục của cấu trúc trang và định dạng dữ liệu, dữ liệu động được tải bằng JavaScript khiến việc trích xuất trở nên khó khăn, vấn đề về chất lượng và trùng lặp dữ liệu, cũng như yêu cầu tuân thủ pháp lý và nguyên tắc robots.txt có thể hạn chế quyền truy cập.
Để một crawler web hoạt động hiệu quả mà vẫn lịch sự với máy chủ, nó phải tuân thủ nghi thức và không gây quá tải cho máy chủ web Ví dụ phổ biến là chờ một khoảng thời gian cố định trước khi lặp lại yêu cầu tới cùng một máy chủ, nhằm tôn trọng giới hạn và duy trì thông lượng ổn định Để đạt được hiệu suất cao mà không làm phiền, crawler thường chạy song song nhiều luồng và duy trì nhiều kết nối TCP mở cùng lúc, có thể lên tới hàng trăm kết nối đồng thời.
Trong một trình thu thập dữ liệu có băng thông hữu hạn và nguồn lực hạn chế, nó phải ưu tiên thứ tự tải xuống các trang chưa được xem Quyết định này phải được thực hiện trực tuyến và trong một môi trường thù địch, nơi spammer tích cực tạo ra các trang đầy spam như trang trại liên kết và các bẫy nhện (link farms và spider traps).
“spider traps”) để lừa một trình thu thập vào nội dung overrepresenting từ một trang web cụ thể
Hầu hết các trình thu thập web thực tế được triển khai dưới dạng hệ thống phân tán chạy trên các cụm máy tính, thường phân bổ trên mạng lưới máy chủ Để tránh tải một trang nhiều lần và đảm bảo tính nhất quán của dữ liệu, hệ thống cần có cơ chế phối hợp và cân bằng tải ở cấp độ toàn cục Đồng thời, nó phải có khả năng chịu lỗi mạnh mẽ để đối phó với sự cố máy chủ, mất mạng và các loại lỗi khác, nhằm duy trì hoạt động ổn định và đáng tin cậy.
Nội dung trên các trang web liên tục thay đổi với tần suất khác nhau tùy thuộc vào đặc thù từng trang và loại nội dung Để tối ưu hóa SEO, một trình thu thập dữ liệu (web crawler) cần học cách thiết lập tần suất thu thập lại phù hợp Việc thu thập quá thường xuyên có thể lãng phí nguồn lực, trong khi thu thập quá ít sẽ làm cho nội dung cũ và thiếu cập nhật Vì vậy, việc xác định tần suất thu thập tối ưu giúp cân bằng giữa sự mới mẻ của nội dung và hiệu quả nguồn lực, đảm bảo dữ liệu được làm mới đúng thời điểm và cải thiện thứ hạng trên công cụ tìm kiếm.
Trang web hiện nay chứa nhiều nội dung trùng lặp hoặc gần trùng lặp, như nhiều bản sao của một bài viết hội nghị phổ biến, các mẫu trang web được truy cập thường xuyên (như Wikipedia) và nội dung tin tức được phát đi rộng rãi Vấn đề trở nên phức tạp vì các trang gần như trùng lặp nhưng không hoàn toàn, vẫn có sự khác biệt ở quảng cáo, thanh menu và các yếu tố khác Việc nhận diện gần bản sao và chọn mẫu nội dung chuẩn để chỉ mục trong quá trình thu thập dữ liệu là yếu tố then chốt cho chiến lược SEO.
Trang web đa ngôn ngữ không có đảm bảo rằng mỗi trang chỉ liên kết với nội dung cùng ngôn ngữ; ví dụ, một giáo sư ở Châu Á có thể duy trì trang web bằng ngôn ngữ địa phương nhưng liên kết đến các ấn phẩm bằng tiếng Anh Nhiều trang chứa văn bản ở nhiều ngôn ngữ khác nhau hoặc pha trộn giữa các ngôn ngữ Vì các kỹ thuật xử lý văn bản như tokenization và stemming khác nhau giữa các ngôn ngữ, việc xác định ngôn ngữ chi phối trên một trang là rất quan trọng để tối ưu hóa phân tích ngôn ngữ và SEO.
2.2.2 Thuật toán chỉ mục ngược
Trong hình thái cơ bản, chỉ mục ngược là danh sách postings cho từng thuật ngữ, mỗi postings liên kết đến các lần xuất hiện của thuật ngữ trong bộ sưu tập; danh sách này gồm các tài liệu chứa thuật ngữ, mỗi phần tử có id tài liệu và trọng số cho lần xuất hiện Trọng số đơn giản nhất là không có gì ngoài id tài liệu, vì trong retrieval boolean sự hiện diện của tài liệu cho thấy thuật ngữ có mặt; trọng số phổ biến nhất là tần số xuất hiện của thuật ngữ trong tài liệu (tf) Trọng số phức tạp hơn có thể bao gồm vị trí xuất hiện từng lần, hỗ trợ truy vấn ghép cụm từ và ghi nhận dựa trên độ gần của thuật ngữ, hoặc tính chất của thuật ngữ như xuất hiện trong tiêu đề để xếp hạng theo khái niệm, thậm chí kết quả xử lý ngôn ngữ bổ sung như nhận diện tên địa điểm để hỗ trợ tìm kiếm địa chỉ Trong bối cảnh web, thông tin văn bản từ anchor text – văn bản liên kết từ các trang khác – bổ sung đáng kể cho đại diện nội dung và thường được lưu trong chỉ mục Ví dụ, term 1 occurs in {d1, d5, d6, d11, }, term 2 occurs in {d11, d23, d59, d84, }, và term 3 occurs in {d1, d4, d11, d19, }.
Trong thực tế, mỗi tài liệu được nhận diện bằng một số nguyên duy nhất từ 1 đến n, với n là tổng số tài liệu Thông tin đăng thường được sắp xếp theo id tài liệu, dù có những cách sắp xếp khác Id không mang ý nghĩa ngữ nghĩa riêng, nhưng việc ánh xạ từ id số sang văn bản không nhất thiết là ngẫu nhiên; ví dụ, các trang cùng tên miền có thể được đánh số liên tục, hoặc ngược lại, những trang có chất lượng cao hơn (ví dụ dựa trên PageRank) có thể được gán số nhỏ hơn để xuất hiện ở đầu danh sách tin đăng Dù theo cách nào, cần có một cấu trúc dữ liệu phụ trợ để duy trì mapping từ id tài liệu sang một đại diện có ý nghĩa hơn cho các xử lý tiếp theo, chẳng hạn như một URL.
Hình 2.5 Minh họa đơn giản của một chỉ mục ngược
Trong hệ thống tìm kiếm, mỗi thuật ngữ liên kết với một danh sách các thông tin đăng, và mỗi niêm yết gồm một id tài liệu cùng với một trọng số được ký hiệu là p Chỉ số đảo ngược cho phép truy cập nhanh đến danh sách các id tài liệu chứa một từ khóa nhất định.