Big Data nguồn mở, Phần 1: Hướng dẫn Hadoop: Tạo ứng dụng Hello World với Java, Pig, Hive, Flume, Fuse, Oozie và Sqoop với Informix, DB2 và MySQL

Bắt đầu tìm hiểu Hadoop và các cơ sở dữ liệu yêu thích của bạn

Bài này tập trung vào việc giải thích Big Data và cung cấp các ví dụ đơn giản về Hadoop, ứng dụng nguồn mở chuyên dùng để phân tích Big Data. Bạn sẽ vui mừng khi biết rằng Hadoop KHÔNG PHẢI là để thay thế cho Informix® hoặc DB2®, nhưng trong thực tế Hadoop chạy rất tốt với cơ sở hạ tầng hiện có. Có rất nhiều thành phần trong họ Hadoop và bài này sẽ đi sâu vào các ví dụ mẫu cụ thể để cho thấy các khả năng của nó. Hãy thử chạy các ví dụ mẫu trên máy tính của mình.

Marty Lurie, Kỹ sư hệ thống, IBM Corporation

Ảnh của Marty LurieMarty Lurie đã bắt đầu sự nghiệp máy tính của mình với việc bấm bìa giấy trong khi tìm hiểu lập trình bằng Fortran trên một máy tính IBM 1130. Công việc hàng ngày của ông là một Kỹ sư hệ thống Hadoop tại Cloudera, nhưng nếu có ai hỏi thì ông sẽ nói đùa rằng chủ yếu là chơi với các máy tính. Ông rất thích một chương trình mà ông đã viết để kết nối máy trượt tuyết đường dài Nordic Track với máy tính xách tay, nhờ chiếc máy đó mà ông đã giảm được 2 cân Anh và giảm lượng cholesterol 20%. Marty có chứng chỉ Haddop Administrator và Hadoop Developer của Cloudera, chứng chỉ Advanced WebSphere Administrator của IBM, chứng chỉ Professional về Informix, chứng chỉ DB2 DBA, chứng chỉ Business Intelligence Solutions Professional, chứng chỉ Linux +. Ngoài ra, ông cũng huấn luyện chú chó của mình chơi bóng rổ. Bạn có thể liên hệ với Marty tại marty@cloudera.com.


Cấp độ đóng góp cho developerWorks của
        tác giả

19 03 2013

Có rất nhiều điều thú vị về Big Data và cũng có rất nhiều sự nhầm lẫn về nó. Bài này sẽ cung cấp một định nghĩa về Big Data và sau đó thực hiện một loạt các ví dụ để bạn có thể có được những hiểu biết ban đầu về một số khả năng của Hadoop, công nghệ nguồn mở hàng đầu trong lĩnh vực Big Data. Cụ thể, ta tập trung vào những câu hỏi sau:.

  • Big Data, Hadoop, Sqoop, Hive và Pig là gì và tại sao lĩnh vực này lại có nhiều điều thú vị?
  • Hadoop liên quan đến DB2 và Informix của IBM như thế nào? Các công nghệ này có thể chạy với nhau không?
  • Tôi có thể bắt đầu với Big Data như thế nào? Có ví dụ nào dễ để thử chạy trên máy tính không?
  • Nếu bạn đã biết khái niệm về Hadoop rồi và muốn vào thẳng công việc với các ví dụ mẫu, thì hãy làm như sau.
    1. Hãy bắt đầu chạy một thể hiện Informix hoặc DB2 của bạn.
    2. Tải về file ảnh cho máy ảo VMWare từ Trang web của Cloudera và tăng thông số RAM máy ảo lên thành 1,5 GB.
    3. Chuyển đến mục chứa các ví dụ mẫu.
    4. Có một thể hiện MySQL đã được xây dựng sẵn trong máy ảo VMWare này. Nếu bạn đang làm các bài thực hành mà không kết nối mạng, hãy sử dụng các ví dụ MySQL này.

Ngoài ra, xin vui lòng xem tiếp...

Big Data là gì?

Big Data lớn về số lượng, được bắt giữ với tốc độ nhanh, có cấu trúc hoặc không có cấu trúc, hoặc là bao gồm các yếu tố ở trên. Những yếu tố này làm cho Big Data khó bắt giữ lại, khai phá và quản lý nếu dùng các phương thức truyền thống. Có rất nhiều ý kiến về lĩnh vực này, đến nỗi có thể cần đến một cuộc tranh luận kéo dài chỉ để định nghĩa thế nào là Big Data.

Sử dụng công nghệ Big Data không chỉ giới hạn về các khối lượng lớn. Bài này sử dụng các ví dụ mẫu nhỏ để minh họa các khả năng của công nghệ này. Tính đến năm 2012, các hệ thống được coi là lớn nằm trong phạm vi 100 Petabyte.

Dữ liệu lớn có thể vừa là dữ liệu có cấu trúc, vừa là dữ liệu không có cấu trúc. Các cơ sở dữ liệu quan hệ truyền thống, như Informix và DB2, cung cấp các giải pháp đã được kiểm chứng với dữ liệu có cấu trúc. Thông qua khả năng mở rộng, các cơ sở dữ liệu này cũng quản lý cả dữ liệu không có cấu trúc. Công nghệ Hadoop mang đến những kỹ thuật lập trình mới và dễ sử dụng hơn để làm việc với các kho dữ liệu lớn có cả dữ liệu có cấu trúc lẫn dữ liệu không có cấu trúc.


Tại sao lại có những điều thú vị ấy?

Có nhiều yếu tố tạo nên sự cường điệu xoay quanh Big Data, bao gồm:.

  • Mang tính toán và lưu trữ lại cùng với nhau trên phần cứng thông dụng: Cho kết quả tốc độ nhanh với chi phí thấp.
  • Tỷ số giá hiệu năng: Công nghệ Big Data của Hadoop đưa ra mức tiết kiệm chi phí đáng kể (hãy nghĩ đến một hệ số nhân xấp xỉ 10) với những cải thiện hiệu năng đáng kể (một lần nữa, hãy nghĩ đến một hệ số nhân là 10). Lời lãi của bạn có thể thay đổi. Nếu công nghệ hiện tại có thể bị đánh bại nặng nề như vậy, thì thật đáng để xem xét xem Hadoop có thể bổ sung hoặc thay thế các khía cạnh của kiến trúc hiện tại của bạn không.
  • Khả năng mở rộng quy mô tuyến tính: Tất cả các công nghệ song song đều tuyên bố dễ mở rộng quy mô. Hadoop có khả năng mở rộng quy mô kể từ khi phát hành bản mới nhất có khả năng mở rộng giới hạn số lượng các nút vượt quá 4.000.
  • Truy cập đầy đủ đến dữ liệu không có cấu trúc: Một kho dữ liệu có thể mở rộng quy mô cao với một mô hình lập trình song song thích hợp, MapReduce, đã là một thách thức cho ngành công nghiệp từ lâu nay. Mô hình lập trình của Hadoop không giải quyết tất cả vấn đề, nhưng nó là một giải pháp mạnh cho nhiều nhiệm vụ.

Các bản phân phối Hadoop: IBM và Cloudera

Đối với những người mới bắt đầu thì họ thường bối rối rằng "Tôi có thể tìm phần mềm để làm việc với Big Data ở đâu?" Các ví dụ trong bài này đều dựa trên bản phân phối Hadoop miễn phí của Cloudera được gọi là CDH (viết tắt của Cloudera distribution including Hadoop). Bản phân phối này có sẵn dưới dạng một file ảnh máy ảo VMWare từ trang web Cloudera. Gần đây IBM đang sửa đổi nền tảng Big Data của mình để chạy trên CDH. Xem thông tin chi tiết trong phần Tài nguyên.

Thường thì thuật ngữ công nghệ đột phá bị lạm dụng rất nhiều, nhưng có thể nó rất phù hợp trong trường hợp này.


Hadoop là gì?

Dưới đây là một vài định nghĩa về Hadoop, mỗi định nghĩa nhắm vào một nhóm đối tượng khác nhau trong doanh nghiệp:

  • Đối với các giám đốc điều hành: Hadoop là một dự án phần mềm nguồn mở của Apache để thu được giá trị từ khối lượng/ tốc độ/ tính đa dạng đáng kinh ngạc của dữ liệu về tổ chức của bạn. Hãy sử dụng dữ liệu thay vì vứt bỏ hầu hết dữ liệu đó đi.
  • Đối với các giám đốc kỹ thuật: Hadoop là một bộ phần mềm nguồn mở để khai phá Big Data có cấu trúc và không có cấu trúc về công ty của bạn. Nó tích hợp với hệ sinh thái Business Intelligence của bạn.
  • Đối với nhân viên pháp lý: Hadoop là một bộ phần mềm nguồn mở được nhiều nhà cung cấp đóng gói và hỗ trợ. Hãy xem phần Tài nguyên về việc trả tiền sở hữu trí tuệ (IP).
  • Đối với các kỹ sư: Hadoop là một môi trường song song thực thi map-reduce dựa trên Java, không chia sẻ gì cả. Hãy nghĩ đến hàng trăm, hàng ngàn máy tính đang làm việc để giải quyết cùng một vấn đề, có khả năng khôi phục lỗi dựng sẵn. Các dự án trong hệ sinh thái Hadoop cung cấp khả năng load (tải) dữ liệu, hỗ trợ ngôn ngữ cấp cao, triển khai trên đám mây tự động và các khả năng khác.
  • Đối với chuyên gia bảo mật: Hadoop là một bộ phần mềm bảo mật-Kerberos.

Hadoop có những thành phần nào?

Dự án Hadoop của Apache có hai thành phần cốt lõi, kho lưu trữ tệp gọi là Hadoop Distributed File System (HDFS – Hệ thống tệp phân tán Hadoop) và khung công tác lập trình gọi là MapReduce. Có một số dự án hỗ trợ để sử dụng HDFS và MapReduce. Bài này sẽ cung cấp một cái nhìn sơ lược, bạn hãy tìm đọc cuốn sách của OReily "Hadoop The Definitive Guide", tái bản lần thứ 3, để biết thêm chi tiết.

Các định nghĩa dưới đây nhằm cung cấp cho bạn những thông tin cơ bản để sử dụng các ví dụ mã tiếp theo. Bài này thực sự mong muốn giúp bạn bắt đầu bằng trải nghiệm thực hành với công nghệ này. Đây là một bài hướng dẫn hơn là bài hỏi đáp thảo luận.

  • HDFS: Nếu bạn muốn có hơn 4000 máy tính làm việc với dữ liệu của bạn, thì tốt hơn bạn nên phổ biến dữ liệu của bạn trên hơn 4000 máy tính đó. HDFS thực hiện điều này cho bạn. HDFS có một vài bộ phận dịch chuyển. Các Datanode (Nút dữ liệu) lưu trữ dữ liệu của bạn và Namenode (Nút tên) theo dõi nơi lưu trữ các thứ. Ngoài ra còn có những thành phần khác nữa, nhưng như thế đã đủ để bắt đầu.
  • MapReduce: Đây là mô hình lập trình cho Hadoop. Có hai giai đoạn, không ngạc nhiên khi được gọi là Map và Reduce. Để gây ấn tượng với các bạn bè của bạn hãy nói với họ là có một quá trình shuffle-sort (ND.: một quá trình mà hệ thống thực hiện sắp xếp và chuyển các kết quả đầu ra của map tới các đầu vào của các bộ rút gọn) giữa hai giai đoạn Map và Reduce. JobTracker (Trình theo dõi công việc) quản lý hơn 4000 thành phần công việc MapReduce. Các TaskTracker (Trình theo dõi nhiệm vụ) nhận các lệnh từ JobTracker. Nếu bạn thích Java thì viết mã bằng Java. Nếu bạn thích SQL hoặc các ngôn ngữ khác không phải Java thì rất may là bạn có thể sử dụng một tiện ích gọi là Hadoop Streaming (Luồng dữ liệu Hadoop).
  • Hadoop Streaming: Một tiện ích để tạo nên mã MapReduce bằng bất kỳ ngôn ngữ nào: C, Perl, Python, C++, Bash, v.v. Các ví dụ bao gồm một trình mapper Python và một trình reducer AWK.
  • Hive và Hue: Nếu bạn thích SQL, bạn sẽ rất vui khi biết rằng bạn có thể viết SQL và yêu cầu Hive chuyển đổi nó thành một tác vụ MapReduce. Đúng là bạn chưa có một môi trường ANSI-SQL đầy đủ, nhưng bạn có 4000 ghi chép và khả năng mở rộng quy mô ra nhiều Petabyte. Hue cung cấp cho bạn một giao diện đồ họa dựa trên trình duyệt để làm công việc Hive của bạn.
  • Pig: Một môi trường lập trình mức cao hơn để viết mã MapReduce. Ngôn ngữ Pig được gọi là Pig Latin. Bạn có thể thấy các quy ước đặt tên hơi khác thường một chút, nhưng bạn sẽ có tỷ số giá-hiệu năng đáng kinh ngạc và tính sẵn sàng cao.
  • Sqoop: Cung cấp việc truyền dữ liệu hai chiều giữa Hadoop và cơ sở dữ liệu quan hệ yêu thích của bạn.
  • Oozie: Quản lý luồng công việc Hadoop. Oozie không thay thế trình lập lịch biểu hay công cụ BPM của bạn, nhưng nó cung cấp cấu trúc phân nhánh if-then-else và điều khiển trong phạm vi tác vụ Hadoop của bạn.
  • HBase: Một kho lưu trữ key-value có thể mở rộng quy mô rất lớn. Nó hoạt động rất giống như một hash-map để lưu trữ lâu bền (với những người hâm mộ python, hãy nghĩ đến một từ điển). Nó không phải là một cơ sở dữ liệu quan hệ, mặc dù có tên là HBase.
  • FlumeNG: Trình nạp thời gian thực để tạo luồng dữ liệu của bạn vào Hadoop. Nó lưu trữ dữ liệu trong HDFS và HBase. Bạn sẽ muốn bắt đầu với FlumeNG, để cải thiện luồng ban đầu.
  • Whirr: Cung cấp Đám mây cho Hadoop. Bạn có thể khởi động một hệ thống chỉ trong vài phút với một tệp cấu hình rất ngắn.
  • Mahout: Máy học dành cho Hadoop. Được sử dụng cho các phân tích dự báo và phân tích nâng cao khác.
  • Fuse: Làm cho hệ thống HDFS trông như một hệ thống tệp thông thường, do đó bạn có thể sử dụng lệnh ls, cd, rm và những lệnh khác với dữ liệu HDFS.
  • Zookeeper: Được sử dụng để quản lý đồng bộ cho hệ thống. Bạn sẽ không phải làm việc nhiều với Zookeeper, nhưng nó sẽ làm việc rất nhiều cho bạn. Nếu bạn nghĩ rằng bạn cần viết một chương trình có sử dụng Zookeeper thì bạn hoặc là rất, rất thông minh và bạn có thể là một ủy viên cho một dự án Apache hoặc bạn sắp có một ngày rất tồi tệ.

Hình 1 cho thấy các phần quan trọng của Hadoop.

Hình 1. Kiến trúc Hadoop
Hình này hiển thị kiến trúc hadoop

HDFS, tầng dưới cùng, nằm trên một cụm phần cứng thông thường. Các máy chủ lắp vào tủ khung (rack-mounted) đơn giản, mỗi máy chủ có các CPU lõi 2-Hex, 6 đến 12 đĩa và 32 Gb ram. Đối với một công việc map-reduce, tầng trình ánh xạ đọc từ các đĩa ở tốc độ rất cao. Trình ánh xạ phát ra các cặp khóa giá trị được sắp xếp và được đưa tới trình rút gọn và tầng trình rút gọn tóm lược các cặp key-value. Không, bạn không phải tóm lược các cặp key-value, trên thực tế bạn có thể có một tác vụ map-reduce chỉ có có các trình ánh xạ. Điều này sẽ trở nên dễ hiểu hơn khi bạn xem ví dụ python-awk.

Hadoop tích hợp với cơ sở hạ tầng Informix hoặc DB2 như thế nào?

Hadoop tích hợp rất tốt với cơ sở dữ liệu Informix và cơ sở dữ liệu DB2 thông qua Sqoop. Sqoop là công cụ nguồn mở hàng đầu để di chuyển dữ liệu giữa Hadoop và các cơ sở dữ liệu quan hệ. Nó sử dụng JDBC để đọc và viết vào Informix, DB2, MySQL, Oracle và các nguồn khác. Có các bộ thích ứng được tối ưu hoá cho một vài cơ sở dữ liệu, bao gồm Netezza và DB2. Hãy xem phần Tài nguyên về cách tải về các bộ thích ứng này. Tất cả các ví dụ đều là đặc trưng của Sqoop.


Bắt đầu: Làm thế nào để chạy các ví dụ Hadoop, Hive, Pig, Oozie và Sqoop đơn giản

Bạn đã tìm hiểu nhập môn và các định nghĩa, bây giờ là lúc bắt đầu những công việc thực sự. Để tiếp tục, bạn sẽ cần tải về VMWare, VirtualBox hoặc file ảnh máy ảo khác từ trang Web Cloudera và bắt đầu chạy MapReduce! File máy ảo chạy cấu hình 64bit và một trong các môi trường ảo hóa phổ biến. Hầu hết các môi trường ảo hóa đều có một bản tải về miễn phí. Khi bạn cố gắng khởi động một file ảnh máy ảo 64bit, bạn có thể nhận được thông báo lỗi về các thiết lập BIOS. Hình 2 cho thấy các thay đổi cần thiết trong BIOS của một máy, ở đây là Thinkpad™. Hãy thận trọng khi thực hiện các thay đổi. Một số gói bảo mật của công ty sẽ yêu cầu bạn nhập mật khẩu trước khi lưu những thay đổi.

Hình 2. Các thiết lập BIOS cho một khách ảo 64bit
Hình này hiển thị các thiết lập BIOS cho một khách ảo 64bit

Big Data được dùng ở đây thực sự là khá nhỏ. Vấn đề không phải là làm cho máy tính của bạn nóng lên khi xử lý một tệp lớn, mà để cho bạn thấy các nguồn dữ liệu rất thú vị và các công việc của map-reduce để trả lời những thắc mắc của bạn.

Tải về file ảnh máy ảo Hadoop

Bạn cần sử dụng file ảnh máy ảo Cloudera để chạy các ví dụ này. Hadoop là một công nghệ để giải quyết các vấn đề. Việc đóng gói file ảnh Cloudera cho phép bạn tập trung vào các câu hỏi big-data. Nhưng nếu bạn quyết định tự mình lắp ráp tất cả các bộ phận, Hadoop trở thành vấn đề cần giải quyết, chứ không còn là giải pháp nữa.

Tải về một máy ảo. Máy ảo CDH4, sản phẩm mới nhất có sẵn ở đây: CDH4 image. Phiên bản trước, CDH3, có sẵn ở đây: CDH3 image.

Bạn có thể chọn các công nghệ ảo hóa của mình. Bạn có thể tải về một môi trường ảo hóa miễn phí từ VMWare và những phần mềm khác. Ví dụ, hãy chuyển đến vmware.com và tải về vmware-player. Máy tính của bạn đang chạy Windows, hãy tải về phiên bản vmware-player dành cho windows. Các ví dụ trong bài này sẽ sử dụng VMWare cho các ví dụ này và chạy hệ điều hành Linux Ubuntu bằng cách sử dụng "tar" thay vì "winzip" hoặc tương đương.

Sau khi tải về, giải nén (untar/unzip) như sau: tar -zxvf cloudera-demo-vm-cdh4.0.0-vmware.tar.gz.

Hoặc, nếu bạn đang sử dụng CDH3, thì sử dụng lệnh sau: tar -zxvf cloudera-demo-vm-cdh3u4-vmware.tar.gz

Unzip có thể hoạt động với các tệp tar. Sau khi giải nén, bạn có thể bắt đầu chạy máy ảo đó như sau:
vmplayer cloudera-demo-vm.vmx.

Bây giờ bạn sẽ có một màn hình trông giống như màn hình hiển thị trong Hình 3.

Hình 3. Ảnh ảo Cloudera
Hình này hiển thị ảnh chụp màn hình của ảnh vm

Lệnh Vmplayer đi sâu ngay vào máy ảo và khởi động máy ảo. Nếu bạn đang sử dụng CDH3, thì bạn sẽ cần phải tắt máy ảo và thay đổi các thiết lập bộ nhớ. Sử dụng biểu tượng nút nhấn nguồn bên cạnh đồng hồ ở phía dưới cùng chính giữa màn hình để tắt nguồn máy ảo. Sau đó, bạn cần chỉnh sửa quyền truy cập vào các thiết lập máy ảo.

Đối với CDH3, bước tiếp theo là bạn tăng bộ nhớ RAM. Hầu hết các thiết lập này chỉ có thể thay đổi khi đã tắt máy ảo. Hình 4 cho thấy cách truy cập vào các thiết lập này và tăng bộ nhớ RAM được cấp phát lên trên 2GB.

Hình 4. Thêm bộ nhớ RAM cho máy ảo
Hình này hiển thị việc thêm RAM cho máy ảo

Như hiển thị trong Hình 5, bạn có thể thay đổi các thiết lập mạng thành bridged (được nối cầu). Với thiết lập này, máy ảo sẽ nhận được địa chỉ IP riêng của mình. Nếu điều này tạo ra các vấn đề về sử dụng mạng của bạn, thì bạn có thể tùy chọn sử dụng Network Address Translation (NAT). Bạn sẽ sử dụng mạng để kết nối đến cơ sở dữ liệu.

Hình 5. Thay đổi các thiết lập mạng thành bridged
Hình này hiển thị việc thay đổi các thiết lập mạng thành bridged

Bạn bị hạn chế bởi bộ nhớ RAM trên hệ thống máy chủ vật lý, do đó, đừng cố gắng cấp phát bộ nhớ RAM nhiều hơn bộ nhớ RAM hiện có trên máy tính của bạn. Nếu bạn làm như vậy, máy tính sẽ chạy rất chậm.

Bây giờ, bạn chờ một lát, hãy tiếp tục và bật nguồn cho máy ảo. Tài khoản cloudera được tự động đăng nhập vào lúc khởi động. Nếu bạn cần mật khẩu thì mật khẩu của Cloudera là: cloudera.

Cài đặt Informix và DB2

Bạn sẽ cần một cơ sở dữ liệu để làm việc với nó. Nếu bạn chưa có một cơ sở dữ liệu nào, thì bạn có thể tải về Ấn bản Informix Developer (Phiên bản Informix dành cho nhà phát triển) ở đây hoặc Ấn bản DB2 Express-C miễn phí.

Một lựa chọn khác để cài đặt DB2 là tải về file ảnh máy ảo VMWare đã cài đặt sẵn DB2 trên một hệ điều hành Linux SuSE. Hãy đăng nhập như là người dùng chủ (root), với mật khẩu là: password.

Chuyển sang mã định danh người dùng (userid) là db2inst1. Làm việc trực tiếp trên tài khoản root cũng giống như việc lái xe mà không thắt dây an toàn vậy. Hãy liên hệ với Quản trị viên cơ sở dữ liệu (DBA) của bạn về việc chạy cơ sở dữ liệu. Bài này sẽ không trình bày điều đó ở đây. Đừng cố gắng cài đặt cơ sở dữ liệu bên trong máy ảo Cloudera vì không có đủ dung lượng đĩa để sử dụng.

Máy ảo sẽ kết nối với cơ sở dữ liệu bằng cách sử dụng Sqoop thông qua driver JDBC. Bạn sẽ cần có driver JDBC cho cơ sở dữ liệu của mình trong máy ảo. Bạn có thể cài đặt trình điều khiển Informix ở đây.

Trình điều khiển DB2 có ở đây: http://www.ibm.com/services/forms/preLogin.do?source=swg-idsdjs or http://www-01.ibm.com/support/docview.wss?rs=4020&uid=swg21385217.

Việc cài đặt trình driver JDBC Informix (hãy nhớ, chỉ cài driver bên trong máy ảo, chứ không phải cả cơ sở dữ liệu ở trong đó) được hiển thị trong Liệt kê 1.

Liệt kê 1. Cài đặt driver JDBC của Informix
tar -xvf ../JDBC.3.70.JC5DE.tar
followed by 
java -jar setup.jar

Lưu ý: Chọn một thư mục con bên trong /home/cloudera để không bị hỏi về quyền hạn mỗi khi cài đặt.

Driver JDBC của DB2 ở định dạng nén, do đó chỉ cần giải nén nó trong thư mục đích, như trong Liệt kê 2.

Liệt kê 2. Cài đặt driver JDBC của DB2
mkdir db2jdbc
cd db2jdbc
unzip ../ibm_data_server_driver_for_jdbc_sqlj_v10.1.zip

Giới thiệu ngắn về HDFS và MapReduce

Trước khi bạn bắt đầu di chuyển dữ liệu giữa cơ sở dữ liệu quan hệ của bạn và Hadoop, bạn cần biết qua về HDFS và MapReduce. Có rất nhiều hướng dẫn kiểu "hello world" cho Hadoop, vì thế các ví dụ ở đây được đưa ra chỉ nhằm để cung cấp đủ thông tin cơ bản để bạn hiểu các bài tập thực hành cơ sở dữ liệu của mình.

HDFS cung cấp lưu trữ trên các nút trong cụm của bạn. Bước đầu tiên trong việc sử dụng Hadoop là đưa dữ liệu vào HDFS. Mã được hiển thị trong Liệt kê 3 lấy một bản sao của một cuốn sách của Mark Twain và một cuốn sách của James Fenimore Cooper và sao chép các văn bản này vào HDFS.

Liệt kê 3. Nạp văn bản cuốn sách của Mark Twain và của James Fenimore Cooper vào HDFS
# install wget utility into the virtual image
sudo yum install wget
                
# use wget to download the Twain and Cooper's works
$ wget -U firefox http://www.gutenberg.org/cache/epub/76/pg76.txt
$ wget -U firefox http://www.gutenberg.org/cache/epub/3285/pg3285.txt
                
# load both into the HDFS file system
# first give the files better names
# DS for Deerslayer
# HF for  Huckleberry Finn
$ mv pg3285.txt DS.txt
$ mv pg76.txt HF.txt
                
# this next command will fail if the directory already exists
$ hadoop fs -mkdir /user/cloudera 
                
# now put the text into the directory 
$ hadoop fs -put HF.txt /user/cloudera
                
                
# way too much typing, create aliases for hadoop commands
$ alias hput="hadoop fs -put"
$ alias hcat="hadoop fs -cat"
$ alias hls="hadoop fs -ls"
# for CDH4 
$ alias hrmr="hadoop fs -rm -r"
# for CDH3 
$ alias hrmr="hadoop fs -rmr"
                
# load the other article
# but add some compression because we can 
                
$ gzip DS.txt 
                
# the  .  in the next command references the cloudera home directory
# in hdfs, /user/cloudera 
                
$ hput DS.txt.gz .
                
# now take a look at the files we have in place
$ hls
Found 2 items
-rw-r--r-- 1 cloudera supergroup  459386 2012-08-08 19:34 /user/cloudera/DS.txt.gz
-rw-r--r-- 1 cloudera supergroup  597587 2012-08-08 19:35 /user/cloudera/HF.txt

Bây giờ bạn có hai tệp trong một thư mục trong HDFS. Đừng phấn khích vội. Thật tình, trên một nút duy nhất và với chỉ có khoảng 1 megabyte, chả có gì đáng xem. Nhưng nếu đây là một cụm có 400 nút và bạn có 5 petabyte đang tồn tại, thì bạn sẽ thực sự rất khó kìm giữ sự hứng thú của mình.

Nhiều hướng dẫn trong số các hướng dẫn Hadoop sử dụng ví dụ đếm từ đã có trong tệp jar ví dụ. Hóa ra là rất nhiều phân tích liên quan đến việc đếm và gộp. Ví dụ trong Liệt kê 4 giới thiệu cho bạn cách gọi bộ đếm từ.

Liệt kê 4. Đếm các từ trong tác phẩm của Twain và Cooper
# hadoop comes with some examples
# this next line uses the provided java implementation of a 
# word count program
                
# for CDH4:
hadoop jar /usr/lib/hadoop-0.20-mapreduce/hadoop-examples.jar wordcount HF.txt HF.out

# for CDH3:
hadoop jar /usr/lib/hadoop/hadoop-examples.jar wordcount HF.txt HF.out
                
# for CDH4:
hadoop jar /usr/lib/hadoop-0.20-mapreduce/hadoop-examples.jar wordcount DS.txt.gz DS.out

# for CDH3:
hadoop jar /usr/lib/hadoop/hadoop-examples.jar wordcount  DS.txt.gz DS.out

Hậu tố .gz trong tệp DS.txt.gz nói cho Hadoop biết xử lý giải nén như là một phần của việc xử lý Map-Reduce. Cooper hơi dài dòng một chút vì thế đáng nén nó.

Còn có một luồng các thông báo từ việc chạy công việc đếm từ của bạn. Hadoop rất vui lòng cung cấp nhiều chi tiết về các chương trình Mapping và Reducing đang chạy thay cho bạn. Các dòng quan trọng mà bạn muốn tìm xem được hiển thị trong Liệt kê 5, bao gồm cả một liệt kê thứ hai về công việc có lỗi và cách sửa chữa một trong những lỗi phổ biến nhất mà bạn sẽ gặp phải khi chạy MapReduce.

Liệt kê 5. Các thông báo MapReduce - "con đường hạnh phúc"
$ hadoop jar /usr/lib/hadoop/hadoop-examples.jar wordcount HF.txt HF.out
12/08/08 19:23:46 INFO input.FileInputFormat: Total input paths to process : 1
12/08/08 19:23:47 WARN snappy.LoadSnappy: Snappy native library is available
12/08/08 19:23:47 INFO util.NativeCodeLoader: Loaded the native-hadoop library
12/08/08 19:23:47 INFO snappy.LoadSnappy: Snappy native library loaded
12/08/08 19:23:47 INFO mapred.JobClient: Running job: job_201208081900_0002
12/08/08 19:23:48 INFO mapred.JobClient:  map 0% reduce 0%
12/08/08 19:23:54 INFO mapred.JobClient:  map 100% reduce 0%
12/08/08 19:24:01 INFO mapred.JobClient:  map 100% reduce 33%
12/08/08 19:24:03 INFO mapred.JobClient:  map 100% reduce 100%
12/08/08 19:24:04 INFO mapred.JobClient: Job complete: job_201208081900_0002
12/08/08 19:24:04 INFO mapred.JobClient: Counters: 26
12/08/08 19:24:04 INFO mapred.JobClient:   Job Counters 
12/08/08 19:24:04 INFO mapred.JobClient:     Launched reduce tasks=1
12/08/08 19:24:04 INFO mapred.JobClient:     SLOTS_MILLIS_MAPS=5959
12/08/08 19:24:04 INFO mapred.JobClient:     Total time spent by all reduces...
12/08/08 19:24:04 INFO mapred.JobClient:     Total time spent by all maps waiting...
12/08/08 19:24:04 INFO mapred.JobClient:     Launched map tasks=1
12/08/08 19:24:04 INFO mapred.JobClient:     Data-local map tasks=1
12/08/08 19:24:04 INFO mapred.JobClient:     SLOTS_MILLIS_REDUCES=9433
12/08/08 19:24:04 INFO mapred.JobClient:   FileSystemCounters
12/08/08 19:24:04 INFO mapred.JobClient:     FILE_BYTES_READ=192298
12/08/08 19:24:04 INFO mapred.JobClient:     HDFS_BYTES_READ=597700
12/08/08 19:24:04 INFO mapred.JobClient:     FILE_BYTES_WRITTEN=498740
12/08/08 19:24:04 INFO mapred.JobClient:     HDFS_BYTES_WRITTEN=138218
12/08/08 19:24:04 INFO mapred.JobClient:   Map-Reduce Framework
12/08/08 19:24:04 INFO mapred.JobClient:     Map input records=11733
12/08/08 19:24:04 INFO mapred.JobClient:     Reduce shuffle bytes=192298
12/08/08 19:24:04 INFO mapred.JobClient:     Spilled Records=27676
12/08/08 19:24:04 INFO mapred.JobClient:     Map output bytes=1033012
12/08/08 19:24:04 INFO mapred.JobClient:     CPU time spent (ms)=2430
12/08/08 19:24:04 INFO mapred.JobClient:     Total committed heap usage (bytes)=183701504
12/08/08 19:24:04 INFO mapred.JobClient:     Combine input records=113365
12/08/08 19:24:04 INFO mapred.JobClient:     SPLIT_RAW_BYTES=113
12/08/08 19:24:04 INFO mapred.JobClient:     Reduce input records=13838
12/08/08 19:24:04 INFO mapred.JobClient:     Reduce input groups=13838
12/08/08 19:24:04 INFO mapred.JobClient:     Combine output records=13838
12/08/08 19:24:04 INFO mapred.JobClient:     Physical memory (bytes) snapshot=256479232
12/08/08 19:24:04 INFO mapred.JobClient:     Reduce output records=13838
12/08/08 19:24:04 INFO mapred.JobClient:     Virtual memory (bytes) snapshot=1027047424
12/08/08 19:24:04 INFO mapred.JobClient:     Map output records=113365

Tất cả các thông báo trên có ý nghĩa gì? Hadoop đã thực hiện nhiều công việc và đang cố gắng báo cho bạn biết về chúng, bao gồm những việc sau:

  • Đã kiểm tra để xem liệu các tệp đầu vào có tồn tại không.
  • Đã kiểm tra để xem liệu thư mục đầu ra đã tồn tại chưa, và nếu có, thì hủy bỏ công việc. Không gì tệ hơn là ghi đè lên hàng giờ tính toán, chỉ bởi một lỗi bàn phím đơn giản.
  • Đã phân phối tệp jar của Java cho tất cả các nút chịu trách nhiệm thực hiện công việc này. Trong trường hợp này, chỉ có một nút duy nhất.
  • Đã chạy giai đoạn ánh xạ của công việc. Thông thường giai đoạn này phân tích cú pháp tệp đầu vào và phát ra một cặp khóa giá trị. Lưu ý khóa và giá trị có thể là các đối tượng.
  • Đã chạy giai đoạn sắp xếp để sắp xếp các kết quả đầu ra của trình ánh xạ dựa trên khóa.
  • Đã chạy giai đoạn rút gọn, thường giai đoạn này tóm lược luồng key-value và ghi kết quả đầu ra vào HDFS.
  • Đã tạo các số liệu đo lường trong tiến trình.

Hình 6 cho thấy một trang web ví dụ mẫu về các số liệu đo lường của công việc Hadoop sau khi chạy bài tập thực hành Hive.

Hình 6. Trang web ví dụ mẫu của Hadoop
Hình này hiển thị trang web ví dụ mẫu về các số liệu đo lường của công việc Hadoop sau khi chạy bài thực hành Hive

Công việc này đã làm gì và kết quả đầu ra nằm ở đâu? Cả hai đều là những câu hỏi thích hợp và được hiển thị trong Liệt kê 6.

Liệt kê 6. Kết quả đầu ra của Map-Reduce
# way too much typing, create aliases for hadoop commands
$ alias hput="hadoop fs -put"
$ alias hcat="hadoop fs -cat"
$ alias hls="hadoop fs -ls"
$ alias hrmr="hadoop fs -rmr"
                
# first list the output directory
$ hls /user/cloudera/HF.out
Found 3 items
-rw-r--r-- 1 cloudera supergroup 0 2012-08-08 19:38 /user/cloudera/HF.out/_SUCCESS
drwxr-xr-x - cloudera supergroup 0 2012-08-08 19:38 /user/cloudera/HF.out/_logs
-rw-r--r-- 1 cl... sup... 138218 2012-08-08 19:38 /user/cloudera/HF.out/part-r-00000
                
# now cat the file and pipe it to  the  less command
$ hcat /user/cloudera/HF.out/part-r-00000 | less
                
# here are a few lines from the file, the word elephants only got used twice
elder,  1
eldest  1
elect   1
elected 1
electronic      27
electronically  1
electronically, 1
elegant 1
elegant!--'deed 1
elegant,        1
elephants       2

Trong trường hợp bạn chạy cùng một công việc hai lần và quên xóa thư mục kết quả đầu ra, bạn sẽ nhận được các thông báo lỗi được hiển thị trong Liệt kê 7. Việc sửa lỗi này chỉ đơn giản là xóa thư mục đó.

Liệt kê 7. Các thông báo MapReduce – lỗi do kết quả đầu ra đã tồn tại trong HDFS
# way too much typing, create aliases for hadoop commands
$ alias hput="hadoop fs -put"
$ alias hcat="hadoop fs -cat"
$ alias hls="hadoop fs -ls"
$ alias hrmr="hadoop fs -rmr"               
                
$ hadoop jar /usr/lib/hadoop/hadoop-examples.jar wordcount HF.txt HF.out
12/08/08 19:26:23 INFO mapred.JobClient: 
Cleaning up the staging area hdfs://0.0.0.0/var/l...
12/08/08 19:26:23 ERROR security.UserGroupInformation: PriviledgedActionException 
as:cloudera (auth:SIMPLE) 
cause:org.apache.hadoop.mapred.FileAlreadyExistsException: 
Output directory HF.out already exists
org.apache.hadoop.mapred.FileAlreadyExistsException: 
Output directory HF.out already exists
at org.apache.hadoop.mapreduce.lib.output.FileOutputFormat.
checkOutputSpecs(FileOutputFormat.java:132)
at org.apache.hadoop.mapred.JobClient$2.run(JobClient.java:872)
at org.apache.hadoop.mapred.JobClient$2.run(JobClient.java:833)
                
.... lines deleted
                
# the simple fix is to remove the existing output directory
                
$ hrmr HF.out
                
# now you can re-run the job successfully
                
# if you run short of space and the namenode enters safemode
# clean up some file space and then
                
$ hadoop dfsadmin -safemode leave

Hadoop có một giao diện trình duyệt để kiểm tra trạng thái của HDFS. Hình 7 cho thấy kết quả đầu ra của công việc đếm từ.

Hình 7. Khám phá HDFS bằng một trình duyệt
Hình này hiển thị việc khám phá HDFS bằng một trình duyệt

Một giao diện điều khiển tinh tế hơn có sẵn miễn phí trong trang web của Cloudera. Nó cung cấp một số khả năng nằm ngoài các giao diện web Hadoop chuẩn. Lưu ý rằng tình trạng sức khỏe của HDFS trong Hình 8 được hiển thị là Bad (Kém).

Hình 8. Trình quản lý Cloudera quản lý Các dịch vụ Hadoop
Hình này hiển thị Trình quản lý Cloudera quản lý Hadoop Services

Tại sao tình trạng sức khỏe của HDFS lại kém? Vì trong một máy ảo đơn, HDFS không thể tạo ra ba bản sao của các khối dữ liệu. Khi các khối dữ liệu không được sao chép đủ, thì có nguy cơ mất dữ liệu, do đó, sức khỏe của hệ thống là kém. Tốt hơn là bạn đừng cố gắng chạy các tác vụ Hadoop chỉ trên một nút đơn.

Bạn không bị hạn chế phải dùng Java cho các công việc MapReduce của mình. Ví dụ cuối cùng này của MapReduce sử dụng Hadoop Streaming để hỗ trợ một trình mapper được viết bằng Python và một trình reducer có sử dụng AWK. Bạn không cần phải là một chuyên gia Java thì mới làm việc được với Map-Reduce!

Mark Twain không phải là một fan hâm mộ Cooper. Trong trường hợp này, Hadoop sẽ cung cấp một phê bình văn học đơn giản để so sánh giữa Twain và Cooper. Phép thử Flesch-Kincaid tính toán mức độ dễ đọc của một văn bản cụ thể. Một trong những yếu tố trong phân tích này là độ dài trung bình của câu. Việc phân tích cú pháp các câu hóa ra phức tạp hơn so với việc chỉ tìm kiếm dấu chấm câu. Gói phần mềm openNLP và gói phần mềm Python NLTK có các trình phân tích cú pháp câu rất tốt. Để đơn giản, ví dụ được hiển thị trong Liệt kê 8 sẽ sử dụng độ dài từ như là một sự thay thế cho số lượng các âm tiết trong một từ. Nếu bạn muốn dùng độ dài từ này cho mức tiếp theo, hãy thực hiện phép thử Flesch-Kincaid trong MapReduce, duyệt trang web và tính toán các mức dễ đọc cho các trang tin ưa thích của mình.

Liệt kê 8. Một phê bình văn học của trình mapper dựa trên Python
# here is the mapper we'll connect to the streaming hadoop interface
                
# the mapper is reading the text in the file - not really appreciating Twain's humor
# 
                
# modified from 
# http://www.michael-noll.com/tutorials/writing-an-hadoop-mapreduce-program-in-python/
$ cat mapper.py 
#!/usr/bin/env python
import sys
                
# read stdin
for linein in sys.stdin:
# strip blanks
linein = linein.strip()
# split into words
mywords = linein.split()
# loop on mywords, output the length of each word
for word in mywords:
# the reducer just cares about the first column, 
# normally there is a key - value pair
print '%s %s' % (len(word), 0)

Kết quả đầu ra của trình mapper, cho từ "Twain", sẽ là: 5 0. Các độ dài từ bằng số đều được sắp xếp theo thứ tự và được đưa tới trình rút gọn theo thứ tự sắp xếp. Trong các ví dụ được hiển thị trong Liệt kê 9 và 10, không cần sắp xếp dữ liệu để nhận được kết quả đầu ra đúng, nhưng do việc sắp xếp này được xây dựng trong cơ sở hạ tầng MapReduce nên dù sao cũng sẽ xảy ra.

Liệt kê 9. Một trình rút gọn AWK dùng cho phê bình văn học
# the awk code is modified from http://www.commandlinefu.com
                
# awk is calculating
#  NR - the number of words in total
#  sum/NR - the average word length
# sqrt(mean2/NR) - the standard deviation 
                
$ cat statsreducer.awk 
awk '{delta = $1 - avg; avg += delta / NR; \
mean2 += delta * ($1 - avg); sum=$1+sum } \
END { print NR, sum/NR, sqrt(mean2 / NR); }'
Liệt kê 10. Chạy một trình mapper Python và trình reducer AWK với Hadoop Streaming
# test locally
                
# because we're using Hadoop Streaming, we can test the 
# mapper and reducer with simple pipes
                
# the "sort" phase is a reminder the keys are sorted
# before presentation to the reducer
#in this example it doesn't matter what order the 
# word length values are presented for calculating the std deviation
                
$ zcat ../DS.txt.gz  | ./mapper.py | sort | ./statsreducer.awk 
215107 4.56068 2.50734
                
# now run in hadoop with streaming
                
# CDH4
hadoop jar /usr/lib/hadoop-mapreduce/hadoop-streaming.jar \
-input HF.txt -output HFstats -file ./mapper.py -file \
./statsreducer.awk -mapper ./mapper.py -reducer ./statsreducer.awk
		
# CDH3
$ hadoop jar /usr/lib/hadoop-0.20/contrib/streaming/hadoop-streaming-0.20.2-cdh3u4.jar \
-input HF.txt -output HFstats -file ./mapper.py -file ./statsreducer.awk \
-mapper ./mapper.py -reducer ./statsreducer.awk
                
$ hls HFstats
Found 3 items
-rw-r--r--   1 cloudera supergroup   0 2012-08-12 15:38 /user/cloudera/HFstats/_SUCCESS
drwxr-xr-x   - cloudera supergroup   0 2012-08-12 15:37 /user/cloudera/HFstats/_logs
-rw-r--r--   1 cloudera ...  24 2012-08-12 15:37 /user/cloudera/HFstats/part-00000
                
$ hcat /user/cloudera/HFstats/part-00000
113365 4.11227 2.17086
                
# now for cooper
                
$ hadoop jar /usr/lib/hadoop-0.20/contrib/streaming/hadoop-streaming-0.20.2-cdh3u4.jar \
-input DS.txt.gz -output DSstats -file ./mapper.py -file ./statsreducer.awk \
-mapper ./mapper.py -reducer ./statsreducer.awk
                
$ hcat /user/cloudera/DSstats/part-00000
215107 4.56068 2.50734

Những người hâm mộ Mark Twain có thể vui mừng khi biết rằng Hadoop tìm ra Cooper sử dụng các từ dài hơn và với một độ lệch tiêu chuẩn gây sốc (nhằm mục đích hài hước). Tất nhiên điều đó giả định rằng các từ ngắn hơn là tốt hơn. Hãy tiếp tục, phần tiếp theo sẽ ghi dữ liệu trong HDFS vào Informix và DB2.

Sử dụng Sqoop để ghi dữ liệu từ HDFS vào Informix, DB2 hoặc MySQL thông qua JDBC

Sqoop Apache Project là một Hadoop dựa trên JDBC nguồn mở cho tiện ích di chuyển dữ liệu của cơ sở dữ liệu. Ban đầu Sqoop đã được tạo ra trong một cuộc thi lập trình hackathon tại Cloudera và sau đó trở thành nguồn mở.

Việc di chuyển dữ liệu từ HDFS sang một cơ sở dữ liệu quan hệ là một trường hợp sử dụng phổ biến. HDFS và Map-Reduce rất giỏi làm công việc nặng. Đối với các truy vấn đơn giản hoặc một kho lưu trữ mặt sau cho một trang web, việc bắt giữ lại kết quả đầu ra Map-Reduce trong một kho lưu trữ quan hệ là một mẫu thiết kế tốt. Bạn có thể tránh chạy lại việc đếm từ của Map-Reduce bằng cách chỉ di chuyển các kết quả bằng Sqoop vào Informix và DB2. Bạn đã tạo ra dữ liệu về Twain và Cooper, bây giờ hãy di chuyển nó vào một cơ sở dữ liệu, như trong Liệt kê 11.

Liệt kê 11. Thiết lập driver JDBC
#Sqoop needs access to the JDBC driver for every
# database that it will access
                
# please copy the driver for each database you plan to use for these exercises
# the MySQL database and driver are already installed in the virtual image
# but you still need to copy the driver to the sqoop/lib directory
                
#one time copy of jdbc driver to sqoop lib directory
$ sudo cp Informix_JDBC_Driver/lib/ifxjdbc*.jar /usr/lib/sqoop/lib/
$ sudo cp db2jdbc/db2jcc*.jar /usr/lib/sqoop/lib/
$ sudo cp /usr/lib/hive/lib/mysql-connector-java-5.1.15-bin.jar /usr/lib/sqoop/lib/

Các ví dụ được hiển thị trong các Liệt kê từ 12 đến 15 được trình bày cho từng cơ sở dữ liệu. Hãy đọc ngay vào ví dụ mà bạn quan tâm, gồm có Informix, DB2 hoặc MySQL. Đối với các chương trình cơ sở dữ liệu được viết theo nhiều ngôn ngữ lập trình, hãy giải trí với tất cả mọi ví dụ. Nếu cơ sở dữ liệu mà bạn chọn không có ở đây thì cũng không phải là một thách thức lớn để chạy các ví dụ mẫu ở những nơi khác.

Liệt kê 12. Những người dùng Informix: Sqoop ghi các kết quả đếm từ vào Informix
# create a target table to put the data
# fire up dbaccess and use this sql 
# create table wordcount ( word char(36) primary key, n int);
                
# now run the sqoop command
# this is best put in a shell script to help avoid typos...
                
$ sqoop export -D sqoop.export.records.per.statement=1 \
--fields-terminated-by '\t' --driver com.informix.jdbc.IfxDriver \
--connect \
"jdbc:informix-sqli://myhost:54321/stores_demo:informixserver=i7;user=me;password=mypw" \
--table wordcount --export-dir /user/cloudera/HF.out
Liệt kê 13. Những người dùng Informix: Sqoop ghi các kết quả đếm từ vào Informix
12/08/08 21:39:42 INFO manager.SqlManager: Using default fetchSize of 1000
12/08/08 21:39:42 INFO tool.CodeGenTool: Beginning code generation
12/08/08 21:39:43 INFO manager.SqlManager: Executing SQL statement: SELECT t.* 
FROM wordcount AS t WHERE 1=0
12/08/08 21:39:43 INFO manager.SqlManager: Executing SQL statement: SELECT t.* 
FROM wordcount AS t WHERE 1=0
12/08/08 21:39:43 INFO orm.CompilationManager: HADOOP_HOME is /usr/lib/hadoop
12/08/08 21:39:43 INFO orm.CompilationManager: Found hadoop core jar at: 
/usr/lib/hadoop/hadoop-0.20.2-cdh3u4-core.jar
12/08/08 21:39:45 INFO orm.CompilationManager: Writing jar file: 
/tmp/sqoop-cloudera/compile/248b77c05740f863a15e0136accf32cf/wordcount.jar
12/08/08 21:39:45 INFO mapreduce.ExportJobBase: Beginning export of wordcount
12/08/08 21:39:45 INFO manager.SqlManager: Executing SQL statement: SELECT t.* 
FROM wordcount AS t WHERE 1=0
12/08/08 21:39:46 INFO input.FileInputFormat: Total input paths to process : 1
12/08/08 21:39:46 INFO input.FileInputFormat: Total input paths to process : 1
12/08/08 21:39:46 INFO mapred.JobClient: Running job: job_201208081900_0012
12/08/08 21:39:47 INFO mapred.JobClient:  map 0% reduce 0%
12/08/08 21:39:58 INFO mapred.JobClient:  map 38% reduce 0%
12/08/08 21:40:00 INFO mapred.JobClient:  map 64% reduce 0%
12/08/08 21:40:04 INFO mapred.JobClient:  map 82% reduce 0%
12/08/08 21:40:07 INFO mapred.JobClient:  map 98% reduce 0%
12/08/08 21:40:09 INFO mapred.JobClient: Task Id : 
attempt_201208081900_0012_m_000000_0, Status : FAILED
java.io.IOException: java.sql.SQLException: 
    Encoding or code set not supported.
at ...SqlRecordWriter.close(AsyncSqlRecordWriter.java:187)
at ...$NewDirectOutputCollector.close(MapTask.java:540)
at org.apache.hadoop.mapred.MapTask.runNewMapper(MapTask.java:649)
at org.apache.hadoop.mapred.MapTask.run(MapTask.java:323)
at org.apache.hadoop.mapred.Child$4.run(Child.java:270)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAs(Subject.java:396)
at ....doAs(UserGroupInformation.java:1177)
at org.apache.hadoop.mapred.Child.main(Child.java:264)
Caused by: java.sql.SQLException: Encoding or code set not supported.
at com.informix.util.IfxErrMsg.getSQLException(IfxErrMsg.java:413)
at com.informix.jdbc.IfxChar.toIfx(IfxChar.java:135)
at com.informix.jdbc.IfxSqli.a(IfxSqli.java:1304)
at com.informix.jdbc.IfxSqli.d(IfxSqli.java:1605)
at com.informix.jdbc.IfxS
12/08/08 21:40:11 INFO mapred.JobClient:  map 0% reduce 0%
12/08/08 21:40:15 INFO mapred.JobClient: Task Id : 
attempt_201208081900_0012_m_000000_1, Status : FAILED
java.io.IOException: java.sql.SQLException: 
    Unique constraint (informix.u169_821) violated.
at .mapreduce.AsyncSqlRecordWriter.write(AsyncSqlRecordWriter.java:223)
at .mapreduce.AsyncSqlRecordWriter.write(AsyncSqlRecordWriter.java:49)
at .mapred.MapTask$NewDirectOutputCollector.write(MapTask.java:531)
at .mapreduce.TaskInputOutputContext.write(TaskInputOutputContext.java:80)
at com.cloudera.sqoop.mapreduce.TextExportMapper.map(TextExportMapper.java:82)
at com.cloudera.sqoop.mapreduce.TextExportMapper.map(TextExportMapper.java:40)
at org.apache.hadoop.mapreduce.Mapper.run(Mapper.java:144)
at .mapreduce.AutoProgressMapper.run(AutoProgressMapper.java:189)
at org.apache.hadoop.mapred.MapTask.runNewMapper(MapTask.java:647)
at org.apache.hadoop.mapred.MapTask.run(MapTask.java:323)
at org.apache.hadoop.mapred.Child$4.run(Child.java:270)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.a
12/08/08 21:40:20 INFO mapred.JobClient: 
Task Id : attempt_201208081900_0012_m_000000_2, Status : FAILED
java.sql.SQLException: Unique constraint (informix.u169_821) violated.
at .mapreduce.AsyncSqlRecordWriter.write(AsyncSqlRecordWriter.java:223)
at .mapreduce.AsyncSqlRecordWriter.write(AsyncSqlRecordWriter.java:49)
at .mapred.MapTask$NewDirectOutputCollector.write(MapTask.java:531)
at .mapreduce.TaskInputOutputContext.write(TaskInputOutputContext.java:80)
at com.cloudera.sqoop.mapreduce.TextExportMapper.map(TextExportMapper.java:82)
at com.cloudera.sqoop.mapreduce.TextExportMapper.map(TextExportMapper.java:40)
at org.apache.hadoop.mapreduce.Mapper.run(Mapper.java:144)
at .mapreduce.AutoProgressMapper.run(AutoProgressMapper.java:189)
at org.apache.hadoop.mapred.MapTask.runNewMapper(MapTask.java:647)
at org.apache.hadoop.mapred.MapTask.run(MapTask.java:323)
at org.apache.hadoop.mapred.Child$4.run(Child.java:270)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.a
12/08/08 21:40:27 INFO mapred.JobClient: Job complete: job_201208081900_0012
12/08/08 21:40:27 INFO mapred.JobClient: Counters: 7
12/08/08 21:40:27 INFO mapred.JobClient:   Job Counters 
12/08/08 21:40:27 INFO mapred.JobClient:     SLOTS_MILLIS_MAPS=38479
12/08/08 21:40:27 INFO mapred.JobClient:     
Total time spent by all reduces waiting after reserving slots (ms)=0
12/08/08 21:40:27 INFO mapred.JobClient:     
Total time spent by all maps waiting after reserving slots (ms)=0
12/08/08 21:40:27 INFO mapred.JobClient:     Launched map tasks=4
12/08/08 21:40:27 INFO mapred.JobClient:     Data-local map tasks=4
12/08/08 21:40:27 INFO mapred.JobClient:     SLOTS_MILLIS_REDUCES=0
12/08/08 21:40:27 INFO mapred.JobClient:     Failed map tasks=1
12/08/08 21:40:27 INFO mapreduce.ExportJobBase: 
Transferred 0 bytes in 41.5758 seconds (0 bytes/sec)
12/08/08 21:40:27 INFO mapreduce.ExportJobBase: Exported 0 records.
12/08/08 21:40:27 ERROR tool.ExportTool: Error during export: Export job failed!
                
# despite the errors above, rows are inserted into the wordcount table
# one row is missing
# the retry and duplicate key exception are most likely related, but
# troubleshooting will be saved for a later article
                
# check how we did
# nothing like a "here document" shell script
                
$ dbaccess stores_demo - <<eoj
> select count(*) from wordcount;
> eoj
                
Database selected.
(count(*)) 
13837
1 row(s) retrieved.
Database closed.
Liệt kê 14. Những người dùng DB2: Sqoop ghi các kết quả đếm từ vào DB2
# here is the db2 syntax
# create a destination table for db2
#
#db2 => connect to sample
#
#   Database Connection Information
#
# Database server        = DB2/LINUXX8664 10.1.0
# SQL authorization ID   = DB2INST1
# Local database alias   = SAMPLE
#
#db2 => create table wordcount ( word char(36) not null primary key , n int)
#DB20000I  The SQL command completed successfully.
#
                
sqoop export -D sqoop.export.records.per.statement=1 \
--fields-terminated-by '\t' \
--driver com.ibm.db2.jcc.DB2Driver \
--connect "jdbc:db2://192.168.1.131:50001/sample"  \
--username db2inst1 --password db2inst1 \
--table wordcount --export-dir /user/cloudera/HF.out 
                
12/08/09 12:32:59 WARN tool.BaseSqoopTool: Setting your password on the 
command-line is insecure. Consider using -P instead.
12/08/09 12:32:59 INFO manager.SqlManager: Using default fetchSize of 1000
12/08/09 12:32:59 INFO tool.CodeGenTool: Beginning code generation
12/08/09 12:32:59 INFO manager.SqlManager: Executing SQL statement: 
SELECT t.* FROM wordcount AS t WHERE 1=0
12/08/09 12:32:59 INFO manager.SqlManager: Executing SQL statement: 
SELECT t.* FROM wordcount AS t WHERE 1=0
12/08/09 12:32:59 INFO orm.CompilationManager: HADOOP_HOME is /usr/lib/hadoop
12/08/09 12:32:59 INFO orm.CompilationManager: Found hadoop core jar 
at: /usr/lib/hadoop/hadoop-0.20.2-cdh3u4-core.jar
12/08/09 12:33:00 INFO orm.CompilationManager: Writing jar 
file: /tmp/sqoop-cloudera/compile/5532984df6e28e5a45884a21bab245ba/wordcount.jar
12/08/09 12:33:00 INFO mapreduce.ExportJobBase: Beginning export of wordcount
12/08/09 12:33:01 INFO manager.SqlManager: Executing SQL statement: 
SELECT t.* FROM wordcount AS t WHERE 1=0
12/08/09 12:33:02 INFO input.FileInputFormat: Total input paths to process : 1
12/08/09 12:33:02 INFO input.FileInputFormat: Total input paths to process : 1
12/08/09 12:33:02 INFO mapred.JobClient: Running job: job_201208091208_0002
12/08/09 12:33:03 INFO mapred.JobClient:  map 0% reduce 0%
12/08/09 12:33:14 INFO mapred.JobClient:  map 24% reduce 0%
12/08/09 12:33:17 INFO mapred.JobClient:  map 44% reduce 0%
12/08/09 12:33:20 INFO mapred.JobClient:  map 67% reduce 0%
12/08/09 12:33:23 INFO mapred.JobClient:  map 86% reduce 0%
12/08/09 12:33:24 INFO mapred.JobClient:  map 100% reduce 0%
12/08/09 12:33:25 INFO mapred.JobClient: Job complete: job_201208091208_0002
12/08/09 12:33:25 INFO mapred.JobClient: Counters: 16
12/08/09 12:33:25 INFO mapred.JobClient:   Job Counters 
12/08/09 12:33:25 INFO mapred.JobClient:     SLOTS_MILLIS_MAPS=21648
12/08/09 12:33:25 INFO mapred.JobClient:     Total time spent by all 
reduces waiting after reserving slots (ms)=0
12/08/09 12:33:25 INFO mapred.JobClient:     Total time spent by all 
maps waiting after reserving slots (ms)=0
12/08/09 12:33:25 INFO mapred.JobClient:     Launched map tasks=1
12/08/09 12:33:25 INFO mapred.JobClient:     Data-local map tasks=1
12/08/09 12:33:25 INFO mapred.JobClient:     SLOTS_MILLIS_REDUCES=0
12/08/09 12:33:25 INFO mapred.JobClient:   FileSystemCounters
12/08/09 12:33:25 INFO mapred.JobClient:     HDFS_BYTES_READ=138350
12/08/09 12:33:25 INFO mapred.JobClient:     FILE_BYTES_WRITTEN=69425
12/08/09 12:33:25 INFO mapred.JobClient:   Map-Reduce Framework
12/08/09 12:33:25 INFO mapred.JobClient:     Map input records=13838
12/08/09 12:33:25 INFO mapred.JobClient:     Physical memory (bytes) snapshot=105148416
12/08/09 12:33:25 INFO mapred.JobClient:     Spilled Records=0
12/08/09 12:33:25 INFO mapred.JobClient:     CPU time spent (ms)=9250
12/08/09 12:33:25 INFO mapred.JobClient:     Total committed heap usage (bytes)=42008576
12/08/09 12:33:25 INFO mapred.JobClient:     Virtual memory (bytes) snapshot=596447232
12/08/09 12:33:25 INFO mapred.JobClient:     Map output records=13838
12/08/09 12:33:25 INFO mapred.JobClient:     SPLIT_RAW_BYTES=126
12/08/09 12:33:25 INFO mapreduce.ExportJobBase: Transferred 135.1074 KB 
in 24.4977 seconds (5.5151 KB/sec)
12/08/09 12:33:25 INFO mapreduce.ExportJobBase: Exported 13838 records.                
                
# check on the results...
#
#db2 => select count(*) from wordcount 
#
#1          
#-----------
#      13838
#
#  1 record(s) selected.
#
#
Liệt kê 15. Những người dùng MySQL: Sqoop ghi các kết quả đếm từ vào MySQL
# if you don't have Informix or DB2 you can still do this example
# mysql - it is already installed in the VM, here is how to access
                
# one time copy of the JDBC driver
                
sudo cp /usr/lib/hive/lib/mysql-connector-java-5.1.15-bin.jar /usr/lib/sqoop/lib/
                
# now create the database and table
                
$ mysql -u root
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 45
Server version: 5.0.95 Source distribution
                
Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
                
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
                
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
                
mysql> create database mydemo;
Query OK, 1 row affected (0.00 sec)
                
mysql> use mydemo
Database changed
mysql> create table wordcount ( word char(36) not null primary key, n int);
Query OK, 0 rows affected (0.00 sec)
                
mysql> exit
Bye
                
# now export
                
$ sqoop export --connect jdbc:mysql://localhost/mydemo \
--table wordcount --export-dir /user/cloudera/HF.out \
--fields-terminated-by '\t' --username root

Nhập dữ liệu vào HDFS từ Informix và DB2 bằng Sqoop

Việc chèn dữ liệu vào HDFS của Hadoop cũng có thể được thực hiện bằng Sqoop. Chức năng hai hướng được điều khiển thông qua tham số nhập khẩu.

Các cơ sở dữ liệu ví dụ mẫu đi kèm với cả hai sản phẩm này có một số bộ dữ liệu đơn giản để bạn có thể dùng cho mục đích này. Liệt kê 16 cho thấy cú pháp và các kết quả khi dùng Sqoop cho mỗi máy chủ..

Đối với những người dùng MySQL, hãy sửa lại cú pháp của các ví dụ Informix hoặc DB2 cho phù hợp để tiếp tục.

Liệt kê 16. Nhập khẩu Sqoop từ cơ sở dữ liệu ví dụ mẫu Informix vào HDFS
$ sqoop import --driver com.informix.jdbc.IfxDriver \
--connect \
"jdbc:informix-sqli://192.168.1.143:54321/stores_demo:informixserver=ifx117" \
--table orders \
--username informix --password useyours
                
12/08/09 14:39:18 WARN tool.BaseSqoopTool: Setting your password on the command-line 
is insecure. Consider using -P instead.
12/08/09 14:39:18 INFO manager.SqlManager: Using default fetchSize of 1000
12/08/09 14:39:18 INFO tool.CodeGenTool: Beginning code generation
12/08/09 14:39:19 INFO manager.SqlManager: Executing SQL statement: 
SELECT t.* FROM orders AS t WHERE 1=0
12/08/09 14:39:19 INFO manager.SqlManager: Executing SQL statement: 
SELECT t.* FROM orders AS t WHERE 1=0
12/08/09 14:39:19 INFO orm.CompilationManager: HADOOP_HOME is /usr/lib/hadoop
12/08/09 14:39:19 INFO orm.CompilationManager: Found hadoop core jar 
at: /usr/lib/hadoop/hadoop-0.20.2-cdh3u4-core.jar
12/08/09 14:39:21 INFO orm.CompilationManager: Writing jar 
file: /tmp/sqoop-cloudera/compile/0b59eec7007d3cff1fc0ae446ced3637/orders.jar
12/08/09 14:39:21 INFO mapreduce.ImportJobBase: Beginning import of orders
12/08/09 14:39:21 INFO manager.SqlManager: Executing SQL statement: 
SELECT t.* FROM orders AS t WHERE 1=0
12/08/09 14:39:22 INFO db.DataDrivenDBInputFormat: BoundingValsQuery: 
SELECT MIN(order_num), MAX(order_num) FROM orders
12/08/09 14:39:22 INFO mapred.JobClient: Running job: job_201208091208_0003
12/08/09 14:39:23 INFO mapred.JobClient:  map 0% reduce 0%
12/08/09 14:39:31 INFO mapred.JobClient:  map 25% reduce 0%
12/08/09 14:39:32 INFO mapred.JobClient:  map 50% reduce 0%
12/08/09 14:39:36 INFO mapred.JobClient:  map 100% reduce 0%
12/08/09 14:39:37 INFO mapred.JobClient: Job complete: job_201208091208_0003
12/08/09 14:39:37 INFO mapred.JobClient: Counters: 16
12/08/09 14:39:37 INFO mapred.JobClient:   Job Counters 
12/08/09 14:39:37 INFO mapred.JobClient:     SLOTS_MILLIS_MAPS=22529
12/08/09 14:39:37 INFO mapred.JobClient:     Total time spent by all reduces 
waiting after reserving slots (ms)=0
12/08/09 14:39:37 INFO mapred.JobClient:     Total time spent by all maps 
waiting after reserving slots (ms)=0
12/08/09 14:39:37 INFO mapred.JobClient:     Launched map tasks=4
12/08/09 14:39:37 INFO mapred.JobClient:     SLOTS_MILLIS_REDUCES=0
12/08/09 14:39:37 INFO mapred.JobClient:   FileSystemCounters
12/08/09 14:39:37 INFO mapred.JobClient:     HDFS_BYTES_READ=457
12/08/09 14:39:37 INFO mapred.JobClient:     FILE_BYTES_WRITTEN=278928
12/08/09 14:39:37 INFO mapred.JobClient:     HDFS_BYTES_WRITTEN=2368
12/08/09 14:39:37 INFO mapred.JobClient:   Map-Reduce Framework
12/08/09 14:39:37 INFO mapred.JobClient:     Map input records=23
12/08/09 14:39:37 INFO mapred.JobClient:     Physical memory (bytes) snapshot=291364864
12/08/09 14:39:37 INFO mapred.JobClient:     Spilled Records=0
12/08/09 14:39:37 INFO mapred.JobClient:     CPU time spent (ms)=1610
12/08/09 14:39:37 INFO mapred.JobClient:     Total committed heap usage (bytes)=168034304
12/08/09 14:39:37 INFO mapred.JobClient:     Virtual memory (bytes) snapshot=2074587136
12/08/09 14:39:37 INFO mapred.JobClient:     Map output records=23
12/08/09 14:39:37 INFO mapred.JobClient:     SPLIT_RAW_BYTES=457
12/08/09 14:39:37 INFO mapreduce.ImportJobBase: Transferred 2.3125 KB in 16.7045 
seconds (141.7585 bytes/sec)
12/08/09 14:39:37 INFO mapreduce.ImportJobBase: Retrieved 23 records.
                
# now look at the results
                
$ hls
Found 4 items
-rw-r--r--   1 cloudera supergroup     459386 2012-08-08 19:34 /user/cloudera/DS.txt.gz
drwxr-xr-x   - cloudera supergroup          0 2012-08-08 19:38 /user/cloudera/HF.out
-rw-r--r--   1 cloudera supergroup     597587 2012-08-08 19:35 /user/cloudera/HF.txt
drwxr-xr-x   - cloudera supergroup          0 2012-08-09 14:39 /user/cloudera/orders
$ hls orders
Found 6 items
-rw-r--r--   1 cloudera supergroup 0 2012-08-09 14:39 /user/cloudera/orders/_SUCCESS
drwxr-xr-x   - cloudera supergroup 0 2012-08-09 14:39 /user/cloudera/orders/_logs
-rw-r--r--   1 cloudera ...roup 630 2012-08-09 14:39 /user/cloudera/orders/part-m-00000
-rw-r--r--   1 cloudera supergroup        
564 2012-08-09 14:39 /user/cloudera/orders/part-m-00001
-rw-r--r--   1 cloudera supergroup        
527 2012-08-09 14:39 /user/cloudera/orders/part-m-00002
-rw-r--r--   1 cloudera supergroup        
647 2012-08-09 14:39 /user/cloudera/orders/part-m-00003
                
# wow  there are four files part-m-0000x
# look inside one 
                
# some of the lines are edited to fit on the screen
$ hcat /user/cloudera/orders/part-m-00002
1013,2008-06-22,104,express ,n,B77930    ,2008-07-10,60.80,12.20,2008-07-31
1014,2008-06-25,106,ring bell,  ,n,8052      ,2008-07-03,40.60,12.30,2008-07-10
1015,2008-06-27,110,        ,n,MA003     ,2008-07-16,20.60,6.30,2008-08-31
1016,2008-06-29,119, St.          ,n,PC6782    ,2008-07-12,35.00,11.80,null
1017,2008-07-09,120,use                 ,n,DM354331  ,2008-07-13,60.00,18.00,null

Tại sao có bốn tệp khác nhau mà mỗi tệp chỉ chứa một phần dữ liệu? Sqoop là một tiện ích song song ở mức cao. Nếu một cụm có 4000 nút đang chạy Sqoop đã thực hiện nhập khẩu hết mức từ một cơ sở dữ liệu, thì 4000 kết nối cùng lúc sẽ trông rất giống như một cuộc tấn công từ chối dịch vụ chống lại cơ sở dữ liệu. Giới hạn kết nối mặc định của Sqoop là bốn kết nối JDBC. Mỗi kết nối tạo ra một tệp dữ liệu trong HDFS. Vì thế có bốn tệp. Đừng lo, bạn sẽ thấy cách Hadoop làm việc trên các tệp mà không gặp bất kỳ khó khăn nào.

Bước tiếp theo là nhập khẩu một bảng DB2. Như hiển thị trong Liệt kê 17, bằng cách chỉ rõ tùy chọn -m 1, có thể nhập khẩu một bảng mà không có khóa chính và kết quả là một tệp duy nhất.

Liệt kê 17. Nhập khẩu Sqoop từ cơ sở dữ liệu ví dụ mẫu DB2 vào HDFS
# very much the same as above, just a different jdbc connection
# and different table name
                
sqoop import --driver com.ibm.db2.jcc.DB2Driver \
--connect "jdbc:db2://192.168.1.131:50001/sample"  \
--table staff --username db2inst1  \
--password db2inst1 -m 1 

# Here is another example
# in this case set the sqoop default schema to be different from
# the user login schema
		
sqoop import --driver com.ibm.db2.jcc.DB2Driver \
--connect "jdbc:db2://192.168.1.3:50001/sample:currentSchema=DB2INST1;" \
--table helloworld \
--target-dir "/user/cloudera/sqoopin2" \
--username marty \
-P -m 1 
		
# the the schema name is CASE SENSITIVE 
# the -P option prompts for a password that will not be visible in
# a "ps" listing

Sử dụng Hive: Nối dữ liệu Informix và dữ liệu DB2

Có một trường hợp sử dụng thú vị cần nối dữ liệu từ Informix đến DB2. Không hứng thú lắm đối với hai bảng tầm thường, nhưng sẽ là một thắng lợi vĩ đại với nhiều terabyte hoặc petabyte dữ liệu.

Có hai cách tiếp cận cơ bản để nối các nguồn dữ liệu khác nhau. Cứ giữ nguyên dữ liệu ở đâu ở đó và sử dụng công nghệ liên hợp dữ liệu đối lập với việc di chuyển dữ liệu đến một kho lưu trữ duy nhất để thực hiện phép nối. Yếu tố kinh tế và hiệu năng của Hadoop làm cho việc di chuyển dữ liệu vào HDFS và thực hiện công việc nặng nhọc với MapReduce trở thành một sự lựa chọn dễ dàng. Các giới hạn băng thông mạng tạo ra một rào cản chính nếu cố gắng nối dữ liệu ở nguyên chỗ cũ bằng một công nghệ kiểu liên hợp. Để biết thêm thông tin về liên hợp dữ liệu, hãy xem phần Tài nguyên.

Hive cung cấp một tập hợp con của SQL để hoạt động trên một cụm. Nó không cung cấp ngữ nghĩa giao dịch. Nó không phải là một sự thay thế cho Informix hoặc DB2. Nếu bạn có một công việc nặng nề nào đó dưới dạng các phép nối bảng, ngay cả khi bạn có một số bảng nhỏ hơn nhưng cần phải thực hiện các tích Đề-các (Cartesian) khó chịu, thì Hadoop là công cụ nên dùng.

Để sử dụng ngôn ngữ truy vấn Hive, cần có một tập hợp con của SQL được gọi là siêu dữ liệu bảng Hiveql. Bạn có thể định nghĩa siêu dữ liệu này dựa vào các tệp hiện có trong HDFS. Sqoop cung cấp một lối tắt thuận tiện với tùy chọn create-hive-table (tạo bảng hive).

Những người dùng MySQL sẽ thấy thoải mái khi sửa lại các ví dụ được hiển thị trong Liệt kê 18 cho phù hợp. Một bài tập thú vị là nối MySQL hoặc bất kỳ các bảng cơ sở dữ liệu quan hệ khác nào, với các bảng tính lớn.

Liệt kê 18. Nối bảng informix.customer với bảng db2.staff
# import the customer table into Hive
$ sqoop import --driver com.informix.jdbc.IfxDriver  \
--connect \
"jdbc:informix-sqli://myhost:54321/stores_demo:informixserver=ifx;user=me;password=you"  \
--table customer
                
# now tell hive where to find the informix data
                
# to get to the hive command prompt just type in hive
                
$ hive
Hive history file=/tmp/cloudera/yada_yada_log123.txt
hive> 
                
# here is the hiveql you need to create the tables
# using a file is easier than typing 
                
create external table customer (
cn int,
fname string,
lname string,
company string,
addr1 string,
addr2 string,
city string,
state string,
zip string,
phone string)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
LOCATION '/user/cloudera/customer'
;
                               
# we already imported the db2 staff table above
                
# now tell hive where to find the db2 data
create external table staff (
id int,
name string,
dept string,
job string,
years string,
salary float,
comm float) 
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
LOCATION '/user/cloudera/staff'
;
                
# you can put the commands in a file 
# and execute them as follows:
                
$ hive -f hivestaff
Hive history file=/tmp/cloudera/hive_job_log_cloudera_201208101502_2140728119.txt
OK
Time taken: 3.247 seconds
OK
10	Sanders	20	Mgr  	7	98357.5	NULL
20	Pernal	20	Sales	8	78171.25	612.45
30	Marenghi	38	Mgr  	5	77506.75	NULL
40	O'Brien	38	Sales	6	78006.0	846.55
50	Hanes	15	Mgr  	10	80
... lines deleted
                
# now for the join we've all been waiting for :-)
                
# this is a simple case, Hadoop can scale well into the petabyte range!                 
                
$ hive
Hive history file=/tmp/cloudera/hive_job_log_cloudera_201208101548_497937669.txt
hive> select customer.cn, staff.name, 
> customer.addr1, customer.city, customer.phone
> from staff join customer
> on ( staff.id = customer.cn );
Total MapReduce jobs = 1
Launching Job 1 out of 1
Number of reduce tasks not specified. Estimated from input data size: 1
In order to change the average load for a reducer (in bytes):
set hive.exec.reducers.bytes.per.reducer=number
In order to limit the maximum number of reducers:
set hive.exec.reducers.max=number
In order to set a constant number of reducers:
set mapred.reduce.tasks=number
Starting Job = job_201208101425_0005, 
Tracking URL = http://0.0.0.0:50030/jobdetails.jsp?jobid=job_201208101425_0005
Kill Command = /usr/lib/hadoop/bin/hadoop 
job  -Dmapred.job.tracker=0.0.0.0:8021 -kill job_201208101425_0005
2012-08-10 15:49:07,538 Stage-1 map = 0%,  reduce = 0%
2012-08-10 15:49:11,569 Stage-1 map = 50%,  reduce = 0%
2012-08-10 15:49:12,574 Stage-1 map = 100%,  reduce = 0%
2012-08-10 15:49:19,686 Stage-1 map = 100%,  reduce = 33%
2012-08-10 15:49:20,692 Stage-1 map = 100%,  reduce = 100%
Ended Job = job_201208101425_0005
OK
110	Ngan	520 Topaz Way       	Redwood City   	415-743-3611      
120	Naughton	6627 N. 17th Way    	Phoenix        	602-265-8754      
Time taken: 22.764 seconds

Sẽ đẹp hơn nhiều khi bạn sử dụng Hue để có một giao diện đồ họa trong trình duyệt, như thể hiện trong Hình 9, 10 và 11.

Hình 9. Giao diện người dùng đồ họa (GUI) Beeswax của Hue cho Hive trong CDH4, xem truy vấn Hiveql
Hình này hiển thị Giao diện người dùng đồ họa Hue Beeswax cho Hive
Hình 10. Giao diện người dùng đồ họa (GUI) Beeswax của Hue cho Hive, xem truy vấn Hiveql
Hình này hiển thị Giao diện người dùng đồ họa Hue Beeswax cho Hive
Hình 11. Giao diện người dùng đồ họa (GUI) Beeswax của Hue, xem kết quả của phép nối Informix-DB2
Hình này hiển thị trình duyệt của Giao diện Hue Beeswax

Sử dụng Pig: Nối dữ liệu Informix và dữ liệu DB2

Pig là một ngôn ngữ thủ tục. Cũng giống như Hive, nó tạo mã MapReduce ngầm bên dưới vỏ bọc. Tính dễ sử dụng của Hadoop sẽ còn tiếp tục được cải thiện khi nhiều dự án trở nên có sẵn. Cũng giống như một số người trong chúng ta thực sự thích dòng lệnh, có một số giao diện người dùng đồ họa làm việc rất tốt với Hadoop.

Liệt kê 19 cho thấy mã Pig được sử dụng để nối bảng customer và bảng staff từ ví dụ trước.

Liệt kê 19. Ví dụ Pig để nối bảng Informix với bảng DB2
$ pig
grunt> staffdb2 = load 'staff' using PigStorage(',') 
>> as ( id, name, dept, job, years, salary, comm ); 
grunt> custifx2 = load 'customer' using PigStorage(',') as  
>>  (cn, fname, lname, company, addr1, addr2, city, state, zip, phone)
>> ;
grunt> joined = join custifx2 by cn,  staffdb2 by id;
                
# to make pig generate a result set use the dump command
# no work has happened up till now
                
grunt> dump joined;
2012-08-11 21:24:51,848 [main] INFO  org.apache.pig.tools.pigstats.ScriptState 
- Pig features used in the script: HASH_JOIN
2012-08-11 21:24:51,848 [main] INFO  org.apache.pig.backend.hadoop.executionengine
.HExecutionEngine - pig.usenewlogicalplan is set to true. 
New logical plan will be used.
                
HadoopVersion	PigVersion	UserId	StartedAt	FinishedAt	Features
0.20.2-cdh3u4	0.8.1-cdh3u4	cloudera	2012-08-11 21:24:51	
2012-08-11 21:25:19	HASH_JOIN
                
Success!
                
Job Stats (time in seconds):
JobId	Maps	Reduces	MaxMapTime	MinMapTIme	AvgMapTime	
MaxReduceTime	MinReduceTime	AvgReduceTime	Alias	Feature	Outputs
job_201208111415_0006	2	1	8	8	8	10	10	10
custifx,joined,staffdb2	HASH_JOIN	hdfs://0.0.0.0/tmp/temp1785920264/tmp-388629360,
                
Input(s):
Successfully read 35 records from: "hdfs://0.0.0.0/user/cloudera/staff"
Successfully read 28 records from: "hdfs://0.0.0.0/user/cloudera/customer"
                
Output(s):
Successfully stored 2 records (377 bytes) in: 
"hdfs://0.0.0.0/tmp/temp1785920264/tmp-388629360"
                
Counters:
Total records written : 2
Total bytes written : 377
Spillable Memory Manager spill count : 0
Total bags proactively spilled: 0
Total records proactively spilled: 0
                
Job DAG:
job_201208111415_0006                
                
2012-08-11 21:25:19,145 [main] INFO  
org.apache.pig.backend.hadoop.executionengine.mapReduceLayer.MapReduceLauncher - Success!
2012-08-11 21:25:19,149 [main] INFO  org.apache.hadoop.mapreduce.lib.
input.FileInputFormat - Total input paths to process : 1
2012-08-11 21:25:19,149 [main] INFO  org.apache.pig.backend.hadoop.
executionengine.util.MapRedUtil - Total input paths to process : 1
(110,Roy            ,Jaeger         ,AA Athletics        ,520 Topaz Way       
,null,Redwood City   ,CA,94062,415-743-3611      ,110,Ngan,15,Clerk,5,42508.20,206.60)
(120,Fred           ,Jewell         ,Century Pro Shop    ,6627 N. 17th Way    
,null,Phoenix        ,AZ,85016,602-265-8754      
,120,Naughton,38,Clerk,null,42954.75,180.00)

Tôi chọn Java, Hive hoặc Pig như thế nào?

Bạn có nhiều tùy chọn để lập trình Hadoop và tốt nhất là xem xét trường hợp sử dụng để chọn đúng công cụ cho công việc đó. Bạn không bị hạn chế chỉ làm việc với dữ liệu quan hệ nhưng bài này tập trung vào Informix, DB2 và Hadoop để hoạt động tốt với chúng. Việc viết hàng trăm dòng mã bằng Java để thực hiện một phép nối băm kiểu quan hệ là hoàn toàn phí thời gian do thuật toán MapReduce của Hadoop đã có sẵn. Bạn chọn tùy chọn nào? Đó là vấn đề sở thích cá nhân. Một số người thích viết mã các phép toán tập hợp bằng SQL. Một số người khác thích viết mã kiểu thủ tục. Bạn nên chọn ngôn ngữ mà bạn làm việc hiệu quả nhất. Nếu bạn có nhiều hệ thống quan hệ và muốn kết hợp tất cả các dữ liệu với hiệu năng lớn với một mức giá thấp, thì Hadoop, MapReduce, Hive và Pig đã sẵn sàng để trợ giúp.

Đừng xóa dữ liệu của bạn: Cuộn lại một phân vùng từ Informix vào HDFS

Hầu hết các cơ sở dữ liệu quan hệ hiện đại đều có thể phân vùng dữ liệu. Một trường hợp sử dụng phổ biến là phân vùng theo khoảng thời gian. Một cửa sổ thời gian cố định của các dữ liệu được lưu trong cơ sở dữ liệu, ví dụ một khoảng thời gian 18 tháng trôi qua, sau đó dữ liệu được đưa vào lưu trữ. Khả năng tách phân vùng là rất mạnh. Nhưng sau khi phân vùng được tách ra người ta làm gì với dữ liệu?

Việc lưu trữ dữ liệu cũ vào băng từ là một cách rất tốn kém để loại bỏ các byte dữ liệu cũ. Sau khi đã di chuyển sang môi trường ít có thể truy cập hơn, dữ liệu rất hiếm khi được truy cập trừ khi có một yêu cầu kiểm toán hợp pháp. Hadoop đưa ra một sự thay thế khác tốt hơn.

Di chuyển các byte dữ liệu lưu trữ từ các phân vùng cũ vào Hadoop tạo ra khả năng truy cập hiệu năng cao với chi phí thấp hơn nhiều so với việc duy trì dữ liệu trong hệ thống giao dịch hoặc quầy dữ liệu/kho dữ liệu ban đầu. Dữ liệu là quá cũ không còn giá trị giao dịch nữa, nhưng vẫn còn rất có giá trị với tổ chức để dùng cho các phân tích dài hạn. Các ví dụ Sqoop được hiển thị ở trên cung cấp những điều cơ bản về cách di chuyển dữ liệu này từ một phân vùng quan hệ sang HDFS.

Fuse – Truy cập các tệp HDFS của bạn thông qua NFS

Có thể truy cập dữ liệu Informix/DB2/tệp phẳng trong HDFS thông qua NFS, như hiển thị trong Liệt kê 20. Cách này cung cấp các hoạt động dòng lệnh mà không cần sử dụng giao diện "hadoop fs-yadayada". Theo quan điểm công nghệ về trường hợp sử dụng, NFS rất bị hạn chế trong một môi trường Dữ liệu lớn, nhưng các ví dụ được cung cấp cho các nhà phát triển và dữ liệu không-lớn-lắm.

Liệt kê 20. Thiết lập Fuse - truy cập dữ liệu HDFS của bạn thông qua NFS
# this is for CDH4, the CDH3 image doesn't have fuse installed...
$ mkdir fusemnt
$ sudo hadoop-fuse-dfs dfs://localhost:8020 fusemnt/
INFO fuse_options.c:162 Adding FUSE arg fusemnt/
$ ls fusemnt
tmp  user  var
$ ls fusemnt/user
cloudera  hive
$ ls fusemnt/user/cloudera
customer  DS.txt.gz  HF.out  HF.txt  orders  staff
$ cat fusemnt/user/cloudera/orders/part-m-00001 
1007,2008-05-31,117,null,n,278693    ,2008-06-05,125.90,25.20,null
1008,2008-06-07,110,closed Monday    
,y,LZ230     ,2008-07-06,45.60,13.80,2008-07-21
1009,2008-06-14,111,next door to grocery                    
,n,4745      ,2008-06-21,20.40,10.00,2008-08-21
1010,2008-06-17,115,deliver 776 King St. if no answer       
,n,429Q      ,2008-06-29,40.60,12.30,2008-08-22
1011,2008-06-18,104,express                                 
,n,B77897    ,2008-07-03,10.40,5.00,2008-08-29
1012,2008-06-18,117,null,n,278701    ,2008-06-29,70.80,14.20,null

Flume - tạo ra một tệp sẵn sàng nạp

Thế hệ tiếp theo của Flume hay là flume-ng là trình nạp song song tốc độ cao. Các cơ sở dữ liệu có các trình nạp tốc độ cao, vậy làm thế nào để chúng sẽ hoạt động tốt với nhau? Trường hợp sử dụng dữ liệu quan hệ dành cho Flume-ng sẽ tạo ra một tệp sẵn sàng để nạp, tại chỗ hoặc từ xa, sao cho một máy chủ dữ liệu quan hệ có thể dùng trình nạp tốc độ cao của mình. Đúng là chức năng này chồng lên Sqoop, nhưng kịch bản lệnh được hiển thị trong Liệt kê 21 đã được tạo ra theo yêu cầu của một khách hàng đặc biệt cho kiểu nạp cơ sở dữ liệu này.

Liệt kê 21. Xuất khẩu dữ liệu HDFS tới một tệp phẳng để nạp bởi một cơ sở dữ liệu
$  sudo yum install flume-ng              
                
$ cat flumeconf/hdfs2dbloadfile.conf 
#
# started with example from flume-ng documentation
# modified to do hdfs source to file sink
#
                
# Define a memory channel called ch1 on agent1
 agent1.channels.ch1.type = memory                
                
# Define an exec source called exec-source1 on agent1 and tell it
# to bind to 0.0.0.0:31313. Connect it to channel ch1.
agent1.sources.exec-source1.channels = ch1
agent1.sources.exec-source1.type = exec
agent1.sources.exec-source1.command =hadoop fs -cat /user/cloudera/orders/part-m-00001
# this also works for all the files in the hdfs directory
# agent1.sources.exec-source1.command =hadoop fs
# -cat /user/cloudera/tsortin/*
agent1.sources.exec-source1.bind = 0.0.0.0
agent1.sources.exec-source1.port = 31313               
                
# Define a logger sink that simply file rolls
# and connect it to the other end of the same channel.
agent1.sinks.fileroll-sink1.channel = ch1
agent1.sinks.fileroll-sink1.type = FILE_ROLL
agent1.sinks.fileroll-sink1.sink.directory =/tmp                
                
# Finally, now that we've defined all of our components, tell
# agent1 which ones we want to activate.
agent1.channels = ch1
agent1.sources = exec-source1
agent1.sinks = fileroll-sink1                
                
# now time to run the script
                
$ flume-ng agent --conf ./flumeconf/ -f ./flumeconf/hdfs2dbloadfile.conf -n 
agent1                
                
# here is the output file
# don't forget to stop flume - it will keep polling by default and generate
# more files
                
$ cat /tmp/1344780561160-1 
1007,2008-05-31,117,null,n,278693    ,2008-06-05,125.90,25.20,null
1008,2008-06-07,110,closed Monday ,y,LZ230     ,2008-07-06,45.60,13.80,2008-07-21
1009,2008-06-14,111,next door to  ,n,4745      ,2008-06-21,20.40,10.00,2008-08-21
1010,2008-06-17,115,deliver 776 King St. if no answer       ,n,429Q      
,2008-06-29,40.60,12.30,2008-08-22
1011,2008-06-18,104,express     ,n,B77897    ,2008-07-03,10.40,5.00,2008-08-29
1012,2008-06-18,117,null,n,278701    ,2008-06-29,70.80,14.20,null
                
# jump over to dbaccess and use the greatest
# data loader in informix: the external table
# external tables were actually developed for 
# informix XPS back in the 1996 timeframe
# and are now available in may servers
                
# 
drop table eorders;
create external table eorders
(on char(10),
mydate char(18),
foo char(18),
bar char(18),
f4 char(18),
f5 char(18),
f6 char(18),
f7 char(18),
f8 char(18),
f9 char(18)
)
using (datafiles ("disk:/tmp/myfoo" ) , delimiter ",");
select * from eorders;

Oozie - thêm luồng công việc cho nhiều tác vụ

Oozie sẽ xâu chuỗi nhiều tác vụ của Hadoop với nhau. Có một tập hợp các ví dụ hấp dẫn kèm theo oozie, đã được dùng trong đoạn mã được hiển thị trong Liệt kê 22.

Liệt kê 22. Kiểm soát tác vụ bằng oozie
# This sample is for CDH3
		
# untar the examples
		
# CDH4
$ tar -zxvf /usr/share/doc/oozie-3.1.3+154/oozie-examples.tar.gz
                
# CDH3
$ tar -zxvf /usr/share/doc/oozie-2.3.2+27.19/oozie-examples.tar.gz
                
# cd to the directory where the examples live 
# you MUST put these jobs into the hdfs store to run them
                
$  hadoop fs -put examples examples
                
# start up the oozie server - you need to be the oozie user
# since the oozie user is a non-login id use the following su trick
                
# CDH4
$ sudo su - oozie -s /usr/lib/oozie/bin/oozie-sys.sh start

# CDH3
$ sudo su - oozie -s /usr/lib/oozie/bin/oozie-start.sh 
                
# checkthe status
oozie admin -oozie http://localhost:11000/oozie -status
System mode: NORMAL
                
# some jar housekeeping so oozie can find what it needs
                
$ cp /usr/lib/sqoop/sqoop-1.3.0-cdh3u4.jar examples/apps/sqoop/lib/
$ cp /home/cloudera/Informix_JDBC_Driver/lib/ifxjdbc.jar examples/apps/sqoop/lib/
$ cp /home/cloudera/Informix_JDBC_Driver/lib/ifxjdbcx.jar examples/apps/sqoop/lib/
                
# edit the workflow.xml  file to use your relational database:
                
#################################
<command> import 
--driver com.informix.jdbc.IfxDriver 
--connect jdbc:informix-sqli://192.168.1.143:54321/stores_demo:informixserver=ifx117 
--table orders --username informix --password useyours 
--target-dir /user/${wf:user()}/${examplesRoot}/output-data/sqoop --verbose<command>
#################################
                
# from the directory where you un-tarred the examples file do the following:
                
$ hrmr examples;hput examples examples
                
# now you can run your sqoop job by submitting it to oozie
                
$  oozie job -oozie http://localhost:11000/oozie -config  \
    examples/apps/sqoop/job.properties -run
                
job: 0000000-120812115858174-oozie-oozi-W
                
# get the job status from the oozie server
                
$ oozie job -oozie http://localhost:11000/oozie -info 0000000-120812115858174-oozie-oozi-W
Job ID : 0000000-120812115858174-oozie-oozi-W
-----------------------------------------------------------------------
Workflow Name : sqoop-wf
App Path      : hdfs://localhost:8020/user/cloudera/examples/apps/sqoop/workflow.xml
Status        : SUCCEEDED
Run           : 0
User          : cloudera
Group         : users
Created       : 2012-08-12 16:05
Started       : 2012-08-12 16:05
Last Modified : 2012-08-12 16:05
Ended         : 2012-08-12 16:05
                
Actions
----------------------------------------------------------------------
ID       Status    Ext ID                 Ext Status Err Code  
---------------------------------------------------------------------
0000000-120812115858174-oozie-oozi-W@sqoop-node                               OK
job_201208120930_0005  SUCCEEDED  -         
--------------------------------------------------------------------
                
# how to kill a job may come in useful at some point
                
oozie job -oozie http://localhost:11000/oozie -kill 
0000013-120812115858174-oozie-oozi-W                
                
# job output will be in the file tree 
$ hcat /user/cloudera/examples/output-data/sqoop/part-m-00003
1018,2008-07-10,121,SW corner of Biltmore Mall              ,n,S22942    
,2008-07-13,70.50,20.00,2008-08-06
1019,2008-07-11,122,closed till noon Mondays                 ,n,Z55709    
,2008-07-16,90.00,23.00,2008-08-06
1020,2008-07-11,123,express                                 ,n,W2286     
,2008-07-16,14.00,8.50,2008-09-20
1021,2008-07-23,124,ask for Elaine                          ,n,C3288     
,2008-07-25,40.00,12.00,2008-08-22
1022,2008-07-24,126,express                                 ,n,W9925     
,2008-07-30,15.00,13.00,2008-09-02
1023,2008-07-24,127,no deliveries after 3 p.m.              ,n,KF2961    
,2008-07-30,60.00,18.00,2008-08-22               
                
                
# if you run into this error there is a good chance that your
# database lock file is owned by root
$  oozie job -oozie http://localhost:11000/oozie -config \
examples/apps/sqoop/job.properties -run
                
Error: E0607 : E0607: Other error in operation [<openjpa-1.2.1-r752877:753278 
fatal store error> org.apache.openjpa.persistence.RollbackException: 
The transaction has been rolled back.  See the nested exceptions for 
details on the errors that occurred.], {1}
                
# fix this as follows
$ sudo chown oozie:oozie  /var/lib/oozie/oozie-db/db.lck 
                
# and restart the oozie server
$ sudo su - oozie -s /usr/lib/oozie/bin/oozie-stop.sh 
$ sudo su - oozie -s /usr/lib/oozie/bin/oozie-start.sh

HBase, một kho lưu trữ key-value hiệu năng cao

HBase là một kho lưu trữ key-value hiệu năng cao. Nếu trường hợp sử dụng của bạn cần có khả năng mở rộng quy mô và chỉ cần kiểu giao dịch cơ sở dữ liệu tương đương như các giao dịch giao kết tự động, thì rất có thể HBase là công nghệ cần dùng. HBase không phải là một cơ sở dữ liệu. Tên của nó không thích hợp vì đối với một số người, thuật ngữ base ngụ ý là cơ sở dữ liệu. Nó thực sự làm việc tuyệt vời cho các kho lưu trữ key-value hiệu năng cao. Có một số sự chồng chéo giữa chức năng của HBase, Informix, DB2 và các cơ sở dữ liệu quan hệ khác. Đối với các giao dịch ACID, tuân thủ SQL đầy đủ, và nhiều chỉ mục thì một cơ sở dữ liệu quan hệ truyền thống sẽ là sự lựa chọn hiển nhiên.

Bài tập viết mã cuối cùng này nhằm đem đến sự hiểu biết cơ bản về HBase. Bài tập này được thiết kế đơn giản và hoàn toàn không đại diện cho phạm vi chức năng của HBase. Hãy sử dụng ví dụ này để hiểu một số trong những khả năng cơ bản trong HBase. "HBase, The Definitive Guide" (HBase một hướng dẫn đáng tin cậy) của Lars George, là cuốn sách bắt buộc phải đọc nếu bạn có kế hoạch thực hiện hoặc loại bỏ HBase trong trường hợp sử dụng cụ thể của mình.

Ví dụ cuối cùng, được hiển thị trong Liệt kê 23 và 24, sử dụng giao diện REST được cung cấp với HBase để chèn các cặp khóa-các giá trị vào một bảng HBase. Chạy bài thử nghiệm bằng curl.

Liệt kê 23. Tạo một bảng HBase và chèn vào một hàng
# enter the command line shell for hbase
                
$ hbase shell
HBase Shell; enter 'help<RETURN> for list of supported commands.
Type "exit<RETURN> to leave the HBase Shell
Version 0.90.6-cdh3u4, r, Mon May  7 13:14:00 PDT 2012
                
#  create a table with a single column family
                
hbase(main):001:0> create 'mytable', 'mycolfamily'   
                
# if you get errors from hbase you need to fix the 
# network config
                
# here is a sample of the error:
                
ERROR: org.apache.hadoop.hbase.ZooKeeperConnectionException: HBase 
is able to connect to ZooKeeper but the connection closes immediately. 
This could be a sign that the server has too many connections 
(30 is the default). Consider inspecting your ZK server logs for 
that error and then make sure you are reusing HBaseConfiguration 
as often as you can. See HTable's javadoc for more information.
                
# fix networking:
                
# add the eth0 interface to /etc/hosts with a hostname
                
$ sudo su - 
# ifconfig | grep addr
eth0      Link encap:Ethernet  HWaddr 00:0C:29:8C:C7:70  
inet addr:192.168.1.134  Bcast:192.168.1.255  Mask:255.255.255.0
Interrupt:177 Base address:0x1400 
inet addr:127.0.0.1  Mask:255.0.0.0
[root@myhost ~]# hostname myhost
[root@myhost ~]# echo "192.168.1.134 myhost" >gt; /etc/hosts
[root@myhost ~]# cd /etc/init.d
                
# now that the host and address are defined restart Hadoop
                
[root@myhost init.d]# for i in hadoop*
> do
> ./$i restart
> done
                
# now try table create again:
                
$ hbase shell
HBase Shell; enter 'help<RETURN> for list of supported commands.
Type "exit<RETURN> to leave the HBase Shell
Version 0.90.6-cdh3u4, r, Mon May  7 13:14:00 PDT 2012
                
hbase(main):001:0> create 'mytable' , 'mycolfamily'
0 row(s) in 1.0920 seconds
                
hbase(main):002:0> 
                
# insert a row into the table you created
# use some simple telephone call log data
# Notice that mycolfamily can have multiple cells
# this is very troubling for DBAs at first, but
# you do get used to it
                
hbase(main):001:0>  put 'mytable',  'key123', 'mycolfamily:number','6175551212'
0 row(s) in 0.5180 seconds
hbase(main):002:0>  put 'mytable',  'key123', 'mycolfamily:duration','25'      
                
# now describe and then scan the table
                
hbase(main):005:0> describe 'mytable'
DESCRIPTION                                          ENABLED                    
{NAME => 'mytable', FAMILIES => [{NAME => 'mycolfam true                       
ily', BLOOMFILTER => 'NONE', REPLICATION_SCOPE => '                            
0', COMPRESSION => 'NONE', VERSIONS => '3', TTL =>                             
'2147483647', BLOCKSIZE => '65536', IN_MEMORY => 'f                            
alse', BLOCKCACHE => 'true'}]}                                                 
1 row(s) in 0.2250 seconds                
                
#  notice that timestamps are included
                
hbase(main):007:0> scan 'mytable'
ROW                        COLUMN+CELL    
key123                    column=mycolfamily:duration, 
timestamp=1346868499125, value=25  
key123                    column=mycolfamily:number, 
timestamp=1346868540850, value=6175551212  
1 row(s) in 0.0250 seconds
Liệt kê 24. Sử dụng giao diện REST của Hbase
# HBase includes a REST server
                
$ hbase rest start -p 9393 &
                
# you get a bunch of messages.... 
                
# get the status of the HBase server
                
$ curl http://localhost:9393/status/cluster
                
# lots of output...
# many lines deleted...
                
mytable,,1346866763530.a00f443084f21c0eea4a075bbfdfc292.
stores=1
storefiless=0
storefileSizeMB=0
memstoreSizeMB=0
storefileIndexSizeMB=0
                
# now scan the contents of mytable
                
$ curl http://localhost:9393/mytable/*
                
# lines deleted
12/09/05 15:08:49 DEBUG client.HTable$ClientScanner: 
Finished with scanning at REGION => 
# lines deleted
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<CellSet><Row key="a2V5MTIz">
<Cell timestamp="1346868499125" column="bXljb2xmYW1pbHk6ZHVyYXRpb24=">MjU=</Cell>
<Cell timestamp="1346868540850" column="bXljb2xmYW1pbHk6bnVtYmVy">NjE3NTU1MTIxMg==</Cell>
<Cell timestamp="1346868425844" column="bXljb2xmYW1pbHk6bnVtYmVy">NjE3NTU1MTIxMg==</Cell>
</Row></CellSet>
                
# the values from the REST interface are base64 encoded
$ echo a2V5MTIz | base64 -d
key123
$ echo bXljb2xmYW1pbHk6bnVtYmVy | base64 -d
mycolfamily:number
                
# The table scan above gives the schema needed to insert into the HBase table
                
$ echo RESTinsertedKey | base64
UkVTVGluc2VydGVkS2V5Cg==
                
$ echo 7815551212 | base64
NzgxNTU1MTIxMgo=
                
# add a table entry with a key value of "RESTinsertedKey" and
# a phone number of "7815551212"
                
# note - curl is all on one line
$  curl -H "Content-Type: text/xml" -d '<CellSet>
<Row key="UkVTVGluc2VydGVkS2V5Cg==">
<Cell column="bXljb2xmYW1pbHk6bnVtYmVy">NzgxNTU1MTIxMgo=<Cell>
<Row><CellSet> http://192.168.1.134:9393/mytable/dummykey
                
12/09/05 15:52:34 DEBUG rest.RowResource: POST http://192.168.1.134:9393/mytable/dummykey
12/09/05 15:52:34 DEBUG rest.RowResource: PUT row=RESTinsertedKey\x0A, 
families={(family=mycolfamily, 
keyvalues=(RESTinsertedKey\x0A/mycolfamily:number/9223372036854775807/Put/vlen=11)}
                
# trust, but verify
                
hbase(main):002:0> scan 'mytable'
ROW                  COLUMN+CELL                           
RESTinsertedKey\x0A column=mycolfamily:number,timestamp=1346874754883,value=7815551212\x0A
key123              column=mycolfamily:duration, timestamp=1346868499125, value=25 
key123              column=mycolfamily:number, timestamp=1346868540850, value=6175551212 
2 row(s) in 0.5610 seconds
                
# notice the \x0A at the end of the key and value
# this is the newline generated by the "echo" command
# lets fix that
                
$ printf 8885551212 | base64
ODg4NTU1MTIxMg==
                
$ printf mykey | base64
bXlrZXk=
                
# note - curl statement is all on one line!
curl -H "Content-Type: text/xml" -d '<CellSet><Row key="bXlrZXk=">
<Cell column="bXljb2xmYW1pbHk6bnVtYmVy">ODg4NTU1MTIxMg==<Cell>
<Row><CellSet> 
http://192.168.1.134:9393/mytable/dummykey              
                
# trust but verify
hbase(main):001:0> scan 'mytable'
ROW                   COLUMN+CELL                                   
RESTinsertedKey\x0A column=mycolfamily:number,timestamp=1346875811168,value=7815551212\x0A
key123              column=mycolfamily:duration, timestamp=1346868499125, value=25     
key123              column=mycolfamily:number, timestamp=1346868540850, value=6175551212
mykey               column=mycolfamily:number, timestamp=1346877875638, value=8885551212
3 row(s) in 0.6100 seconds

Kết luận

Hoan hô, bạn đã thực hiện bài này đến cuối cùng rồi, giỏi lắm! Đây chỉ là khởi đầu để hiểu Hadoop và cách nó tương tác với Informix và DB2. Dưới đây là một số gợi ý cho các bước tiếp theo của bạn.

  • Lấy các ví dụ đã trình bày ở trên và sửa lại chúng cho phù hợp với máy chủ của bạn. Bạn sẽ cần sử dụng dữ liệu nhỏ do không có nhiều không gian nhớ trong ảnh ảo.
  • Lấy chứng chỉ Quản trị viên Hadoop. Vào trang Cloudera để biết các khóa học và các thông tin về kỳ kiểm tra.
  • Lấy chứng chỉ Nhà phát triển Hadoop.
  • Khởi động một cụm bằng cách sử dụng ấn bản Cloudera Manager miễn phí.
  • Bắt đầu với IBM Big Sheets chạy trên đỉnh của CDH4.

Tài nguyên

Học tập

Lấy sản phẩm và công nghệ

Thảo luận

  • Hãy tham gia vào cộng đồng My developerWorks. Kết nối với những người sử dụng developerWorks khác trong khi khám phá các blog, các diễn đàn, các nhóm và wiki theo hướng nhà phát triển.

Bình luận

developerWorks: Đăng nhập

Các trường được đánh dấu hoa thị là bắt buộc (*).


Bạn cần một ID của IBM?
Bạn quên định danh?


Bạn quên mật khẩu?
Đổi mật khẩu

Bằng việc nhấn Gửi, bạn đã đồng ý với các điều khoản sử dụng developerWorks Điều khoản sử dụng.

 


Ở lần bạn đăng nhập đầu tiên vào trang developerWorks, một hồ sơ cá nhân của bạn được tạo ra. Thông tin trong bản hồ sơ này (tên bạn, nước/vùng lãnh thổ, và tên cơ quan) sẽ được trưng ra cho mọi người và sẽ đi cùng các nội dung mà bạn đăng, trừ khi bạn chọn việc ẩn tên cơ quan của bạn. Bạn có thể cập nhật tài khoản trên trang IBM bất cứ khi nào.

Thông tin gửi đi được đảm bảo an toàn.

Chọn tên hiển thị của bạn



Lần đầu tiên bạn đăng nhập vào trang developerWorks, một bản trích ngang được tạo ra cho bạn, bạn cần phải chọn một tên để hiển thị. Tên hiển thị của bạn sẽ đi kèm theo các nội dung mà bạn đăng tải trên developerWorks.

Tên hiển thị cần có từ 3 đến 30 ký tự. Tên xuất hiện của bạn phải là duy nhất trên trang Cộng đồng developerWorks và vì lí do an ninh nó không phải là địa chỉ email của bạn.

Các trường được đánh dấu hoa thị là bắt buộc (*).

(Tên hiển thị cần có từ 3 đến 30 ký tự)

Bằng việc nhấn Gửi, bạn đã đồng ý với các điều khoản sử dụng developerWorks Điều khoản sử dụng.

 


Thông tin gửi đi được đảm bảo an toàn.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=70
Zone=Information Management
ArticleID=861824
ArticleTitle=Big Data nguồn mở, Phần 1: Hướng dẫn Hadoop: Tạo ứng dụng Hello World với Java, Pig, Hive, Flume, Fuse, Oozie và Sqoop với Informix, DB2 và MySQL
publish-date=03192013