Mô hình lập trình MapReduce được dùng để xử lý dữ liệu lớn dựa trên lý thuyết của mô hình tính toán song song và mô hình xử lý dữ liệu phân tán trên những cụm máy tính.. Mô hình xử lý Ma
Trang 1ĐẠI HỌC ĐÀ NẴNG TRƯỜNG ĐẠI HỌC BÁCH KHOA
PHAODAVANH HONGSOUVANH
NGHIÊN CỨU ỨNG DỤNG MÔ HÌNH MAPREDUCE
ĐỂ GIẢI QUYẾT BÀI TOÁN ĐỒ THỊ
Chuyên ngành: Khoa học máy tính
Trang 2LỜI CAM ĐOAN
Tôi xin cam đoan:
Những nội dung trong luận văn này là do tôi thực hiện dưới sự hướng dẫn trực tiếp của PGS.TS Nguyễn Tấn Khôi
Mọi tham khảo dùng trong luận văn được trích dẫn rõ ràng và trung thực về tên tác giả, tên công trình, thời gian và địa điểm công bố
Mọi sao chép không hợp lệ, vi phạm quy chế đào tạo, tôi xin chịu hoàn toàn trách nhiệm
Tác giả luận văn
PHAODAVANH HONGSOUVANH
Trang 3LỜI CẢM ƠN
Trong quá trình thực hiện đề tài, tôi đã gặp rất nhiều khó khăn phát sinh mà nếu không có sự giúp đỡ, động viên của gia đình, các thầy cô giáo, bạn bè đồng nghiệp thì tôi khó có thể hoàn thành được luận văn này
Lời đầu tiên tôi xin gửi lời cảm ơn chân thành đến các quý thầy cô giáo, Khoa chuyên ngành Công nghệ thông tin, Trường Đại học Bách khoa đã tận tình giảng dạy, truyền đạt những kiến thức, kinh nghiệm quý báu trong suốt thời gian tôi theo học tại chương trình Các kiến thức, kinh nghiệm quý báu của các thầy cô giáo không chỉ giúp cá nhân tôi hoàn thiện
hệ thống kiến thức trong học tập mà còn giúp tôi ứng dụng các kiến thức đó trong công việc hiện tại
Đặc biệt, tôi xin gởi lời cảm ơn chân thành và sâu sắc nhất đến thầy giáo PGS.TS Nguyễn Tấn Khôi, người Thầy đã tận tình hướng dẫn và tạo điều kiện tốt nhất để tôi hoàn thành luận văn này
Tôi cũng xin được bày tỏ tình cảm với gia đình, đồng nghiệp, bạn bè đã tạo điều kiện
để tôi có thể dành thời gian cho khóa học Xin chân thành cảm ơn những người bạn lớp cao học K32, trong gần 2 năm qua đã luôn luôn động viên, khích lệ và hỗ trợ tôi trong quá trình học tập
Tuy có nhiều cố gắng, nhưng chắc chắn luận văn không tránh khỏi những thiếu sót nhất định Tôi rất mong nhận được ý kiến đóng góp quý báu của các thầy cô giáo và các bạn
để luận văn ngày càng được hoàn thiện hơn
Trân trọng cảm ơn!
Đà Nẵng, Ngày 16 Tháng 01 Năm 2018
Tác giả PHAODAVANH Hongsouvanh
Trang 4MỤC LỤC
LỜI CAM ĐOAN……… ……….……….i
LỜI CẢM ƠN ……… ……….……… …… ……ii
MỤC LỤC……….……….…… ………iii
DANH MỤC CÁC TỪ VIẾT TẮT……… ……… … ….………vi
DANH MỤC CÁC BẢNG……… ……….……….……….vii
DANH MỤC CÁC HÌNH……….…….….……… ……viii
LỜI CAM ĐOAN i
LỜI CẢM ƠN ii
DANH MỤC CÁC TỪ VIẾT TẮT vi
DANH MỤC CÁC BẢNG vii
DANH MỤC CÁC HÌNH ẢNH viii
MỞ ĐẦU 1
1 Tính cấp chọn đề tài 1
2 Mục tiêu và nhiệm vụ nghiên cứu 2
2.1 Mục tiêu 2
2.2 Nhiệm vụ 2
3 Đối tượng và phạm vi nghiên cứu 2
3.1 Đối tượng nghiên cứu của đề tài 2
3.2 Phạm vi nghiên cứu của đề tài 2
4 Phương pháp nghiên cứu 2
4.1 Nghiên cứu lý thuyết 2
4.2 Nghiên cứu thực nghiệm 2
5 Cấu trúc luận văn 3
6 Ý nghĩa khoa học và thực tiễn của đề tài 3
Trang 5Nền tảng tính toán với Hadoop 4 1.1.
Hệ thống tập tin phân tán Hadoop 4
CHƯƠNG 2 MÔ HÌNH XỬ LÝ PHÂN TÁN MAPREDUCE VÀ HADOOP 31
Xây dựng chương trình MapReduce Job 31 2.1
Các kiểu dữ liệu mà Hadoop hỗ trợ 31
2.4 Kết luận chương 37 CHƯƠNG 3 PHÂN TÍCH THIẾT KẾ BÀI TOÁN ĐỒ THỊ DỰA TRÊN MÔ HÌNH PHÂN TÁN MAPREDUCE 39
Ứng dụng MapReduce giải quyết bài toán cây khung nhỏ nhất 39 3.1
Giới thiệu bài toán 39
Trang 6Thuật toán Kruskal 41
3.1.4 Giải quyết bài toán Cây khung nhỏ nhất với MapReduce 45
3.1.5 Ứng dụng MapReduce giải quyết bài toán tìm đường đi ngắn nhất (Shortest 3.2 Path) 46 Phát biểu bài toán 47
3.2.1 Thuật toán Dijkstra 47
3.2.2 Thời gian thực hiện thuật toán 48
3.2.3 Giải quyết bài toán Đường đi ngắn nhất với MapReduce 49
3.2.4 Ứng dụng MapReduce giải bài toán luồng cực đại trong mạng 54
3.3 Mạng 54
3.3.1 Giới thiệu bài toán 55
3.3.2 Giới thiệu thuật toán Ford – Fulkerson 56
3.3.3 Giải quyết bài toán Luồng cực đại trên mạng với MapReduce 56
3.3.4 Thử nghiệm và đánh giá kết quả 57
3.4 Thử nghiệm hệ thống 57
3.4.1 Đánh giá kết quả thử nghiệm. 63
3.4.2 Kết luận chương 65
3.5 KẾT LUẬN VÀ HƯỚNG PHÁT TRIỂN 66
1 Kết luận 66
2 Hướng phát triển 66
DANH MỤC TÀI LIỆU THAM KHẢO 68
PHỤ LỤC 70
Trang 7HDFS Hadoop Distributed File System
NDFS Nutch Distributed File System
OSDI Operating System Design and Implementation
Trang 8DANH MỤC CÁC BẢNG
Bảng 2.1 Danh sách các kiểu dữ liệu của Hadoop 32
Bảng 2.2 Một số lớp thực hiện mapper được định nghĩa
Bảng 2.3 Danh sách các reducer cơ bản được triển khai
Trang 9DANH MỤC CÁC HÌNH ẢNH
Ký hiệu Tên hình ảnh Trang Hình 1.1 Cấu trúc các thành phần của Hadoop 6
Hình 1.3 NameNode và DataNode trong HDFS 13
Hình 1.19 Đồ thị G liên thông mạnh, đồ thị G’ liên thông yếu 20 Hình 2.1 Biểu đồ phân cấp của quá trình MapReduce 31 Hình 3.1 Cây khung nhỏ nhất của một đồ thị phẳng 39
Trang 10Hình 3.3 Kết quả đồ thị G sau khi dùng thuật toán Kruskal 45
Hình 3.6 Mạng với các khả năng thông qua (đỉnh 1 là đỉnh
phát, đỉnh 6 là đỉnh thu) và một luồng với giá trị 7 54 Hình 3.7 Giao diện chính của chương trình MST 57
Hình 3.10 Giao diện console trong khi chạy MapReduce 58 Hình 3.11 Kết quả sau khi chạy xong MapReduce 59
Hình 3.13 Giao diện của chương trình Dijkstra 60
Hình 3.16 Mô tả thời gian thực hiện thuật toán 63
Hình 3.17 Mô tả sự khác nhau về thời gian thực hiện khi đầu vào
khác nhau với hệ thống gồm một, hai và năm cụm 63
Hình 3.19 Mô tả sự khác nhau về thời gian thực hiện khi đầu vào
khác nhau với 1, 2 và 3 giai đoạn MapReduce 64
Trang 11MỞ ĐẦU
1 Tính cấp chọn đề tài
Hiện nay, với sự phát triển của công nghệ, lượng dữ liệu lưu trữ càng ngày càng lớn Điều này đặt ra nhiều thách thức Để xử lý lượng dữ liệu khổng lồ đó, rất nhiều công nghệ đã ra đời Trong đó phải kể đến công nghệ tính toán phân tán Ý tưởng chính của việc tính toán phân tán là chia bài toán thành những bài toán con và giải quyết trên các máy riêng biệt nhau được kết nối trong một cluster Chúng ta có thể thấy sự thành công của các công ty như Google, Facebook trong thời đại bùng nổ về công nghệ hiện nay Đằng sau sự thành công đó có sự đóng góp không nhỏ của một
mô hình lập trình được đưa ra bởi Google – đó là mô hình lập trình phân tán MapReduce
MapReduce là một mô hình lập trình phân tán, bao gồm hai giai đoạn chính là Map và Reduce Mô hình lập trình MapReduce được dùng để xử lý dữ liệu lớn dựa trên lý thuyết của mô hình tính toán song song và mô hình xử lý dữ liệu phân tán trên những cụm máy tính
Mô hình xử lý MapReduce cho phép Xử lý tốt bài toán với lượng dữ liệu lớn có các tác vụ phân tích và tính toán phức tạp không lường trước được; Có thể tiến hành chạy song song trên các máy phân tán một cách chính xác và hiệu quả Không cần quan tâm đến sự trao đổi dữ liệu giữa các cluster với nhau vì chúng hoạt động một cách độc lập, không cần theo dõi xử lý các tác vụ, xử lý lỗi; Có thể thực hiện mô hình MapReduce trên nhiều ngôn ngữ (Java, C/ C++, Python, Perl, Ruby) với các thư viện tương ứng
Tuy nhiên hiện nay có một số bài toán khi ứng dụng lý thuyết đồ thị để giải theo phương pháp truyền thống thường thì có thời gian tính toán lớn Việc giải bài toán này với tính chất tuần tự của giải thuật tuần tự khi số đỉnh của đồ thị lên đến hàng chục ngàn đỉnh sẽ gặp phải những vấn đề như thời gian thực hiện chương trình, tốc độ xử
lý, khả năng lưu trữ của bộ nhớ…
Với nhu cầu xử lý dữ liệu lớn, thời gian xử lý ngắn hơn, do đó hướng ứng dụng MapReduce để giải các bài toán đồ thị, tôi đề xuất chọn đề tài luận văn cao học:
“Nghiên cứu ứng dụng mô hình MapReduce để giải quyết bài toán đồ thị”
Trang 122 Mục tiêu và nhiệm vụ nghiên cứu
2.1Mục tiêu
Nghiên cứu ứng dụng mô hình xử lý phân tán MapReduce trên nền tảng hadoop
để giải quyết một số bài toán đồ thị có kích thước dữ liệu lớn
2.2 Nhiệm vụ
- Tìm hiểu về nền tảng tính toán phân tán với Hadoop
- Tìm hiểu về mô hình tính toán MapReduce
- Tìm hiểu về LTĐT
- Xây dựng giải thuật giải quyết một số bài toán đồ thị dựa theo mô hình MapReduce
3 Đối tượng và phạm vi nghiên cứu
3.1 Đối tượng nghiên cứu của đề tài
- Cấu trúc Framework, Hadoop, Kiến trúc HDFS
- Các bài toán đồ thị
- Tìm hiểu xây dựng các hàm Map, hàm Reduce
- Triển khai mô hình hệ thống
3.2 Phạm vi nghiên cứu của đề tài
- Mô hình xử lý phân tán MapReduce trên nền tảng hadoop
- Ứng dụng mô hình MapReduce để giải quyết một số bài toán đồ thị
4 Phương pháp nghiên cứu
4.1 Nghiên cứu lý thuyết
- Tìm hiểu các mô hình xử lý phân tán
- Tìm hiểu các bài toán đồ thị
- Tìm hiểu giải thuật xử lý phân tán
4.2 Nghiên cứu thực nghiệm
- Xây dựng sơ đồ, xây dựng thuật toán để giải một số bài toán đồ thị
- Lập trình ứng dụng bằng ngôn ngữ lập trình Java
- Xây dựng chương trình thử nghiệm
Trang 135 Cấu trúc luận văn
Ngoài phần mở đầu và phần kết luận, nội dung chính của luận văn được kiến trúc thành 3 chương
Chương 1 Cơ sở lý thuyết
Chương này trình bày những kiến thức cơ bản về nền tảng tính toán phân tán với Hadoop: giới thiệu Hadoop, các thành phần của Hadoop, Hadoop Distributed Dữ liệu System (HDFS) Cơ chế xử lý phân tán MapReduce và tổng quát về Đồ thị
Chương 2 Mô hình xử lý phân tán MapReduce và Hadoop
Chương này trình bày cách tạo một ứng dụng MapReduce cơ bản, các thư viện
mà Hadoop cung cấp để thao tác với hệ thống tập tin tự tạo ra khi lập trình
Chương 3 Xây dựng bài toán đồ thị trên nền tảng hệ thống MapReduce
Trong chương này chúng tôi sẽ trình bày một số thuật toán như Kruscal, thuật toán Ford-Fulkerson…trên nền tảng hệ thống MapReduce để giải quyết bài toán: tìm đường đi ngắn nhất từ một đỉnh đến tất cả các đỉnh còn lại trong một đồ thị, Cây khung nhỏ nhất của đồ thị, tìm luồng cực đại trên mạng…sau đó sẽ triển khai mô hình hệ thống và demo chương trình
6 Ý nghĩa khoa học và thực tiễn của đề tài
Luận văn này đã tìm hiểu và xây dựng được giải thuật giải bài toán đồ thị từ giải thuật tuần tự sang xử lý song song Ứng dụng xử lý dữ liệu lớn trên mô hình phân tán khi giải các bài toán về đồ thị
Trang 14CHƯƠNG 1: CƠ SỞ LÝ THUYẾT Chương này trình bày một cách tổng quan về nền tảng tính tán phân tán với Hadoop, giới thiệu kiến trúc HDFS cũng như cách đọc ghi dữ liệu trên HDFS Trình bày về mô hình tính toán MapReduce và những kiến thức về LTĐT cũng như các thuật toán cơ bản trên đồ thị
Nền tảng tính toán với Hadoop
1.1
Chúng ta đang sống trong thời đại bùng nổ dữ liệu số Mỗi ngày lượng dữ liệu lưu trữ không ngừng tăng lên và vượt ra khỏi khả năng xử lý của các hệ thống truyền thống Điều đó đòi hỏi phải xây dựng một hệ thống mới, có khả năng xử
lý được một lượng dữ liệu lớn, trong một khoảng thời gian chấp nhận được Xuất phát
từ nhu cầu đó, Hadoop đã ra đời dựa trên ý tưởng từ các bài báo về mô hình xử lý dữ liệu phân tán MapReduce của Google và Hệ thống tập tin của Google-Google Dữ liệu System (GFS)
Hiện nay, Hadoop đã được ứng dụng rộng rãi trên khắp thế giới Hadoop hoạt động trên ý tưởng của mô hình xử lý dữ liệu phân tán Mapreduce, cụ thể là hệ thống sẽ chia nhỏ nhiệm vụ lớn cho hàng loạt máy tính cùng nhau xử lý song song Với ý tưởng
đó, Hadoop có thể dễ dàng được triển khai trên các hệ thống máy tính có sẵn chứ không cần phải đầu tư những thiết bị phần cứng cao cấp, đắt tiền Đặc biệt, Hadoop là một dự án mã nguồn mở và hoàn toàn miễn phí Trong phần sau sẽ trình bày các khái niệm, cấu trúc Hadoop, kiến trúc HDFS…
Hệ thống tập tin phân tán Hadoop
1.1.1
Hadoop là một framework cho phép phát triển các ứng dụng phân tán, viết bằng Java Tuy nhiên nhờ cơ chế streaming, Hadoop cho phép phát triển các ứng dụng phân tán bằng cả java lẫn một số ngôn ngữ lập trình khác như C++, Python Hadoop cung cấp một phương tiện lưu trữ dữ liệu phân tán trên nhiều node, hỗ trợ tối ưu hóa lưu lượng mạng đó là Hadoop Distributed Dữ liệu System (HDFS) HDFS che giấu tất cả các thành phần phân tán, các nhà phát triển ứng dụng chỉ nhìn thấy HDFS như một hệ thống dữ liệu cục bộ bình thường và giúp các nhà phát triển ứng dụng phân tán tập trung tối đa vào phần logic của ứng dụng, bỏ qua được một số phần chi tiết kỹ thuật
Trang 15Hadoop được tạo ra bởi Doug Cutting, người sáng tạo ra Apache Lucene– bộ thư viện tạo chỉ mục tìm kiếm trên text được sử dụng rộng rãi Hadoop bắt nguồn từ Nutch, một ứng dụng search engine nguồn mở
Nutch được khởi xướng từ năm 2002 và một hệ thống search engine ra đời Tuy nhiên, các nhà kiến trúc sư của Nutch nhanh chóng nhận ra rằng Nutch sẽ không thể
mở rộng ra để có thể thực hiện vai trò searcher engine của mình trên tập dữ liệu hàng
tỷ trang web Nguyên nhân chính của giới hạn này là do Nutch lúc này chỉ chạy trên một máy đơn (stand alone) nên gặp phải các khuyết điểm:
- Khả năng lưu trữ bị giới hạn: giả sử mỗi trang web cần 10kb đĩa cứng để lưu, thì với hơn 100 triệu trang ta cần 1 Terabyte đĩa cứng, và với khối lượng hàng tỷ trang web có trên mạng thì cần tới hàng chục Petabyte để lưu trữ
- Tốc độ truy xuất chậm: với khối lượng dữ liệu lớn như vậy, việc truy xuất tuần tự
để phân tích dữ liệu và index trở nên rất chậm chạp, và thời gian để đáp ứng các câu truy vấn tìm kiếm (search query) là không hợp lý
Năm 2003, Google công bố kiến trúc của hệ thống dữ liệu phân tán GFS Năm
2004, họ bắt tay vào việc ứng dụng kiến trúc của GFS vào cài đặt một hệ thống dữ liệu phân tán nguồn mở có tên là Nutch Distributed Dữ liệu System (NDFS) Trong thời gian này Google lại công bố bài báo giới thiệu MapReduce Đầu năm 2005 các nhà phát triển Nutch đã xây dựng được phiên bản MapReduce trên Nutch, vào giữa năm
2005, tất cả các thuật toán chính của Nutch đều được cải tiến lại để chạy trên nền NDFS và MapReduce
NDFS và MapReduce trong Nutch đã nhanh chóng tìm được các ứng
dụng của mình bên ngoài lĩnh vực search engine, vào tháng hai năm 2006 Doug Cutting đã tách riêng NDFS và MapReduce ra để hình thành một dự án độc lập có tên Hadoop
Cùng thời gian này, Doug Cutting gia nhập vào Yahoo! Tại đây, ông được tạo một môi trường tuyệt vời để phát triển Hadoop, vào tháng 2 năm 2006 Yahoo đã công
bố sản phẩm search engine được xây dựng trên một Hadoop cluster có kích thước 10.000 nhân vi xử lý
Năm 2008, Hadoop đã phá kỷ lục thế giới về sắp xếp một Terabyte dữ liệu Chạy trên một cluster gồm 910 node, Hadoop đã sắp xếp một Terabyte dữ liệu trong
Trang 16vòng 209 giây, phá kỷ lục cũ là 297 giây Sau đó ít lâu, Google công bố ứng dụng chạy trên MapReduce của họ đã sắp xếp được một Terabyte dữ liệu trong 68 giây Vào tháng 5 năm 2009, một đội các nhà phát triển của Yahoo đã dùng Hadoop để sắp xếp một Terabyte dữ liệu trong vòng 62 giây
MapReduce
Một framework giúp phát triển các ứng dụng phân tán theo
mô hình MapReduce một cách dễ dàng và mạnh mẽ, ứng dụng phân tán MapReduce có thể chạy trên một cluster lớn với nhiều node
HDFS
Hệ thống dữ liệu phân tán, cung cấp khả năng lưu trữ dữ liệu khổng lồ và tính năng tối ưu hóa việc sử dụng băng thông giữa các node HDFS có thể sử dụng để chạy một cluster lớn với hàng chục ngàn node
HBase Một cơ sở dữ liệu phân tán, theo hướng cột
Trang 17(colunm-dữ liệu bên dưới và cung cấp khả năng tính toán song song dựa trên MapReduce
Hive Một kho dữ liệu phân tán Hive quản lý dữ liệu được lưu trữ
trên HDFS và cung cấp một ngôn ngữ truy vấn dựa trên SQL
Chukwa
Một hệ thống tập hợp và phân tích dữ liệu Chukwa chạy các collector (các chương trình tập hợp dữ liệu), các collector này lưu trữ dữ liệu trên HDFS và sử dụng MapReduce để phát sinh các báo cáo
Pig Ngôn ngữ luồng dữ liệu cấp cao và framework thực thi dùng
cho tính toán song song
Trong khuôn khổ luận văn này chỉ nghiên cứu phần quan trọng nhất của Hadoop
đó là MapReduce và xây dựng bài toán ứng dụng trên MapReduce
Nguyên tắc hoạt động của một Hadoop MapReduce
1.1.3
Hadoop chia đầu vào cho mỗi công việc MapReduce vào các mảnh có kích thước cố định gọi là các đầu vào split hoặc là các split Hadoop tạo ra một task map cho mỗi split, chạy mỗi nhiệm vụ map do người sử dụng định nghĩa cho mỗi bản ghi (record) trong split
Có rất nhiều các split, điều này có nghĩa là thời gian xử lý mỗi split nhỏ hơn so với thời gian xử lý toàn bộ đầu vào Vì vậy, nếu chúng ta xử lý các split một cách song song, thì quá trình xử lý sẽ cân bằng tải tốt hơn, nếu các split nhỏ, khi đó một chiếc máy tính nhanh có thể xử lý tương đương nhiều split trong quá trình thực hiện công việc hơn là một máy tính chậm Ngay cả khi các máy tính giống hệt nhau, việc xử lý không thành công hay các công việc khác đang chạy đồng thời làm cho cân bằng tải như mong muốn, và chất lượng của cân bằng tải tăng như là chia các splits thành các phần nhỏ hơn
Mặt khác, nếu chia tách quá nhỏ, sau đó chi phí cho việc quản lý các split và của tạo ra các map task bắt đầu chiếm rất nhiều tổng thời gian của quá trình xử lý công việc Đối với hầu hết công việc, kích thước split tốt nhất thường là kích thước của một block của HDFS, mặc định là 64MB, mặc dù nó có thể thay đổi được cho mỗi cluster (cho tất cả các dữ liệu mới được tạo ra) hoặc định rõ khi mỗi dữ liệu được tạo ra
Trang 18Hadoop làm tốt nhất các công việc của nó khi chạy các map task trên một node khi mà dữ liệu đầu vào cư trú ngay trong HDFS Các map task ghi đầu ra của chúng trên đĩa cụ bộ, không phải là vào HDFS
Các tiến trình nền tảng của Hadoop
1.1.4
NameNode
Là một trình nền quan trọng nhất của Hadoop Hadoop sử dụng một kiển trúc master/slave cho cả lưu trữ phân tán và xử lý phân tán Hệ thống lưu trữ phân tán được gọi là Hadoop Dữ liệu System hay HDFS NameNode là master của HDFS để chỉ đạo các trình nền DataNode slave để thực hiện các nhiệm vụ I/O mức thấp
DataNode
Mỗi máy slave trong cluster sẽ lưu trữ một trình nền DataNode để thực hiện các công việc nào đó của hệ thống dữ liệu phân tán - đọc và ghi các khối HDFS tới các dữ liệu thực tế trên hệ thống dữ liệu cục bộ (local dữ liệusytem) Khi đọc hay ghi một dữ liệu HDFS, dữ liệu đó được chia nhỏ thành các khối và NameNode sẽ nói cho các client nơi các trình nền DataNode sẽ nằm trong đó Client liên lạc trực tiếp với các trình nền DataNode để xử lý các dữ liệu cục bộ tương ứng với các block Hơn nữa, một DataNode có thể giao tiếp với các DataNode khác để nhân bản các khối dữ liệu của nó để dự phòng
Secondary NameNode
Các Secondary NameNode là một trình nền hỗ trợ giám sát trạng thái của các cụm HDFS Giống như NameNode, mỗi cụm có một Secondary NameNode, và nó thường trú trên một máy của mình Không có các trình nền DataNode hay TaskTracker chạy trên cùng một server Secondary NameNode khác với NameNode trong quá trình xử lý của nó không nhận hoặc ghi lại bất cứ thay đổi thời gian thực tới HDFS Thay vào đó giao tiếp với các NameNode bằng cách chụp những bức ảnh của siêu dữ liệu HDFS (HDFS metadata) tại những khoảng xác định bởi cấu hình của các cluster
Trang 19 JobTracker
Trình nền JobTracker là một liên lạc giữa ứng dụng và Hadoop Một khi mã nguồn được gửi tới các cụm (cluster), JobTracker sẽ quyết định kế hoạch thực hiện bằng cách xác định những tập tin nào sẽ xử lý, các nút được giao các nhiệm vụ khác nhau, và theo dõi tất cả các nhiệm vụ khi chúng đang chạy Nếu một nhiệm vụ (task) thất bại (fail), JobTracker sẽ tự động chạy lại nhiệm vụ đó, có thể trên một node khác, cho đến một giới hạn nào đó được định sẵn của việc thử lại này
Chỉ có một JobTracker trên một cụm Hadoop, thường chạy trên một máy chủ như là một nút master của cluster
TaskTracker
Như với các trình nền lưu trữ, các trình nền tính toán cũng phải tuân theo kiến trúc master/slave: JobTracker là giám sát tổng việc thực hiện chung của một công việc MapRecude và các taskTracker quản lý việc thực hiện các nhiệm vụ riêng trên mỗi node slave Mỗi TaskTracker chịu trách nhiệm thực hiện các task riêng mà các JobTracker giao cho
Một trong những trách nhiệm của các TaskTracker là liên tục liên lạc với JobTracker Nếu JobTracker không nhận được nhịp đập từ một TaskTracker nào đó trong thời gian đã quy định, nó sẽ cho rằng TaskTracker đã bị treo (cashed) và sẽ gửi lại nhiệm vụ tương ứng cho các nút khác trong cluster
Tổng quan của một Hadoop cluster
1.1.5
HDFS và MapReduce là hai thành phần chính của một Hadoop cluster Nhìn chung, kiến trúc của Hadoop là kiến trúc master-slave, và cả hai thành phần HDFS và MapReduce đều tuân theo kiến trúc master-slave này Kiến trúc của một Hadoop cluster như sau:
Trang 20Hình 1.2 Tổng quan một Hadoop cluster
Trên một hadoop cluster, có duy nhất một node chạy NameNode, một node chạy JobTracker (NameNode và JobTracker có thể nằm trên cùng một máy vật lý, tuy nhiên trên các cluster thật sự với hàng trăm, hàng nghìn node thì thường phải tách riêng NameNode và JobTracker ra các máy vật lý khác nhau Có nhiều node slave, mỗi node slave thường đóng 2 vài trò: DataNode và TaskTracker
NameNode và DataNode chịu trách nhiệm vận hành hệ thống tập tin phân tán HDFS với vai trò cụ thể được phân chia như sau:
NameNode: đóng vai trò là master của hệ thống HDFS, quản lý các meta-data của
hệ thống HDFS như dữ liệu system space, danh sách các tập tin trên hệ thống và các block id tương ứng của từng dữ liệu, quản lý danh sách slave và tình trạng hoạt động của các DataNode thông qua các hearbeat, đều hướng quá trình đọc/ghi dữ liệu từ client lên các DataNode
Trang 21DataNode: chứa các block dữ liệu thực sự của các dữ liệu trên HDFS, chịu trách nhiệm đáp ứng các yêu cầu đọc/ghi dữ liệu từ client, đáp ứng các yêu cầu tạo/xóa các block dữ liệu từ NameNode
JobTracker và TaskTracker chịu trách nhiệm duy trì bộ máy MapReduce, nhận và thực thi các MapReduce Job Vai trò cụ thể như sau:
JobTracker: tiếp nhận các yêu cầu thực thi các MapReduce job, phân chia job này thành các task và phân công cho các TaskTracker thực hiện, quản lý tình trạng thực hiện các task của TaskTracker, phân công lại nếu cần JobTracker cũng quản lý danh sách các node TaskTracker và tình trạng của node thông qua hearbeat
TaskTracker: nhận các task từ JobTracker và thực hiện task
Ngoài ra trên một Hadoop cluster còn có SecondaryNameNode
SecondaryNameNode: duy trì một bản sao của meta-data trên NameNote và bản sao này sẽ được dùng để phục hồi lại NameNode nếu bị hư hỏng
Hadoop Distributed File System (HDFS)
Các lỗi về phần cứng thường xuyên xảy ra Hệ thống HDFS sẽ chạy trên các cluster với hàng trăm hoặc thậm chí hàng ngàn node Các node được xây dựng nên từ các phần cứng thông thường, giá rẻ, tỷ lệ lỗi cao Chất lượng và số lượng của các thành phần phần cứng như vậy sẽ tất yếu dẫn đến tỷ lệ xảy ra lỗi trên cluster sẽ cao Các vấn
đề có thể điểm qua như lỗi ứng dụng, lỗi của hệ điều hành, lỗi đĩa cứng, bộ nhớ, lỗi của các thiết bị kết nối, lỗi mạng, và lỗi về nguồn điện…Vì thế khả năng phát hiện lỗi, chống chịu lỗi và tự động phục hồi phải được tích hợp vào trong hệ thống HDFS Kích thước dữ liệu sẽ lớn hơn so với các chuẩn truyền thống, các dữ liệu có kích thước hàng GB sẽ trở nên phổ biến Khi làm việc trên các tập dữ liệu với kích thước
Trang 22nhiều TB, ít khi nào người ta lại chọn việc quản lý hàng tỷ dữ liệu có kích thước hàng
KB, thậm chí nếu hệ thống có thể hỗ trợ Điều chúng ta muốn nói ở đây là việc phân chia tập dữ liệu thành một số lượng ít dữ liệu có kích thước lớn sẽ là tối ưu hơn Hai tác dụng to lớn của điều này có thể làm giảm thời gian truy xuất dữ liệu và đơn giản hóa việc quản lý các tập tin
Hầu hết các dữ liệu đều được thay đổi bằng cách bổ sung dữ liệu vào cuối dữ liệu hơn là ghi đè lên dữ liệu hiện có Việc ghi dữ liệu lên một vị trí ngẫu nhiên trong dữ liệu không hề tồn tại Một khi đã được tạo ra, các dữ liệu sẽ trở thành dữ liệu chỉ đọc (Read Only), và thường được đọc một cách tuần tự Có rất nhiều loại dữ liệu phù hợp với các đặc điểm trên Đó có thể là các kho dữ liệu lớn để các chương trình xử lý quét qua và phân tích dữ liệu Đó có thể là các dòng dữ liệu được tạo ra một các liên tục qua quá trình chạy các ứng dụng (ví dụ như dữ liệu log) Đó có thể là kết quả trung gian của một máy này và lại được dùng làm đầu vào xử lý trên một máy khác Và do vậy, việc bổ sung dữ liệu vào dữ liệu sẽ trở thành điểm chính để tối ưu hóa hiệu suất
1.1.6.2 Kiến trúc HDFS
Giống như các hệ thống dữ liệu khác, HDFS duy trì một cấu trúc cây phân cấp các
dữ liệu, thư mục mà các dữ liệu sẽ đóng vai trò là các node lá Trong HDFS, mỗi dữ liệu sẽ được chia ra làm một hay nhiều block và mỗi block này sẽ có một block ID để nhận diện Các block của cùng một dữ liệu (trừ block cuối cùng) sẽ có cùng kích thước gọi là block size của dữ liệu đó Mỗi block của dữ liệu sẽ được lưu trữ thành ra nhiều bản sao khác nhau vì mục đích an toàn dữ liệu
HDFS có một kiến trúc master/slave Trên một cluster chạy HDFS, có hai loại node
là Namenode và Datanode Một cluster có duy nhất một Namenode và có một hay nhiều Datanode
Namenode đóng vai trò là master, chịu trách nhiệm duy trì thông tin về cấu trúc phân cấp các dữ liệu, thư mục của hệ thống dữ liệu và các Metadata khác của hệ thống
dữ liệu Cụ thể, các Metadata mà Namenode lưu trữ gồm có :
Dữ liệu System Namespace : là hình ảnh cây thư mục của hệ thống dữ liệu tại một thời điểm nào đó Dữ liệu System Namespace thể hiện tất cả các dữ liệu, thư mục trên hệ thống dữ liệu và quan hệ giữa chúng
Trang 23Để ánh xạ từ tên dữ liệu ra thành danh sách và các block : với mỗi dữ liệu, ta có một danh sách có thứ tự các block của dữ liệu đó, mỗi Block đại diện bởi Block ID Nơi lưu trữ các block : các block đại diện một Block ID Với mỗi block ta có một danh sách các DataNode lưu trữ các bản sao của block đó
Các DataNode sẽ chịu trách nhiệm lưu trữ các block thật sự của từng dữ liệu của hệ thống dữ liệu phân tán lên hệ thống dữ liệu cục bộ của nó Mỗi một block sẽ được lưu trữ như là một dữ liệu riêng biệt trên hệ thống dữ liệu cục bộ của DataNode Kiến trúc của HDFS được thể hiện qua sơ đồ dưới đây :
Hình 1.3 NameNode và DataNode trong HDFS
Namenode sẽ chịu trách nhiệm điều phối các thao tác truy cập của client lên hệ thống HDFS Các Datanode là nơi lưu trữ các block của các dữ liệu trên HDFS, nên chúng sẽ là nơi trực tiếp đáp ứng các thao tác truy cập này Chẳng hạn như khi client của hệ thống muốn đọc một dữ liệu trên hệ thống HDFS, client này sẽ thực hiện một request (thông qua RPC) đến Namenode để lấy các metadata của dữ liệu cần đọc
Từ metadata này nó sẽ biết được danh sách các block của dữ liệu và vị trí của các Datanode chứa các bản sao của từng block Client sẽ truy cập vào các Datanode để thực hiện các yêu cầu đọc các block
Trang 24Mô hình xử lý phân tán MapReduce
MapReduce có thể hiểu là một phương thức thực thi để giúp các ứng dụng có thể
xử lý nhanh một lượng dữ liệu lớn Các dữ liệu này được đặt tại các máy tính phân tán Các máy tính này sẽ hoạt động song song độc lập với nhau Điều này làm rút ngắn thời gian xử lý toàn bộ dữ liệu
Một đặc điểm đáng chú ý của MapReduce là dữ liệu đầu vào có thể là dữ liệu cấu trúc (dữ liệu lưu trữ dạng bảng quan hệ hai chiều) hoặc dữ liệu không cấu trúc (dữ liệu dạng tập tin hệ thống)
Các máy tính lưu trữ các dữ liệu phân tán trong quá trình thực thi được gọi là các nút (nodes) của hệ thống Nếu các máy tính này cùng sử dụng chung trên một phần cứng thì chúng được gọi là một cụm (cluster) Nếu các máy này hoạt động riêng rẽ trên các phần cứng khác nhau thì chúng được gọi là một lưới
Cơ chế hoạt động của MapReduce
1.2.2
MapReduce hoạt động gồm hai quá trình thực hiện hai hàm Map và Reduce
Ý tưởng chính của MapReduce chính là thực hiện việc chia để trị
Trang 25(1): Thư viện MapReduce (MR) mà chương trình người dùng (User Program) sử dụng chia các tập tin đầu vào thành các phần nhỏ Dung lượng mỗi phần từ 16 megabytes đến 64 megabytes Và sau đó sao chép chương trình thành các tiến trình song song chạy trên các máy tính phân tán chứa dữ liệu
(2): Chương trình điều khiển Master sẽ gán mỗi phần dữ liệu cho một hàm Map và một hàm Reduce
(3)-(4): worker là phần được gán một hàm Map và Reduce để xử lý, nó sẽ đọc dữ liệu, phân tích cặp (key, value) ở đầu vào và phân tích thành các cặp trung gian khác được lưu tại vùng nhớ đệm
Trang 26(5): Định kỳ, các cặp dữ liệu trung gian sẽ được đẩy đến các worker tương ứng (do master điều khiển) để hàm reduce xử lý Các thuật toán sắp xếp, so sánh, phân vùng dữ liệu sẽ được sử dụng tại giai đoạn này Các tập dữ liệu trung gian có cùng key sẽ được sắp xếp cùng một nhóm
(6): Khi tất cả các tác vụ Map và Reduce đã hoàn tất thì sẽ cho ra kết quả cuối cùng của quy trình MapReduce
Với MapReduce, rất nhiều máy tính trung gian có thể sử dụng để xử lý dữ liệu
mà trước kia không thể
Như vậy toàn bộ quá trình MapReduce có thể hiểu như sau:
- Đọc dữ liệu đầu vào
- Thực hiện xử lý các phần dữ liệu vào (xử lý từng phần một)
- Đưa ra kết quả cuối cùng
Hình 1.5 Mô hình làm việc của một công việc MapReduce
Lấy ý tưởng từ lập trình hàm, mô hình MapReduce dựa trên hai hàm Map và Reduce Để xử lý khối dữ liệu bao gồm nhiều cặp (key, value), lập trình viên viết hai hàm Map và Reduce Hàm Map có đầu vào là một cặp (k1,v1) và đầu ra là một danh sách các cặp (k2, v2), như vậy hàm Map có thể viết một cách hình thức như sau:
Trang 27Hình 1.6 Hàm Map
Mô hình MapReduce áp dụng hàm Map (do người dùng viết) vào từng cặp (key, value) trong khối dữ liệu vào, chạy rất nhiều phiên bản của hàm Map song song với nhau trên các node của cluster Sau khi giai đoạn này kết thúc, kết quả thu được là một tập hợp rất nhiều cặp (key, value) gọi là các cặp (key, value) trung gian Các cặp này lại được nhóm một lần nữa theo khóa, như vậy các cặp (key, value) trung gian có cùng khóa sẽ nằm cùng một nhóm trung gian
Sau đó, hàm Reduce (cũng do người dùng viết) sẽ được áp dụng vào từng nhóm trung gian để tạo thành kết quả cuối cùng tùy theo yêu cầu đặt ra Một cách hình thức, hàm Reduce có thể được mô tả như sau:
Hình 1.7 Hàm Reduce
Trong đó k2 là khóa chung của nhóm trung gian, list(v2) là tập các giá trị trong nhóm và list(v3) là một danh sách các giá trị trả về của hàm Reduce thuộc kiểu dữ liệu v3 Do hàm Reduce được áp dụng vào nhiều nhóm trung gian độc lập, chúng lại một lần nữa có thể được chạy song song với nhau
Trang 28Hadoop MapReduce
1.2.4
Hadoop đã giữ nguyên cơ chế của MapReduce của Google để cài đặt thành bộ máy thực thi MapReduce Đây là một framework cho phép dễ dàng phát triển và triển khai các ứng dụng MapReduce
Cơ chế hoạt động mapreduce:
- Phân nhỏ dữ liệu đầu vào
Hình1.8 Phân nhỏ dữ liệu đầu vào
- Thông qua thư viện MapReduce ứng với từng ngôn ngữ, chương trình có nhiệm
vụ phân mảnh tệp dữ liệu đầu vào Dữ liệu vào được chia thành các phần nhỏ Sao chép chương trình:
Chương trình MapReduce làm nhiệm vụ sao chép chương trình chạy thành các tiến trình song song lên các máy tính phân tán Các máy gồm có Master và Worker Trong đó máy Master làm nhiệm vụ điều phối sự hoạt động của quá trình thực hiện MapReduce trên các máy Worker Các máy Worker làm nhiệm vụ thực hiện quá trình
Map và Reduce với dữ liệu mà nó nhận được
Disk
Disk Localtion Save Map
Worker Master
Trang 29Thực hiện hàm Map:
Máy master sẽ phân phối các tác vụ Map và Reduce vào các worker đang rảnh rỗi Các tác vụ này được Master phân phối cho các máy dựa trên vị trí của dữ liệu liên quan trong hệ thống Máy Worker khi nhận được tác vụ Map sẽ đọc dữ liệu mà nó nhận được từ phân vùng dữ liệu đã gán cho nó và thực hiện hàm Map Kết quả đầu ra
là các cặp <key, value> trung gian Các cặp này được lưu tạm trên bộ nhớ đệm của các máy
Hình 1.10 Thực hiện hàm Map
Sau khi thực hiện xong công việc Map Các máy Worker làm nhiệm vụ chia các giá trị trung gian thành R vùng (tương ứng với R tác vụ Reduce) lưu xuống đĩa và thông báo kết quả, vị trí lưu cho máy Master
Hình 1.11 Thực thi tác vụ Reduce
Master sẽ gán các giá trị trung gian và vị trí của các cặp dữ liệu đó cho các
máy thực hiện công việc Reduce Các máy Reduce làm nhiệm vụ xử lý các key, thực hiện hàm Reduce và đưa kết quả cuối
Thông báo kết quả:
Master sẽ kích hoạt thông báo cho chương trình người dùng quá trình MapReduce
đã hoàn tất Kết quả đầu ra được lưu trữ trên R tập tin
1
2
R
Trang 30Để thể hiện các chức năng ở trên trong việc viết chương trình chúng ta cần xây dựng 3 hàm:
- MapReduce không thay thế chiến lược database và dataWarehouse
- MapReduce không thiết kế cho xử lý sự kiện phức tạp theo thời gian thực
- MapReduce không tốt cho xử lý giao dịch (truy cập ngẫu nhiên)
- MapReduce không tốt cho bài toán tuần tự
- MapReduce không tốt khi xử lý nhiều tệp nhỏ
- MapReduce không tốt cho tính toán hiệu năng cao với ít dữ liệu
Tóm lại:
- MapReduce giấu sự phức tạp của mô hình lập trình cho làm việc phân tán và khả năng chịu lỗi
- Nguyên lý thiết kế:
+ Mở rộng khả năng, giảm lo ngại về phần cứng
+ Rẻ hơn, cấu hình phần cứng thấp, giá lập trình và quản trị thấp
- Điện toán đám mây sẽ giúp sử dụng Hadoop dễ dàng hơn
Lý thuyết đồ thị
1.3
Trong nhiều tình huống, do thói quen người ta thường vẽ lên giấy những điểm biểu thị cho các cá thể, các khu dân cư và nối các điểm đó với nhau bằng những nét hoặc những mũi tên tượng trưng cho mối liên hệ nào đó Các sơ đồ này được dùng với các tên gọi khác nhau Chính Denes Konig (1884-1944) là người đầu tiên đề nghị gọi các sơ đồ trên là “đồ thị”, đồng thời đề nghị nghiên cứu một cách có hệ thống các tính chất đó
Để áp dụng vào trong các lĩnh vực khác nhau, LTĐT phải được hình thức hóa đến mức cao, tuy nhiên những khái niệm cơ bản được định nghĩa một cách trừu tượng nhưng vẫn còn giữ được mối quan hệ nhất định với những “đồ thị thực tế”
mà ta rất dễ nhận ra khi sơ đồ đã vạch xong Phần sau trình bày một số khái niệm
Trang 31cũng như các thuật toán cơ bản về LTĐT
Giới thiệu
1.3.1
Đồ thị là một cấu trúc rời rạc gồm các đỉnh và các cạnh nối các đỉnh đó Được
mô tả hình thức G = (V, E) Trong đó, V gọi là tập các đỉnh (Vertices) và E gọi là tập các cạnh (Edges) Có thể coi E là tập các cặp (u, v) với u và v là hai đỉnh của V Một
Đồ thị có hướng: G được gọi là đồ thị có hướng nếu các cạnh trong E là có định hướng, có thể có cạnh nối từ đỉnh u tới đỉnh v nhưng chưa chắc đã có cạnh nối từ đỉnh v tới đỉnh u Hay nói cách khác, tập E gồm các cặp (u, v) có tính thứ tự: (u, v) ≠ (v, u) Trong đồ thị có hướng, các cạnh được gọi là các cung Đồ thị vô hướng cũng
có thể coi là đồ thị có hướng nếu như ta coi cạnh nối hai đỉnh u, v bất kỳ tương đương với hai cung (u, v) và (v, u)
Trang 32Hình 1.13 Phân loại đồ thị
Cạnh liên thuộc, đỉnh kề, bậc:
Đối với đồ thị vô hướng G = (V, E) Xét một cạnh e E, nếu e = (u, v) thì ta nói hai đỉnh u và v là kề nhau (adjacent) và cạnh e này liên thuộc (incident) với đỉnh u và đỉnh v
Với một đỉnh v trong đồ thị, ta định nghĩa bậc (degree) của v, ký hiệu deg(v) là số cạnh liên thuộc với v Dễ thấy rằng trên đơn đồ thị thì số cạnh liên thuộc với v cũng là
số đỉnh kề với v
Đối với đồ thị có hướng G = (V, E) Xét một cung e E, nếu e = (u, v) thì ta nói u nối tới v và v nối từ u, cung e là đi ra khỏi đỉnh u và đi vào đỉnh v Đỉnh u khi đó được gọi là đỉnh đầu, đỉnh v được gọi là đỉnh cuối của cung e
Với mỗi đỉnh v trong đồ thị có hướng, ta định nghĩa: Bán bậc ra của v ký hiệu deg+(v) là số cung đi ra khỏi nó; bán bậc vào ký hiệu deg-(v) là số cung đi vào đỉnh
đó
Đường đi: Một đường đi độ dài k từ đỉnh u đến đỉnh v là dãy (u = x0, x1, ,xk = v) thoả mãn (xi, xi+1) E (là một cạnh của đồ thị) với i: (0 ≤ i ≤ k) Đỉnh u gọi là đỉnh xuất phát, v gọi là đỉnh kết thúc của đường đi Đường đi không có cạnh nào đi qua hơn một lần gọi là đường đi đơn
Chu trình: Đường đi có đỉnh xuất phát trùng với đỉnh kết thúc gọi là chu trình
Cách biểu diễn đồ thị
1.3.3
Khi lập trình giải các bài toán được mô hình hóa bằng đồ thị, việc đầu tiên cần làm là tìm cấu trúc dữ liệu để biểu diễn đồ thị sao cho việc giải quyết bài toán được thuận tiện nhất
Trang 33Có rất nhiều phương pháp biểu diễn đồ thị, mỗi phương pháp biểu diễn sẽ được chỉ rõ hơn trong từng thuật toán cụ thể
1.3.3.1 Biểu diễn đồ thị bằng ma trận kề
Với G = (V, E) là một đơn đồ thị có hướng trong đó V =n, ta có thể đánh số các đỉnh từ 1 tới n và đồng nhất mỗi đỉnh với số thứ tự của nó Bằng cách đánh số như vậy, đồ thị G có thể biểu diễn bằng ma trận vuông
A=a }
Trong đó: ai j = 1 nếu (i, j) E, ai j = 0 nếu (i, j) E Với i, giá trị của các phần tử trên đường chéo chính ma trận A: {aii} có thể đặt tùy theo mục đích cụ thể, chẳng hạn đặt bằng 0
Ma trận A xây dựng như vậy được gọi là ma trận kề (adjacency matrix) của đồ thị G Việc biểu diễn đồ thị vô hướng được quy về việc biểu diễn phiên bản có hướng tương ứng: thay mỗi cạnh (i, j) bởi hai cung ngược hướng nhau: (i, j) và (j, i)
Trong trường hợp G là đơn đồ thị, ta có thể biểu diễn ma trận kề A tương ứng là các phần tử logic
Hình 1.14 Biểu diễn đồ thị bằng ma trận kề
Ma trận kề có nhiều ưu điểm như đơn giản trực quan dễ cài đặt trên máy Muốn kiểm tra xem hai đỉnh (u, v) của đồ thị có kề nhau hay không, ta chỉ việc kiểm tra bằng một phép so sánh: auv ≠ 0
Tuy nhiên ma trận kề cũng có những nhược điểm như bất kể số cạnh của đồ thị
Trang 34là nhiều hay ít, ma trận kề luôn luôn đòi hỏi n2 ô nhớ để lưu các phần tử ma trận, điều
đó gây lãng phí bộ nhớ Một số bài toán yêu cầu thao tác liệt kê tất cả các đỉnh v kề với một đỉnh u cho trước Trên ma trận kề việc này được thực hiện bằng cách xét tất cả các đỉnh v và kiểm tra điều kiện auv ≠ 0 Như vậy, ngay cả khi đỉnh u là đỉnh cô lập (không kề với đỉnh nào) hoặc đỉnh treo (chỉ kề với một đỉnh) ta cũng phải buộc xét tất
cả các đỉnh v và kiểm tra giá trị tương ứng auv
1.3.3.2 Biểu diễn đồ thị bằng danh sách cạnh
Trong trường hợp đồ thị có n đỉnh, m cạnh, ta có thể biểu diễn đồ thị dưới dạng danh sách cạnh, trong cách biểu diễn này, liệt kê các cạnh của đồ thị trong một danh sách, mỗi phần tử của danh sách là một cặp (u, v) tương ứng với một cạnh của đồ thị Danh sách được lưu trong bộ nhớ dưới dạng mảng hoặc danh sách móc nối
Ví dụ với đồ thị dưới đây:
Hình 1.15 Biểu diễn đồ thị bằng danh sách cạnh
Cài đặt trên mảng
(1,3) (2,4) (3,5) (4,1) (5,2)
Cài đặt trên danh sách móc nối
Biểu diễn đồ thị bằng danh sách cạnh có ưu điểm trong trường hợp đồ thị thưa (có số cạnh tương đối nhỏ), cách biểu diễn bằng danh sách cạnh sẽ tiết kiệm được không gian lưu trữ Trong một số trường hợp, ta phải xét tất cả các cạnh của đồ thị thì
1 2 3 4 5
Trang 35Bên cạnh đó biểu diễn đồ thị bằng danh sách cạnh cũng có những nhược điểm
là khi ta cần duyệt tất cả các đỉnh kề với đỉnh v nào đó của đồ thị, thì chẳng có cách nào khác là phải duyệt tất cả các cạnh, lọc ra những cạnh có chứa đỉnh v và xét đỉnh còn lại Việc kiểm tra hai đỉnh u, v có kề nhau hay không cũng bắt buộc phải duyệt danh sách cạnh, điều đó khá tốn thời gian trong trường hợp đồ thị dày (nhiều cạnh)
1.3.3.3 Biểu diễn đồ thị bằng danh sách kề
Để khắc phục nhược điểm của phương pháp biểu diễn bằng ma trận kề và danh sách cạnh, người ta đề xuất phương pháp biểu diễn đồ thị bằng danh sách kề (adjacency list) Trong cách biểu diễn này, với mỗi đỉnh v của đồ thị, ta cho tương ứng với một danh sách các đỉnh kề với v
Với đồ thị có hướng G = (V, E) V gồm n đỉnh và E gồm m cung Có hai cách cài đặt danh sách kề phổ biến
+ Forward Star: Với mỗi đỉnh u, lưu trữ một danh sách adj[u] chứa các đỉnh nối từ u: adj[u]=v: (u, v) E
+ Reverse Star: Với mỗi đỉnh v, lưu trữ một danh sách adj[v] chứa các đỉnh nối tới v: adj[v]=u: (u, v) E
Biểu diễn danh sách kề bằng mảng:
Dùng một mảng adj[1 m] chứa các đỉnh, mảng được chia làm n đoạn, đoạn thứ u trong mảng lưu danh sách các đỉnh kề với đỉnh u
Để biết một đoạn nằm từ chỉ số nào đến chỉ số nào, ta có một mảng head[1 n+1] đánh dấu vị trí phân đoạn: head[u] sẽ bằng chỉ số đứng liền trước đoạn thứ u, quy ước head[n+1]=m
Khi đó các phần tử trong đoạn: adj[head[u]+1…head[u+1]] là các đỉnh kề với đỉnh u
Khi sử dụng danh sách kề để biểu diễn đồ thị vô hướng, ta quy nó về đồ thị có hướng và số cung m được nhân đôi, ta xây dựng 2 mảng adj và head, hình 1.18
1 2 3 4 5 6 7 8 9 10 11 12 13 14
adj 2 3 1 3 4 5 1 2 5 2 5 2 3 4
1 2 3 4 5 6
Trang 36head 0 2 6 9 11 14
Hình 1.16 Biểu diễn đồ thị bằng danh sách kề
Biểu diễn bằng danh sách kề có một số ưu điểm như khi duyệt tất cả các đỉnh kề với một đỉnh v cho trước là hết sức dễ dàng Bên cạnh đó việc duyệt tất cả các cạnh cũng đơn giản vì một cạnh thực ra là nối một đỉnh với một đỉnh khác kề nó
Tuy nhiên biểu diễn bằng danh sách kề cũng có những nhược điểm, danh sách kề yếu hơn ma trận kề ở việc kiểm tra (u,v) có phải là cạnh hay không, bởi trong cách biểu diễn này ta sẽ phải duyệt toàn bộ danh sách kề của u hay danh sách kề của v
Duyệt đồ thị
1.3.4
1.3.4.1 Phát biểu bài toán
Cho đồ thị G = (V, E) và s, t là hai đỉnh của đồ thị Yêu cầu: Hãy chỉ ra một đường đi từ s đến t (nếu có)
Hình 1.17 Đồ thị vô hướng, đồ thị có hướng Trên cả hai đồ thị, (1, 2, 3, 4) là đường đi đơn độ dài 3 từ đỉnh 1 tới đỉnh 4 Bởi (1, 2) (2, 3) và (3, 4) đều là các cạnh (hay cung)
Làm sao để duyệt tất cả các đỉnh có thể đến được từ một đỉnh xuất phát nào đó? Vấn đề này đưa về một bài toán liệt kê mà yêu cầu của nó là không được bỏ sót hay lặp lại bất kỳ đỉnh nào Vì vậy, cần phải xây dựng những thuật toán cho phép duyệt một cách hệ thống các đỉnh, những thuật toán như vậy gọi là những thuật toán tìm kiếm trên đồ thị Trong LTĐT, người ta quan tâm đến hai thuật toán cơ bản nhất: thuật toán tìm kiếm theo chiều sâu và thuật toán tìm kiếm theo chiều rộng
1.3.4.2 Thuật toán tìm kiếm theo chiều sâu DFS
Trang 37Tư tưởng của thuật toán có thể trình bày như sau: Bắt đầu từ s, mọi đỉnh u kề với s tất nhiên sẽ đến được từ s Với mỗi đỉnh u đó, những đỉnh v kề với u cũng đến được từ s Ý tưởng đó gợi ý cho ta viết một thủ tục đệ quy DFS(u) mô tả việc duyệt
từ đỉnh u bằng cách thông báo thăm đỉnh u và tiếp tục quá trình duyệt DFS(v) với v
là một đỉnh chưa thăm kề với u Để quá trình duyệt không lặp lại bất kì đỉnh nào, ta dùng kỹ thuật đánh dấu, khi thăm một đỉnh, ta sẽ đánh dấu đỉnh đó lại để các bước duyệt đệ quy kế tiếp không thăm lại đỉnh đó nữa
Vấn đề còn lại: Để in ra được đường đi từ đỉnh xuất phát s, trong quá trình duyệt DFS(u), trước khi gọi đệ quy DFS(v) với v là một đỉnh kề với u mà chưa đánh dấu, ta lưu lại “vết” đường đi từ u tới v bằng cách đặt trace[v]:= u, tức
là trace[v] là đỉnh liền trước v trong đường đi từ s tới v Khi quá trình tìm kiếm theo chiều sâu kết thúc, đường đi từ s tới f sẽ là: t Trace[t] …. Trace[u1] Trace[s]
Trace[v]:= u; {Truy vết đường đi}
DFS(v); {Gọi đệ quy duyệt bắt đầu với v}
Trang 38- Nếu t chưa bị đánh dấu thì kết luận: Không có
đường từ st;
- Nếu t đã bị đánh dấu thì dựa vào Trace tìm đường
đi từ st;
End;
1.3.4.3 Thuật toán tìm kiếm theo chiều rộng BFS
Ý tưởng của phương pháp cài đặt này là "lập lịch" duyệt các đỉnh Khi thăm một đỉnh ta sẽ lên lịch thăm tất cả các đỉnh kề nó sao cho thứ tự duyệt là ưu tiên chiều rộng (đỉnh nào gần s hơn sẽ được duyệt trước) Ví dụ: Bắt đầu, ta thăm đỉnh s Việc thăm đỉnh s sẽ phát sinh thứ tự duyệt những đỉnh (x1, x2, …, xp) kề với đỉnh s (những đỉnh gần s nhất) Khi thăm đỉnh x1 sẽ lại phát sinh yêu cầu cần duyệt những đỉnh (u1,
u2, , uq) kề với x1 Nhưng rõ ràng các đỉnh này "xa" s hơn những đỉnh x nên chúng chỉ được duyệt đến khi tất cả những đỉnh x đã duyệt xong Tức là thứ tự duyệt đỉnh sau khi đã thăm x1 sẽ là: (x2, x3, …,xp, u1, u2,…, uq)
Bước 1: Khởi tạo
- Các đỉnh đều ở trạng thái chưa đánh dấu, ngoại trừ đỉnh xuất phát s là đã đánh dấu
- Một hàng đợi (Queue), ban đầu chỉ có một phần tử là s Hàng đợi dùng để chứa các đỉnh sẽ được duyệt theo thứ tự ưu tiên chiều rộng
Bước 2: Lặp cho tới khi hàng đợi rỗng:
Trang 39- Xét tất cả những đỉnh v kề với u mà chưa được đánh dấu, với mỗi đỉnh v đó:
Đánh dấu v
Ghi nhận vết đường đi từ u đến v (Trace[v] =u)
Đưa v vào hàng đợi
Bước 3: Truy vết tìm đường đi
1.3.4.4 Độ phức tạp tính toán của thuật toán DFS và BFS
Quá trình tìm kiếm trên đồ thị bắt đầu từ một đỉnh có thể thăm tất cả các đỉnh còn lại, khi đó cách biểu diễn đồ thị có ảnh hưởng lớn tới chi phí về thời gian thực hiện giải thuật
Trong trường hợp ta biểu diễn đồ thị bằng danh sách kề, cả hai thuật toán BFS và DFS đều có độ phức tạp tính toán là O(n + m) = O(max(n, m)) Đây là cách cài đặt tốt nhất Nếu ta biểu diễn đồ thị bằng ma trận kề thì độ phức tạp tính toán trong trường hợp này là O(n+n2) =O(n2) Nếu ta biểu diễn đồ thị bằng danh sách cạnh, thao tác duyệt những đỉnh kề với đỉnh u sẽ dẫn tới việc phải duyệt qua toàn bộ danh sách cạnh, đây là cài đặt tồi nhất, nó có độ phức tạp tính toán là O(n.m)
Tính liên thông của đồ thị
1.3.5
1.3.5.1 Tính liên thông trên đồ thị vô hướng
Đồ thị vô hướng G = (V, E) được gọi là liên thông (connected) nếu giữa mọi cặp đỉnh của G luôn tồn tại đường đi Đồ thị chỉ gồm một đỉnh duy nhất cũng được coi là đồ thị liên thông
Cho đồ thị vô hướng G = (V, E) và U là một tập khác rỗng của tập đỉnh V Ta nói U
là một thành phần liên thông (connected component) của G nếu:
+ Đồ thị G hạn chế trên tập U: GU = (U, EU) là đồ thị liên thông
+ Không tồn tại một tập W chứa U mà đồ thị G hạn chế trên W là liên thông (tính tối đại của U)
Một đồ thị liên thông chỉ có một thành phần liên thông là chính nó Một đồ thị không liên thông sẽ có nhiều hơn một thành phần liên thông
Đôi khi, việc xóa đi một đỉnh và tất cả các cạnh liên thuộc với nó sẽ tạo ra một
đồ thị con mới có nhiều thành phần liên thông hơn đồ thị ban đầu, các đỉnh như thế gọi là đỉnh khớp
Hoàn toàn tương tự, những cạnh mà khi ta bỏ nó đi sẽ tạo ra một đồ thị có
Trang 40nhiều thành phần liên thông hơn so với đồ thị ban đầu được gọi là cạnh cắt (cut edges) hay cầu (bridges)
1.3.5.2 Tính liên thông trên đồ thị có hướng
Đồ thị G Đồ thị G’
Hình 1.19 Đồ thị G là liên thông mạnh nhưng đồ thị G’ là liên thông yếu
Cho đồ thị G có hướng G = (V, E), G gọi là liên thông mạnh (strongly connected) nếu luôn tồn tại đường đi (theo các cung định hướng) giữa hai đỉnh bất
kỳ của đồ thị, G’ gọi là liên thông yếu (weakly connected) nếu phiên bản vô hướng của nó là đồ thị liên thông
ra khỏi đồ thị và lặp lại, thuật toán sẽ kết thúc khi tập đỉnh của đồ thị trở thành rỗng Việc loại bỏ đỉnh của đồ thị có thể thực hiện bằng cơ chế đánh dấu những đỉnh bị loại
Kết luận chương
1.4
Chương này trình bày tổng quan về nền tảng tính toán phân tán với Hadoop, cơ chế
xử lý phân tán MapReduce cũng như những kiến thức cơ bản về đồ thị Các vấn đề trọng tâm này sẽ được thực hiện trong luận văn Từ những vấn đề này sẽ đi sâu tìm hiểu trọng tâm của luận văn và thực hiện ở các chương tiếp theo