Liên quan đến CouchDB của tôi câu hỏi .
Bất cứ ai cũng có thể giải thích MapReduce theo cách mà một người tê có thể hiểu được?
Liên quan đến CouchDB của tôi câu hỏi .
Bất cứ ai cũng có thể giải thích MapReduce theo cách mà một người tê có thể hiểu được?
Câu trả lời:
Đi tất cả các cách cơ bản cho Bản đồ và Giảm.
Bản đồ là một chức năng "biến đổi" các mục trong một loại danh sách thành một loại mục khác và đưa chúng trở lại trong cùng một loại danh sách.
giả sử tôi có một danh sách các số: [1,2,3] và tôi muốn nhân đôi mọi số, trong trường hợp này, hàm "nhân đôi mọi số" là hàm x = x * 2. Và không cần ánh xạ, tôi có thể viết một vòng lặp đơn giản, nói
A = [1, 2, 3]
foreach (item in A) A[item] = A[item] * 2
và tôi có A = [2, 4, 6] nhưng thay vì viết các vòng lặp, nếu tôi có chức năng bản đồ, tôi có thể viết
A = [1, 2, 3].Map(x => x * 2)
x => x * 2 là một hàm được thực thi đối với các phần tử trong [1,2,3]. Điều gì xảy ra là chương trình lấy từng mục, thực hiện (x => x * 2) đối với nó bằng cách làm x bằng với từng mục và tạo danh sách kết quả.
1 : 1 => 1 * 2 : 2
2 : 2 => 2 * 2 : 4
3 : 3 => 3 * 2 : 6
vì vậy sau khi thực hiện chức năng bản đồ với (x => x * 2) bạn sẽ có [2, 4, 6].
Giảm là một hàm "thu thập" các mục trong danh sách và thực hiện một số tính toán trên tất cả chúng, do đó giảm chúng thành một giá trị duy nhất.
Tìm tổng hoặc tìm trung bình là tất cả các trường hợp của hàm giảm. Chẳng hạn như nếu bạn có một danh sách các số, giả sử [7, 8, 9] và bạn muốn chúng được tóm tắt, bạn sẽ viết một vòng lặp như thế này
A = [7, 8, 9]
sum = 0
foreach (item in A) sum = sum + A[item]
Nhưng, nếu bạn có quyền truy cập vào hàm giảm, bạn có thể viết nó như thế này
A = [7, 8, 9]
sum = A.reduce( 0, (x, y) => x + y )
Bây giờ có một chút khó hiểu tại sao có 2 đối số (0 và hàm có x và y) được truyền. Để hàm giảm có ích, nó phải có thể lấy 2 mục, tính toán một cái gì đó và "giảm" 2 mục đó xuống chỉ một giá trị, do đó chương trình có thể giảm mỗi cặp cho đến khi chúng ta có một giá trị duy nhất.
việc thực hiện sẽ như sau:
result = 0
7 : result = result + 7 = 0 + 7 = 7
8 : result = result + 8 = 7 + 8 = 15
9 : result = result + 9 = 15 + 9 = 24
Nhưng bạn không muốn bắt đầu với số không mọi lúc, vì vậy đối số đầu tiên là ở đó để cho phép bạn chỉ định một giá trị hạt giống cụ thể là giá trị trong result =
dòng đầu tiên .
nói rằng bạn muốn tổng hợp 2 danh sách, nó có thể trông như thế này:
A = [7, 8, 9]
B = [1, 2, 3]
sum = 0
sum = A.reduce( sum, (x, y) => x + y )
sum = B.reduce( sum, (x, y) => x + y )
hoặc một phiên bản bạn có thể tìm thấy nhiều hơn trong thế giới thực:
A = [7, 8, 9]
B = [1, 2, 3]
sum_func = (x, y) => x + y
sum = A.reduce( B.reduce( 0, sum_func ), sum_func )
Đây là một điều tốt trong phần mềm DB bởi vì, với sự hỗ trợ của Map \ Giảm, bạn có thể làm việc với cơ sở dữ liệu mà không cần biết dữ liệu được lưu trữ trong DB để sử dụng nó như thế nào, đó là công cụ DB dùng để làm gì.
Bạn chỉ cần có thể "nói" cho động cơ những gì bạn muốn bằng cách cung cấp cho chúng chức năng Bản đồ hoặc Giảm và sau đó công cụ DB có thể tìm đường đi xung quanh dữ liệu, áp dụng chức năng của bạn và đưa ra kết quả cho bạn muốn tất cả mà không cần bạn biết làm thế nào nó lặp lại trên tất cả các hồ sơ.
Có các chỉ mục và khóa và tham gia và chế độ xem và rất nhiều nội dung mà một cơ sở dữ liệu có thể chứa, do đó, bằng cách bảo vệ bạn khỏi cách dữ liệu được lưu trữ thực sự, mã của bạn được viết và bảo trì dễ dàng hơn.
Tương tự như vậy đối với lập trình song song, nếu bạn chỉ xác định những gì bạn muốn làm với dữ liệu thay vì thực sự thực thi mã vòng lặp, thì cơ sở hạ tầng bên dưới có thể "song song" và thực hiện chức năng của bạn trong một vòng lặp song song đồng thời cho bạn.
Average()
được cho là đóng băng trên đầu trang Sum()
. Nhưng tôi đã nói về nó để minh họa tại sao hàm được gọi là "Giảm" ... Hàm trung bình là thứ lấy danh sách các số và giảm nó thành một số duy nhất (là mức trung bình).
MapReduce là một phương pháp để xử lý song song một lượng lớn dữ liệu mà không yêu cầu nhà phát triển phải viết bất kỳ mã nào khác ngoài trình ánh xạ và giảm các hàm.
Hàm bản đồ lấy dữ liệu và đưa ra kết quả, được giữ trong một rào chắn. Hàm này có thể chạy song song với một số lượng lớn tác vụ bản đồ tương tự . Bộ dữ liệu sau đó có thể được giảm giá trị vô hướng.
Vì vậy, nếu bạn nghĩ về nó như một câu lệnh SQL
SELECT SUM(salary)
FROM employees
WHERE salary > 1000
GROUP by deptname
Chúng ta có thể sử dụng bản đồ để có được tập hợp nhân viên của mình với mức lương> 1000 mà bản đồ phát ra rào cản thành các nhóm kích thước nhóm.
Giảm sẽ tổng hợp từng nhóm. Cung cấp cho bạn bộ kết quả của bạn.
chỉ nhận được điều này từ các ghi chú nghiên cứu trường đại học của tôi trên giấy google
Bước 2 là Bản đồ. Bước 3 là Giảm.
Ví dụ,
Lý do MapReduce được phân chia giữa Map và Giảm là vì các phần khác nhau có thể dễ dàng được thực hiện song song. (Đặc biệt nếu Giảm có các tính chất toán học nhất định.)
Để biết mô tả phức tạp nhưng hay về MapReduce, hãy xem: Mô hình lập trình MapReduce của Google - Xem lại (PDF) .
MAP và REDUCE là các chức năng Lisp cũ từ thời con người giết chết những con khủng long cuối cùng.
Hãy tưởng tượng bạn có một danh sách các thành phố với thông tin về tên, số người sống ở đó và quy mô của thành phố:
(defparameter *cities*
'((a :people 100000 :size 200)
(b :people 200000 :size 300)
(c :people 150000 :size 210)))
Bây giờ bạn có thể muốn tìm thành phố có mật độ dân số cao nhất.
Đầu tiên chúng tôi tạo một danh sách tên thành phố và mật độ dân số bằng MAP:
(map 'list
(lambda (city)
(list (first city)
(/ (getf (rest city) :people)
(getf (rest city) :size))))
*cities*)
=> ((A 500) (B 2000/3) (C 5000/7))
Sử dụng GIẢM GIÁ bây giờ chúng ta có thể tìm thấy thành phố có mật độ dân số lớn nhất.
(reduce (lambda (a b)
(if (> (second a) (second b))
a
b))
'((A 500) (B 2000/3) (C 5000/7)))
=> (C 5000/7)
Kết hợp cả hai phần, chúng tôi nhận được mã sau đây:
(reduce (lambda (a b)
(if (> (second a) (second b))
a
b))
(map 'list
(lambda (city)
(list (first city)
(/ (getf (rest city) :people)
(getf (rest city) :size))))
*cities*))
Hãy giới thiệu các chức năng:
(defun density (city)
(list (first city)
(/ (getf (rest city) :people)
(getf (rest city) :size))))
(defun max-density (a b)
(if (> (second a) (second b))
a
b))
Sau đó, chúng tôi có thể viết mã GIẢM GIÁ MAP của chúng tôi là:
(reduce 'max-density
(map 'list 'density *cities*))
=> (C 5000/7)
Nó gọi MAP
và REDUCE
(đánh giá là từ trong ra ngoài), vì vậy nó được gọi là giảm bản đồ .
max-density
so sánh các yếu tố thứ hai của các đối số thông qua, phải không? Xin lỗi vì chỉnh sửa ngớ ngẩn.
Hãy lấy ví dụ từ bài báo của Google . Mục tiêu của MapReduce là có thể sử dụng hiệu quả một khối lượng các đơn vị xử lý làm việc tương đương với một số loại thuật toán. Ví dụ như sau: bạn muốn trích xuất tất cả các từ và số lượng của chúng trong một bộ tài liệu.
Thực hiện điển hình:
for each document
for each word in the document
get the counter associated to the word for the document
increment that counter
end for
end for
Triển khai MapReduce:
Map phase (input: document key, document)
for each word in the document
emit an event with the word as the key and the value "1"
end for
Reduce phase (input: key (a word), an iterator going through the emitted values)
for each value in the iterator
sum up the value in a counter
end for
Xung quanh đó, bạn sẽ có một chương trình chính sẽ phân vùng bộ tài liệu theo "phần tách" sẽ được xử lý song song cho giai đoạn Bản đồ. Các giá trị phát ra được ghi bởi công nhân trong một bộ đệm dành riêng cho công nhân. Chương trình tổng thể sau đó ủy quyền cho các công nhân khác thực hiện giai đoạn Giảm ngay khi được thông báo rằng bộ đệm đã sẵn sàng để được xử lý.
Mọi đầu ra của worker (là Map hoặc là worker worker) trên thực tế là một tệp được lưu trữ trên hệ thống tệp phân tán (GFS cho Google) hoặc trong cơ sở dữ liệu phân tán cho CouchDB.
Giới thiệu thực sự dễ dàng , nhanh chóng và "dành cho người giả" về MapReduce có sẵn tại: http://www.marcolotz.com/?p=67
Đăng một số nội dung của nó:
Trước hết, tại sao MapReduce ban đầu được tạo ra?
Về cơ bản Google cần một giải pháp để thực hiện các công việc tính toán lớn dễ dàng song song hóa, cho phép dữ liệu được phân phối trong một số máy được kết nối qua mạng. Bên cạnh đó, nó phải xử lý lỗi máy một cách minh bạch và quản lý các vấn đề cân bằng tải.
MapReduce thế mạnh thực sự là gì?
Người ta có thể nói rằng phép thuật MapReduce dựa trên ứng dụng chức năng Map và Giảm. Tôi phải thú nhận bạn đời, rằng tôi rất không đồng ý. Tính năng chính khiến MapReduce trở nên phổ biến là khả năng song song và phân phối tự động, kết hợp với giao diện đơn giản. Các yếu tố này được tóm tắt với việc xử lý lỗi trong suốt đối với hầu hết các lỗi khiến khung này trở nên phổ biến.
Một chút sâu hơn trên giấy:
MapReduce ban đầu được đề cập trong một bài báo của Google (Dean & Ghemawat, 2004 - liên kết tại đây) như là một giải pháp để thực hiện tính toán trong Dữ liệu lớn bằng cách sử dụng cách tiếp cận song song và cụm máy tính hàng hóa. Trái ngược với Hadoop, được viết bằng Java, khung của Google được viết bằng C ++. Tài liệu mô tả cách một khung công tác song song sẽ hoạt động bằng cách sử dụng các hàm Map và Giảm từ lập trình chức năng qua các tập dữ liệu lớn.
Trong giải pháp này sẽ có hai bước chính - được gọi là Bản đồ và Thu nhỏ -, với một bước tùy chọn giữa bước đầu tiên và lần thứ hai - được gọi là Kết hợp. Bước Map sẽ chạy trước, thực hiện tính toán trong cặp giá trị khóa đầu vào và tạo ra giá trị khóa đầu ra mới. Người ta phải nhớ rằng định dạng của các cặp khóa-giá trị đầu vào không nhất thiết phải khớp với cặp định dạng đầu ra. Bước Giảm sẽ tập hợp tất cả các giá trị của cùng một khóa, thực hiện các tính toán khác trên nó. Kết quả là bước cuối cùng này sẽ xuất ra các cặp khóa-giá trị. Một trong những ứng dụng tầm thường nhất của MapReduce là triển khai đếm từ.
Mã giả cho ứng dụng này, được đưa ra dưới đây:
map(String key, String value):
// key: document name
// value: document contents
for each word w in value:
EmitIntermediate(w, “1”);
reduce(String key, Iterator values):
// key: a word
// values: a list of counts
int result = 0;
for each v in values:
result += ParseInt(v);
Emit(AsString(result));
Như người ta có thể nhận thấy, bản đồ đọc tất cả các từ trong một bản ghi (trong trường hợp này bản ghi có thể là một dòng) và phát ra từ đó dưới dạng một khóa và số 1 là một giá trị. Sau đó, giảm sẽ nhóm tất cả các giá trị của cùng một khóa. Hãy cho một ví dụ: hãy tưởng tượng rằng từ 'ngôi nhà' xuất hiện ba lần trong hồ sơ. Đầu vào của bộ giảm tốc sẽ là [house, [1,1,1]]. Trong bộ giảm tốc, nó sẽ tổng hợp tất cả các giá trị cho nhà khóa và cung cấp dưới dạng đầu ra giá trị khóa sau: [house, [3]].
Đây là hình ảnh về diện mạo của nó trong khung MapReduce:
Như một vài ví dụ cổ điển khác về các ứng dụng MapReduce, người ta có thể nói:
• Đếm tần suất truy cập URL
• Đồ thị liên kết ngược
• Grep phân phối
• Vector hạn trên mỗi máy chủ
Để tránh lưu lượng truy cập mạng quá nhiều, bài viết mô tả cách khung nên cố gắng duy trì địa phương dữ liệu. Điều này có nghĩa là nó phải luôn cố gắng đảm bảo rằng một máy đang chạy các công việc Map có dữ liệu trong bộ nhớ / bộ nhớ cục bộ của nó, tránh để lấy nó từ mạng. Nhằm mục đích giảm mạng thông qua việc đặt một trình ánh xạ, bước kết hợp tùy chọn, được mô tả trước đây, được sử dụng. Bộ kết hợp thực hiện các tính toán trên đầu ra của các bộ ánh xạ trong một máy nhất định trước khi gửi nó tới Bộ giảm tốc - có thể ở trong một máy khác.
Tài liệu cũng mô tả cách các yếu tố của khung nên hoạt động trong trường hợp có lỗi. Những yếu tố này, trong bài báo, được gọi là worker và master. Chúng sẽ được chia thành các yếu tố cụ thể hơn trong các triển khai nguồn mở. Vì Google chỉ mô tả cách tiếp cận trong bài báo và không phát hành phần mềm độc quyền của mình, nhiều khung công tác nguồn mở đã được tạo để triển khai mô hình. Như các ví dụ người ta có thể nói Hadoop hoặc tính năng MapReduce giới hạn trong MongoDB.
Thời gian chạy cần quan tâm đến các chi tiết lập trình viên không phải là chuyên gia, như phân vùng dữ liệu đầu vào, lên lịch thực hiện chương trình trên toàn bộ máy lớn, xử lý các lỗi máy (dĩ nhiên là một cách minh bạch) và quản lý giao tiếp giữa các máy . Người dùng có kinh nghiệm có thể điều chỉnh các tham số này, như cách dữ liệu đầu vào sẽ được phân vùng giữa các công nhân.
Ý chính:
• Dung sai lỗi:Nó phải chịu đựng sự cố máy một cách duyên dáng. Để thực hiện điều này, chủ nhân ping định kỳ các công nhân. Nếu chủ không nhận được phản hồi từ một công nhân nhất định trong một khoảng thời gian xác định, chủ sẽ xác định công việc là thất bại ở công nhân đó. Trong trường hợp này, tất cả các nhiệm vụ bản đồ được hoàn thành bởi công nhân bị lỗi sẽ bị ném đi và được giao cho một công nhân có sẵn khác. Điều tương tự xảy ra nếu công nhân vẫn đang xử lý bản đồ hoặc tác vụ giảm. Lưu ý rằng nếu công nhân đã hoàn thành phần rút gọn của nó, tất cả các tính toán đã hoàn thành vào thời điểm nó không thành công và không cần phải thiết lập lại. Là một điểm chính của thất bại, nếu chủ thất bại, tất cả các công việc đều thất bại. Vì lý do này, người ta có thể xác định các điểm kiểm tra định kỳ cho chủ, để lưu cấu trúc dữ liệu của nó.
• Địa phương: Để tránh lưu lượng mạng, khung cố gắng đảm bảo rằng tất cả dữ liệu đầu vào có sẵn cục bộ cho các máy sẽ thực hiện tính toán trên chúng. Trong mô tả ban đầu, nó sử dụng Hệ thống tệp của Google (GFS) với hệ số sao chép được đặt thành 3 và kích thước khối là 64 MB. Điều này có nghĩa là cùng một khối 64 MB (tạo một tệp trong hệ thống tệp) sẽ có các bản sao giống hệt nhau trong ba máy khác nhau. Bậc thầy biết các khối ở đâu và cố gắng sắp xếp các công việc bản đồ trong máy đó. Nếu thất bại, chủ sẽ cố gắng phân bổ một máy gần một bản sao của dữ liệu đầu vào nhiệm vụ (tức là một máy công nhân trong cùng một giá của máy dữ liệu).
• Độ chi tiết của nhiệm vụ: Giả sử rằng mỗi pha bản đồ được chia thành các mảnh M và mỗi pha Giảm được chia thành các mảnh R, lý tưởng sẽ là M và R lớn hơn rất nhiều so với số lượng máy công nhân. Điều này là do thực tế là một công nhân thực hiện nhiều nhiệm vụ khác nhau cải thiện cân bằng tải động. Bên cạnh đó, nó làm tăng tốc độ phục hồi trong trường hợp công nhân thất bại (vì nhiều tác vụ bản đồ mà nó đã hoàn thành có thể được trải ra trên tất cả các máy khác).
• Nhiệm vụ sao lưu: Đôi khi, một nhân viên Map hoặc Reducer có thể cư xử chậm hơn rất nhiều so với những người khác trong cụm. Điều này có thể giữ tổng thời gian xử lý và làm cho nó bằng với thời gian xử lý của máy chậm đơn lẻ đó. Bài viết gốc mô tả một giải pháp thay thế gọi là Nhiệm vụ sao lưu, được chủ nhân lên lịch khi hoạt động MapReduce gần hoàn thành. Đây là những nhiệm vụ được lên kế hoạch bởi Master của các nhiệm vụ đang thực hiện. Do đó, hoạt động MapReduce hoàn thành khi bản chính hoặc bản sao lưu kết thúc.
• Bộ đếm: Đôi khi người ta có thể muốn đếm các sự kiện xảy ra. Vì lý do này, tính nơi tạo ra. Các giá trị truy cập trong mỗi công nhân được định kỳ truyền đến chủ. Sau đó, tổng thể tổng hợp (Yep. Có vẻ như bộ tổng hợp Pregel đến từ nơi này) các giá trị truy cập của bản đồ thành công và giảm tác vụ và trả chúng về mã người dùng khi hoạt động MapReduce hoàn tất. Ngoài ra còn có một giá trị truy cập hiện tại có sẵn trong trạng thái chính, vì vậy một người theo dõi quá trình có thể theo dõi cách nó hoạt động.
Chà, tôi đoán với tất cả các khái niệm trên, Hadoop sẽ là một miếng bánh cho bạn. Nếu bạn có bất kỳ câu hỏi nào về bài viết MapReduce ban đầu hoặc bất cứ điều gì liên quan, xin vui lòng cho tôi biết.
Tôi không muốn nghe có vẻ nghiêm túc, nhưng điều này đã giúp tôi rất nhiều, và nó khá đơn giản:
cat input | map | reduce > output
Nếu bạn đã quen thuộc với Python, sau đây là lời giải thích đơn giản nhất có thể về MapReduce:
In [2]: data = [1, 2, 3, 4, 5, 6]
In [3]: mapped_result = map(lambda x: x*2, data)
In [4]: mapped_result
Out[4]: [2, 4, 6, 8, 10, 12]
In [10]: final_result = reduce(lambda x, y: x+y, mapped_result)
In [11]: final_result
Out[11]: 42
Xem cách từng phân đoạn dữ liệu thô được xử lý riêng lẻ, trong trường hợp này, nhân với 2 (phần bản đồ của MapReduce). Dựa trên mapped_result
, chúng tôi đã kết luận rằng kết quả sẽ là 42
(phần giảm của MapReduce).
Một kết luận quan trọng từ ví dụ này là thực tế là mỗi đoạn xử lý không phụ thuộc vào đoạn khác. Ví dụ, nếu thread_1
bản đồ [1, 2, 3]
và thread_2
bản đồ [4, 5, 6]
, kết quả cuối cùng của cả hai luồng vẫn sẽ [2, 4, 6, 8, 10, 12]
nhưng chúng tôi đã giảm một nửa thời gian xử lý cho việc này. Điều tương tự cũng có thể nói đối với hoạt động giảm và là bản chất của cách MapReduce hoạt động trong tính toán song song.