Phát triển Java 2.0: Phân tích dữ liệu lớn bằng
MapReduce của Hadoop
Khi Google tung ra tính năng tìm kiếm hình nh vào năm 2001, Google đã có 250 triệu hình ảnh
được lập chỉ mục. Gần một thập kỷ sau đó, gã khổng ltìm kiếm này đã lập chỉ mục hơn 10 t
hình ảnh. Ba mươi lăm ginội dung được tải lên YouTube mi phút. Tính trung nh, Twitter
được cho là xử lý 55 triệu mẫu tin ngắn mi ngày. Đầu năm nay, 600 triệu truy cập hàng ngày đã
đăng nhập vào tính năng tìm kiếm của Twitter. Đó là những gì chúng tôi mun đưa ra khi i v
dữ liệu ln.
Về loạt bài này
Viễn cảnh phát triển Java đã thay đổi hoàn toàn kể từ khi công nghệ Java xuất hiện ln đầu tiên.
Nhờ hoàn thiện các framework mở và các cơ s hạ tầng triển khai cho thuê đáng tin cậy, bây gi
chúng ta có thể tích hợp, thử nghiệm, chạy và bảo trì các ứng dụng Java một cách nhanh chóng
không tốn kém. Trong loạt bài này, Andrew Glover khám phá một loạt các công nghvà các
công cụ làm cơ sở phát triển Java kiểu mi này thành hiện thực.
Đã có lúc dữ liệu trên một quy mô lớn như vậy chỉ được sử dụng trong các tập đoàn lớn, các
trường đại học và chính ph— những nơi có khả năng mua siêu máy tính đắt tiền và thuê nhân
viên để duy trì. Ngày nay, với việc hạ thấp chi p u trữ và sức mạnh xử lý trở nên thông dụng,
các công ty nhhơn và một số cá nhân, đã bắt đầu lưu trữ và khai p dliệu tương tự nvy,
thúc đẩy mt làn sóng về đổi mi ứng dụng.
Một trong những công nghệ tạo khả năng của cuộc cách mạng dữ liệu lớn là MapReduce, mt
mô hình lập trình và công cụ được Google phát triển để xử các tập hợp dữ liệu phân tán quy
mô ln. Trong bài này, tôi gii thiệu công cụ MapReduce nguồn mở của Apache, đó là Hadoop,
mà mt s người đã gọi là ứng dụng sát thcủa điện toán đám mây.
Giới thiệu Hadoop
Về cơ bản, Hadoop framework (khung công tác Hadoop) của Apache là một cơ chế dùng để
phân tích các tập dữ liệu rất ln mà không cn đặt trong một kho dữ liệu. Hadoop trừu tượng hóa
công cụ phân tích dữ liệu to lớn của MapReduce, làm nó trở nên dễ tiếp cận hơn với các nhà phát
triển. Hadoop có khả năng mở rộng vô s các node và có thể xử lý tất cả hot động và phi hợp
liên quan đến việc phân loại dữ liệu.
Hadoop vi các tính năng và tùy chnh phong phú đã trthành mt framework có ích và mnh
mẽ đến không ngờ. Yahoo! và vô scác tổ chức khác đã tìm thấy ở nó một cơ chế hiệu quả để
phân tích các núi dliệu bit, byte. Hadoop cũng khá dễ thực hiện trên một node đơn; tất cả
những gì bn cần là dliệu nào đó để phân tích và biết rõ vmã Java, bao gồm mt phương tiện
lập trình tng quát (generics). Hadoop cũng làm việc với Ruby, Python và C++.
Thông tin thêm về MapReduce
Nếu bạn là độc giả của loạt bài này, t thể bạn đã tìm hiểu ch hoạt động của MapReduce.
Trong bài "Tìm hiểu dch vREST với CouchDB và RESTClient của Groovy" (REST up with
CouchDB and Groovy's RESTClient), tôi đã trình bày cách CouchDB sử dụng MapReduce cho
các khung nhìn, sau đó tôi lại sử dụng nó trong bài "MongoDB: Một kho dữ liệu NoSQL vi các
di chuyển RDBMS (tt cả đều đúng)) (MongoDB: A NoSQL datastore with (all the right)
RDBMS moves)," như là cơ chế dùng để xử các tài liệu MongoDB.
Là một framework dựa trên các khái niệm dùng để x c tập hợp dữ liệu khổng lồ,
MapReduce được tối ưu hóa rất cao để giải quyết vn đề phân tán bằng cách sử dụng một s
lượng lớn các máy tính. Framework này bao gồm hai hàm, như tên gọi của nó cho thấy. Hàm
map (ánh xạ) được thiết kế để nhận một đầu vào dữ liệu lớn và phân chia nó thành từng mnh
nhỏ hơn, rồichuyn chúng đến các quá trình khác có thlàm điều gì đó với nó. Hàm reduce
(giảm) phân loại các câu trả lời riêng lẻ do hàm map thu thập và đưa chúng tới mt đầu ra cuối
cùng.
Trong Hadoop, bn định nghĩa các việc thực hiện mapreduce bng cách mrộng các lớp cơ
sở riêng của Hadoop. Các việc thực hin này được gắn chặt với nhau bằng một cấu hình quy đnh
chúng, cùng với các đnh dạng đầu vào và đầu ra. Hadoop rất tch hợp cho việc xlý các tệp rất
lớn chứa dữ liệu có cấu trúc. Một khía cạnh rất tin dụng của Hadoop là ở chnó xử lý phân tích
cú pháp thô của một tệp đầu vào, do đó bạn có thể x mt dòng tại mt thời đim. Vì thế việc
đnh nghĩa một hàm map thực ra chỉ là vấn đề xác đnh những gì bạn cần nắm lấy từ mt dòng
văn bn gửi đến.
Về đầu trang
Dliệu khắp mọi nơi!
Phát triển kỹ năng về ch đề này
Nội dung này nm trong "đường dẫn đến kiến thức (knowledge path)" để bsung các k năng
của bạn. Xem Using NoSQL and analyzing big data
Chính phHoa Kỳ tạo ra rt nhiều dữ liệu, phần ln trong số đó quan trọng với các công dân
trung lưu. Các cơ quan chính phủ khác tự do phân phối dữ liệu ln quan đến sức khỏe nền kinh
tế Mỹ và việc thay đổi kết quả thống kê dân sxã hi. Cơ quan Khảo sát Địa chất Hoa Kỳ
(USGS - The U.S. Geological Survey) công bố các dữ liệu động đất quốc tế.
Nhiều trận động đất nh xảy ra hàng ngày tại nhiều khu vực trên toàn thế gii. Phần lớn trong s
đó xảy ra ở sâu bên trong lớp vỏ trái đất, do đó không ai cảm thấy chúng, nhưng các trạm thu vẫn
ghi lại chúng. USGS công bố hàng tuần dữ liệu động đất của mình dưới dạng của một tệp CSV
(hoặc các giá trị được phân cách bng dấu phẩy).
Một tệp trung bình hàng tuần không phi là quá lớn — chỉ khoảng 100KB hay tương đương như
vậy. Mặc dù vy, nó sẽ dùng làm cơ sở cho việc tìm hiểu về Hadoop. Tuy nhiên, hãy nhớ rằng
Hadoop có khnăng xử lý các tập hợp dữ liệu ln hơn nhiều.
Theo dõi các trận động đất
Tệp CSV mà mi đây i đã tải về từ trang web của USGS có khoảng 920 dòng, như trong Liệt
kê 1:
Liệt kê 1. Tổng số dòng của một tệp dữ liệu động đất của USGS
$> wc -l eqs7day-M1.txt
920 eqs7day-M1.txt
Các nội dung của tệp CVS trông đại thể giống như những gì bn thấy trong Liệt2 (đây chính
là hai dòng đầu tiên):
Liệt kê 2. Hai dòng đầu tiên của tệp CVS
$> head -n 2 eqs7day-M1.txt
Src,Eqid,Version,Datetime,Lat,Lon,Magnitude,Depth,NST,Region
ci,14896484,2,"Sunday, December 12, 2010 23:23:20 UTC",33.3040,-
116.4130,1.0,11.70,22,
"Southern California"
Đó là những gì tôi sẽ gọi là mt tệp giàu thông tin (information rich), đặc biệt là khi bạn biết
rằng tệp này tổng số 920 dòng. Tuy nhiên, tôi chỉ muốn biết có bao nhiêu trận động đất xảy ra
mi ngày trong tuần được tệp này báo cáo. Sau đó, tôi muốn biết khu vực bình thường nào đã có
nhiều trận động đất nhất trong vòng bảy ngày đó.
Suy nghĩ đầu tiên của tôi là tôi thể sử dụng các lệnh grep đơn giản để tìm kiếm số lượng các
trận đng đất mỗi ngày. Hãy xem tệp này, i thấy rằng dữ liệu của nó bắt đầu t ngày12 tháng
12 (December 12). vy, tôi thực hin mt lệnh grep -c của chuỗi đó, với kết quả được hin
th trong Liệt kê 3:
Liệt kê 3. bao nhiêu trận động đất vào ngày 12 tháng 12?
$> grep -c 'December 12' eqs7day-M1.txt
98
Cài đặt Hadoop
Nếu bạn vẫn chưa cài đặt Hadoop thì hãy làm điều đó ngay. Trước tiên, tải về tệp mã nh phân
mới nhất, giải nén nó rồi thiết lập đường dẫn thư mục bin của Hadoop vào biến môi trường path
trên máy tính của bn. Việc này cho phép bạn thực hiện lnh hadoop trực tiếp. Việc sử dụng
Hadoop đòi hi bạn phi thực hin lệnh hadoop của nó chứ không phải bằng cách gọi lnh java.
Bạn có thchuyn các tùy chọn vào lnh hadoop, chẳng hạn như có thể tìm thấy các tệp nhị
phân Java của bn ở đâu ( dụ, các tệp này đại din cho các việc thực hin map và reduce của
bạn). Trong trường hợp của tôi, tôi to ra mt tệp jar và nói cho Hadoop biết nhng công việc
o mà tôi muốn chạy bên trong tệp jar của mình. i cũng thêm vào bất kỳ tệp nhị phân bổ sung
o cần thiết để chyng dụng của mình với đường dẫn lớp (classpath) của Hadoop.
Bây giờ tôi biết rằng vào ngày 12 tháng 12 đã có 98 mục nhập hay 98 trận động đất được ghi
nhận. Tôi chỉ có thể xuống dòng và thực hiện một lnh grep với ngày 10, 11 tháng 12 và v.v.
Nhưng điều đó thật là chán. Thơn nữa là để làm được, tôi cần phải biết trong tệp đó có nhng
ngày nào. Tôi thì lại không muốn quan tâm về điều đó và trong một s trường hợp, có thể tôi
không có quyền truy cập vào thông tin. Thực sự tôi chỉ muốn biết nhng con scho từng ngày
cụ thể trong bất kỳ khoảng thi gian by ngày nào và tôi thể nhn được thông tin đó một cách
dễ dàng bằng Hadoop.
Hadoop ch cần mt vài mẩu thông tin để trả lời câu hỏi thnhất và thhai của tôi: đó là, cần x
những đầu vào nào và làm thế nào để xử lý map và reduce. Ngoài ra tôi cũng sẽ phi cung cấp
mt công việc gắn chặt mi thli với nhau. Nhưng trước khi tôi bắt đầu làm về mã đó, tôi sẽ
mất một vài phút để chắc chn rằng mi thứ đều hợp lệ với dữ liệu CSV của tôi.
Về đầu trang
Phân tích cú pháp dliệu bằng opencsv
Ngoài dòng đầu tiên chính là tiêu đề của tệp dữ liu CSV về các trận đng đất, thì mi dòng là
mt loạt các giá trị dữ liệu được phân cách bằng dấu phẩy. Đầu tiên tôi quan tâm đến ba mẩu
thông tin: ny, ta đ và đlớn của mi trận động đất. Đểđược những mẩu tin này, tôi sẽ sử
dụng một thư vin mã nguồn mở tin li tên là opencsv, giúp phân tích cú pháp các tệp CSV.
Trong lần kiểm tra đầu tiên, tôi sbắt đầu bằng cách viết mt bài kiểm tra nhanh JUnit để xác
minh rằng tôi có thnhn được thông tin mà tôi cần từ một dòng ví dmẫu thu được của tệp
CSV, được hiển thị trong Liệt kê 4:
Liệt kê 4. Phân tích cú pháp một dòng CSV
public class CSVProcessingTest {
private final String LINE = "ci,14897012,2,\"Monday, December 13, 2010 " +
"14:10:32 UTC\",33.0290,-115." +
"5388,1.9,15.70,41,\"Southern California\"";
@Test
public void testReadingOneLine() throws Exception {
String[] lines = new CSVParser().parseLine(LINE);
assertEquals("should be Monday, December 13, 2010 14:10:32 UTC",
"Monday, December 13, 2010 14:10:32 UTC", lines[3]);
assertEquals("should be Southern California",
"Southern California", lines[9]);
assertEquals("should be 1.9", "1.9", lines[6]);
}
}
Như bạn có ththấy trong Lit kê 4, opencsv thực hinng việc với các giá trị được phân cách
bằng dấu phẩy khá dễ dàng. Trình phân tích cú pháp ch trả về một mảng của các String (Chui
ký tự), do đó, có thể nhận được các giá trị vị trí (chỉ cần nhớ lại rằng việc truy cập vào mảng và
collection của Java dựa vào số 0 (zero-based)).
Chuyển đổi định dạng ngày
Khi làm việc vi MapReduce, công việc của hàm map là chọn mt vài giá trị để trả lời, cùng vi
khóa nào đó. Có nghĩa là, trước tiên hàm map làm việc và trả về hai phần tử: một khóa và mt giá
tr. Hãy quay lại các yêu cầu trước đây của tôi, trước hết tôi muốn tìm ra có bao nhiêu trận động
đất xy ra mi ngày. Theo đó, khi i phân tích tệp động đất, i sẽ phát ra hai giá trị: khóa của
i slà ngày và giá tr sẽ là mt bđếm. Sau đó hàm reduce của tôi sẽ tính tổng các bộ đếm (là
các snguyên), thế cung cấp cho tôi số lần động đất trong một ngày.
Vì tôi đang quan tâm đến khoảng thi gian là 24-giờ, nêni sẽ phi loại bỏ khía cạnh thi gian
của ngày trong mi tệp. Trong Liệt kê 5, tôi viết một bài kiểm tra nhanh để xác nhn hợp lệ rằng
i sẽ chuyển đổi đnh dạng ngày tháng cụ thtrong mt tệp gửi đến thành một ngày khoảng
thi gian 24-gi tổng quát hơn như thế nào:
Liệt kê 5. Các chuyển đổi định dạng ngày
@Test
public void testParsingDate() throws Exception {
String datest = "Monday, December 13, 2010 14:10:32 UTC";
SimpleDateFormat formatter = new SimpleDateFormat("EEEEE, MMMMM dd, yyyy
HH:mm:ss Z");
Date dt = formatter.parse(datest);
formatter.applyPattern("dd-MM-yyyy");
String dtstr = formatter.format(dt);
assertEquals("should be 13-12-2010", "13-12-2010", dtstr);
}