Apache HBase là tất cả về việc cung cấp cho bạn quyền truy cập ngẫu nhiên, theo thời gian thực, đọc / ghi vào Dữ liệu lớn của bạn, nhưng làm cách nào để bạn có được dữ liệu đó vào HBase một cách hiệu quả ngay từ đầu? Theo trực giác, người dùng mới sẽ cố gắng thực hiện điều đó thông qua các API ứng dụng khách hoặc bằng cách sử dụng công việc MapReduce với TableOutputFormat, nhưng những cách tiếp cận đó đều có vấn đề, như bạn sẽ tìm hiểu bên dưới. Thay vào đó, tính năng tải hàng loạt của HBase dễ sử dụng hơn nhiều và có thể chèn cùng một lượng dữ liệu nhanh hơn.
Bài đăng trên blog này sẽ giới thiệu các khái niệm cơ bản về tính năng tải hàng loạt, trình bày hai trường hợp sử dụng và đề xuất hai ví dụ.
Tổng quan về Tải hàng loạt
Nếu bạn có bất kỳ triệu chứng nào trong số này, tải hàng loạt có lẽ là lựa chọn phù hợp cho bạn:
- Bạn cần chỉnh sửa Kho lưu trữ của mình để sử dụng hầu hết bộ nhớ.
- Bạn cần sử dụng WAL lớn hơn hoặc bỏ qua chúng hoàn toàn.
- Các hàng đợi nén và xếp hàng của bạn lên đến hàng trăm.
- GC của bạn nằm ngoài tầm kiểm soát vì số lượt chèn của bạn nằm trong phạm vi MB.
- Thời gian chờ của bạn vượt ra khỏi SLA khi bạn nhập dữ liệu.
Hầu hết các triệu chứng đó thường được gọi là “cơn đau ngày càng tăng”. Sử dụng tải hàng loạt có thể giúp bạn tránh chúng.
Trong HBase-speak, tải hàng loạt là quá trình chuẩn bị và tải HFiles (định dạng tệp riêng của HBase) trực tiếp vào các Máy chủ Vùng, do đó bỏ qua đường dẫn ghi và loại bỏ hoàn toàn các vấn đề đó. Quá trình này tương tự như ETL và trông giống như sau:
1. Trích xuất dữ liệu từ một nguồn, thường là các tệp văn bản hoặc cơ sở dữ liệu khác. HBase không quản lý phần này của quy trình. Nói cách khác, bạn không thể yêu cầu HBase chuẩn bị HFiles bằng cách đọc trực tiếp chúng từ MySQL - đúng hơn, bạn phải làm điều đó bằng cách của riêng bạn. Ví dụ:bạn có thể chạy mysqldump trên bảng và tải các tệp kết quả lên HDFS hoặc chỉ lấy các tệp nhật ký Apache HTTP của bạn. Trong mọi trường hợp, dữ liệu của bạn cần phải ở HDFS trước khi thực hiện bước tiếp theo.
2. Chuyển dữ liệu thành HFiles. Bước này yêu cầu công việc MapReduce và đối với hầu hết các loại đầu vào, bạn sẽ phải tự viết Bản đồ. Công việc sẽ cần phát ra khóa hàng dưới dạng Khóa và KeyValue, Đặt hoặc Xóa dưới dạng Giá trị. Bộ khử được xử lý bởi HBase; bạn định cấu hình nó bằng HFileOutputFormat.configureIncrementalLoad () và nó thực hiện như sau:
- Kiểm tra bảng để định cấu hình tổng phân vùng đơn đặt hàng
- Tải tệp phân vùng lên cụm và thêm tệp đó vào DistributedCache
- Đặt số lượng nhiệm vụ giảm để phù hợp với số lượng khu vực hiện tại
- Đặt khóa đầu ra / lớp giá trị để phù hợp với yêu cầu của HFileOutputFormat
- Đặt bộ giảm tốc để thực hiện phân loại thích hợp (KeyValueSortReducer hoặc PutSortReducer)
Ở giai đoạn này, một HFile sẽ được tạo cho mỗi vùng trong thư mục đầu ra. Hãy nhớ rằng dữ liệu đầu vào gần như được ghi lại hoàn toàn, vì vậy bạn sẽ cần ít nhất gấp đôi dung lượng ổ đĩa trống so với kích thước của tập dữ liệu gốc. Ví dụ:đối với mysqldump 100GB, bạn phải có ít nhất 200GB dung lượng đĩa trống trong HDFS. Bạn có thể xóa tệp kết xuất khi kết thúc quá trình.
3. Tải các tệp vào HBase bằng cách thông báo cho Máy chủ Vùng tìm chúng ở đâu. Đây là bước đơn giản nhất. Nó yêu cầu sử dụng LoadIncrementalHFiles (thường được gọi là công cụ hoàn chỉnh) và bằng cách chuyển cho nó một URL định vị các tệp trong HDFS, nó sẽ tải từng tệp vào vùng liên quan thông qua RegionServer phục vụ nó. Trong trường hợp một vùng được chia nhỏ sau khi các tệp được tạo, công cụ sẽ tự động chia HFile theo các ranh giới mới. Quy trình này không hiệu quả lắm, vì vậy nếu bảng của bạn hiện đang được ghi bởi các quy trình khác, thì tốt nhất là bạn nên tải tệp ngay sau khi hoàn tất bước chuyển đổi.
Dưới đây là một minh họa về quá trình này. Luồng dữ liệu đi từ nguồn ban đầu đến HDFS, nơi Máy chủ vùng sẽ chỉ cần di chuyển tệp đến thư mục của vùng của chúng.
Các trường hợp sử dụng
Tải tập dữ liệu ban đầu: Tất cả người dùng di chuyển từ một kho dữ liệu khác nên xem xét trường hợp sử dụng này. Đầu tiên, bạn phải trải qua bài tập thiết kế lược đồ bảng sau đó tự tạo bảng, tách trước. Các điểm phân tách phải xem xét đến sự phân bố khóa hàng và số lượng Máy chủ Vùng. Tôi khuyên bạn nên đọc bản trình bày của đồng nghiệp Lars George của tôi về thiết kế giản đồ nâng cao cho bất kỳ trường hợp sử dụng nghiêm trọng nào.
Ưu điểm ở đây là việc ghi tệp trực tiếp nhanh hơn nhiều so với việc đi qua đường dẫn ghi của RegionServer (ghi vào cả MemStore và WAL) và sau đó xả, nén, v.v. Điều đó cũng có nghĩa là bạn không phải điều chỉnh cụm của mình cho một khối lượng công việc nhiều ghi và sau đó điều chỉnh lại cho khối lượng công việc bình thường của bạn.
Tải trọng gia tăng: Giả sử bạn có một số tập dữ liệu hiện đang được HBase cung cấp, nhưng bây giờ bạn cần nhập thêm hàng loạt dữ liệu từ bên thứ ba hoặc bạn có công việc hàng đêm tạo ra một vài gigabyte mà bạn cần chèn. Nó có thể không lớn bằng tập dữ liệu mà HBase đang phân phối, nhưng nó có thể ảnh hưởng đến phân vị thứ 95 của độ trễ của bạn. Đi qua đường dẫn ghi thông thường sẽ có tác dụng bất lợi là kích hoạt nhiều lần gửi và giao dịch trong quá trình nhập hơn bình thường. Ứng suất IO bổ sung này sẽ cạnh tranh với các truy vấn nhạy cảm với độ trễ của bạn.
Ví dụ
Bạn có thể sử dụng các ví dụ sau trong cụm Hadoop của riêng mình nhưng các hướng dẫn được cung cấp cho Cloudera QuickStart VM, là một cụm nút đơn, hệ điều hành khách và dữ liệu mẫu và ví dụ được đưa vào một thiết bị máy ảo cho máy tính để bàn của bạn.
Khi bạn khởi động VM, hãy thông báo cho nó biết, thông qua giao diện web sẽ tự động mở, để triển khai CDH và sau đó đảm bảo rằng dịch vụ HBase cũng được khởi động.
Trình tải hàng loạt TSV được tích hợp sẵn
HBase cung cấp một công việc MR có thể đọc tệp giá trị được phân tách bằng dấu phân cách và xuất trực tiếp vào bảng HBase hoặc tạo HFiles để tải hàng loạt. Ở đây chúng ta sẽ:
- Lấy dữ liệu mẫu và tải dữ liệu đó lên HDFS.
- Chạy công việc ImportTsv để chuyển đổi tệp thành nhiều HFiles theo một bảng được định cấu hình trước.
- Chuẩn bị và tải các tệp trong HBase.
Bước đầu tiên là mở bảng điều khiển và sử dụng lệnh sau để lấy dữ liệu mẫu:
curl -O https://people.apache.org/~jdcryans/word_count.csv
Tôi đã tạo tệp này bằng cách chạy đếm từ trên bản thảo gốc của bài đăng blog này và sau đó xuất ra kết quả ở định dạng csv, không có bất kỳ tiêu đề cột nào. Bây giờ, hãy tải tệp lên HDFS:
hdfs dfs -put word_count.csv
Phần trích xuất của tải hàng loạt hiện đã hoàn tất, bạn cần phải chuyển đổi tệp. Đầu tiên bạn cần thiết kế bảng. Để đơn giản hóa mọi thứ, hãy gọi nó là “wordcount” - các phím hàng sẽ là các từ và cột duy nhất sẽ chứa số, trong một họ mà chúng tôi sẽ gọi là “f”. Thực tiễn tốt nhất khi tạo bảng là chia bảng theo phân phối khóa hàng nhưng đối với ví dụ này, chúng tôi sẽ chỉ tạo năm vùng với các điểm phân tách trải đều trên không gian khóa. Mở trình bao hbase:
hbase shell
Và chạy lệnh sau để tạo bảng:
create 'wordcount', {NAME => 'f'}, {SPLITS => ['g', 'm', 'r', 'w']}
Bốn điểm phân tách sẽ tạo ra năm vùng, trong đó vùng đầu tiên bắt đầu bằng một phím hàng trống. Để có được các điểm phân tách tốt hơn, bạn cũng có thể thực hiện phân tích nhanh để xem các từ được phân bổ thực sự như thế nào, nhưng tôi sẽ để điều đó tùy thuộc vào bạn.
Nếu bạn trỏ trình duyệt máy ảo của mình tới http:// localhost:60010 /, bạn sẽ thấy bảng mới được tạo của chúng tôi và năm vùng của nó đều được gán cho Máy chủ vùng.
Bây giờ đã đến lúc thực hiện công việc nặng nhọc. Gọi jar HBase trên dòng lệnh với tập lệnh “hadoop” sẽ hiển thị danh sách các công cụ có sẵn. Cái mà chúng tôi muốn có tên là importtsv và có cách sử dụng như sau:
hadoop jar /usr/lib/hbase/hbase-0.94.6-cdh4.3.0-security.jar importtsv ERROR: Wrong number of arguments: 0 Usage: importtsv -Dimporttsv.columns=a,b,c
Dòng lệnh chúng ta sẽ sử dụng là dòng lệnh sau:
hadoop jar /usr/lib/hbase/hbase-0.94.6-cdh4.3.0- security.jar importtsv -Dimporttsv.separator=, -Dimporttsv.bulk.output=output -Dimporttsv.columns=HBASE_ROW_KEY,f:count wordcount word_count.csv
Dưới đây là tóm tắt về các phần tử cấu hình khác nhau:
- -Dimporttsv.separator =, chỉ định rằng dấu phân cách là dấu phẩy.
- -Dimporttsv.bulk.output =đầu ra là một đường dẫn tương đối đến nơi các tệp HF sẽ được viết. Vì người dùng của bạn trên VM là “cloudera” theo mặc định, điều đó có nghĩa là các tệp sẽ nằm trong / user / cloudera / output. Bỏ qua tùy chọn này sẽ khiến công việc được ghi trực tiếp lên HBase.
- -Dimporttsv.columns =HBASE_ROW_KEY, f:count là danh sách tất cả các cột có trong tệp này. Khóa hàng cần được xác định bằng cách sử dụng chuỗi HBASE_ROW_KEY viết hoa toàn bộ; nếu không nó sẽ không bắt đầu công việc. (Tôi đã quyết định sử dụng từ "đếm" nhưng nó có thể là bất kỳ thứ gì khác.)
Công việc sẽ hoàn thành trong vòng một phút, với kích thước đầu vào nhỏ. Lưu ý rằng năm Bộ giảm tốc đang chạy, một Bộ giảm tốc cho mỗi vùng. Đây là kết quả trên HDFS:
-rw-r--r-- 3 cloudera cloudera 4265 2013-09-12 13:13 output/f/2c0724e0c8054b70bce11342dc91897b -rw-r--r-- 3 cloudera cloudera 3163 2013-09-12 13:14 output/f/786198ca47ae406f9be05c9eb09beb36 -rw-r--r-- 3 cloudera cloudera 2487 2013-09-12 13:14 output/f/9b0e5b2a137e479cbc978132e3fc84d2 -rw-r--r-- 3 cloudera cloudera 2961 2013-09-12 13:13 output/f/bb341f04c6d845e8bb95830e9946a914 -rw-r--r-- 3 cloudera cloudera 1336 2013-09-12 13:14 output/f/c656d893bd704260a613be62bddb4d5f
Như bạn có thể thấy, các tệp hiện thuộc về người dùng “cloudera”. Để tải chúng, chúng tôi cần thay đổi chủ sở hữu thành “hbase” nếu không HBase sẽ không có quyền di chuyển tệp. Chạy lệnh sau:
sudo -u hdfs hdfs dfs -chown -R hbase:hbase/user/cloudera/output
Đối với bước cuối cùng, chúng ta cần sử dụng công cụ completebulkload để trỏ đến vị trí của tệp và bảng chúng ta đang tải đến:
hbase org.apache.hadoop.hbase.mapreduce.LoadIncrementalHFiles output wordcount
Quay trở lại trình bao HBase, bạn có thể chạy lệnh đếm sẽ hiển thị cho bạn số hàng đã được tải. Nếu bạn quên cắt, lệnh sẽ bị treo.
Công việc MR tùy chỉnh
Trình tải hàng loạt TSV rất tốt cho việc tạo mẫu, nhưng vì nó diễn giải mọi thứ dưới dạng chuỗi và không hỗ trợ thao tác các trường tại thời điểm chuyển đổi, bạn sẽ phải viết công việc MR của riêng mình. Đồng nghiệp của tôi James Kinley, người làm việc như một kiến trúc sư giải pháp ở châu Âu, đã viết một công việc mà chúng tôi sẽ sử dụng cho ví dụ tiếp theo của chúng tôi. Dữ liệu cho công việc chứa các tin nhắn Facebook và Twitter công khai liên quan đến trận chung kết NBA 2010 (trận 1) giữa Lakers và Celtics. Bạn có thể tìm thấy mã ở đây. (Máy ảo Quick Start đi kèm với git và maven được cài đặt để bạn có thể sao chép kho lưu trữ trên đó.)
Nhìn vào lớp Trình điều khiển, các bit quan trọng nhất là sau:
job.setMapOutputKeyClass(ImmutableBytesWritable.class); job.setMapOutputValueClass(KeyValue.class); … // Auto configure partitioner and reducer HFileOutputFormat.configureIncrementalLoad(job, hTable);
Đầu tiên, Mapper của bạn cần xuất ra một ImmutableBytesW ghi có chứa khóa hàng và giá trị đầu ra có thể là KeyValue, Put hoặc Delete. Đoạn mã thứ hai cho thấy cách định cấu hình Hộp giảm tốc; trên thực tế nó hoàn toàn được xử lý bởi HFileOutputFormat. configIncrementalLoad () như được mô tả trong phần “Transform” trước đây.
Lớp HBaseKVMapper chỉ chứa Mapper tôn trọng các giá trị và khóa đầu ra đã định cấu hình:
public class HBaseKVMapper extends Mapper<LongWritable, Text, ImmutableBytesWritable, KeyValue> {
Để chạy nó, bạn sẽ cần phải biên dịch dự án bằng maven và lấy các tệp dữ liệu theo các liên kết trong README. (Nó cũng chứa tập lệnh shell để tạo bảng.) Trước khi bắt đầu công việc, đừng quên tải các tệp lên HDFS và đặt classpath của bạn để biết HBase vì lần này bạn sẽ không sử dụng jar của nó. :
export HADOOP_CLASSPATH=$HADOOP_CLASSPATH:/etc/hbase/conf/:/usr/lib/hbase/*
Bạn sẽ có thể bắt đầu công việc bằng dòng lệnh tương tự như dòng lệnh sau:
hadoop jar hbase-examples-0.0.1-SNAPSHOT.jar com.cloudera.examples.hbase.bulkimport.Driver -libjars /home/cloudera/.m2/repository/joda-time/joda-time/2.1/joda-time-2.1.jar, /home/cloudera/.m2/repository/net/sf/opencsv/opencsv/2.3/opencsv-2.3.jar RowFeeder\ for\ Celtics\ and\ Lakers\ Game\ 1.csv output2 NBAFinal2010
Như bạn có thể thấy, các phần phụ thuộc của công việc phải được thêm riêng. Cuối cùng, bạn có thể tải các tệp bằng cách thay đổi chủ sở hữu của chúng trước tiên và sau đó chạy công cụ tải tệp hoàn chỉnh:
sudo -u hdfs hdfs dfs -chown -R hbase:hbase/user/cloudera/output2 hbase org.apache.hadoop.hbase.mapreduce.LoadIncrementalHFiles output2 NBAFinal2010
Các vấn đề tiềm ẩn
Dữ liệu đã xóa gần đây xuất hiện lại. Sự cố này xảy ra khi một Xóa được chèn qua tải hàng loạt và được nén lớn trong khi Đặt tương ứng vẫn ở trong Kho lưu trữ. Dữ liệu sẽ được coi là bị xóa khi Xóa nằm trong HFile, nhưng khi nó bị xóa trong quá trình nén, Lệnh sẽ hiển thị trở lại. Nếu bạn gặp trường hợp sử dụng như vậy, hãy xem xét định cấu hình họ cột của bạn để giữ các ô đã xóa bằng KEEP_DELETED_CELLS trong shell hoặc HColumnDescriptor.setKeepDeletedCells ().
Dữ liệu được tải hàng loạt không thể bị ghi đè bởi một tải hàng loạt khác. Sự cố này xảy ra khi hai tệp HF được tải hàng loạt được tải vào các thời điểm khác nhau cố gắng ghi một giá trị khác nhau trong cùng một ô, nghĩa là chúng có cùng một khóa hàng, họ, bộ định lượng và dấu thời gian. Kết quả là giá trị được chèn đầu tiên sẽ được trả về thay vì giá trị thứ hai. Lỗi này sẽ được sửa trong HBase 0.96.0 và CDH 5 (phiên bản chính CDH tiếp theo) và công việc đang được thực hiện trong HBASE-8521 cho nhánh 0.94 và CDH 4.
Tải hàng loạt kích hoạt các giao dịch chính. Vấn đề này xuất hiện khi bạn đang thực hiện tải hàng loạt gia tăng và có đủ tệp được tải hàng loạt để kích hoạt một lần nén nhỏ (ngưỡng mặc định là 3). Các HFiles được tải với số thứ tự được đặt thành 0 để chúng được chọn đầu tiên khi Máy chủ vùng đang chọn tệp để nén và do một lỗi, nó cũng sẽ chọn tất cả các tệp còn lại. Sự cố này sẽ ảnh hưởng nghiêm trọng đến những người đã có nhiều khu vực lớn (nhiều GB) hoặc những người tải hàng loạt thường xuyên (vài giờ một lần và ít hơn) vì nhiều dữ liệu sẽ bị nén. HBase 0.96.0 có bản sửa lỗi thích hợp và CDH 5 cũng vậy; HBASE-8521 khắc phục sự cố trong 0,94 vì các HFiles được tải hàng loạt hiện được gán một số thứ tự thích hợp. HBASE-8283 có thể được bật với hbase.hstore.useExploringCompation sau 0.94.9 và CDH 4.4.0 để giảm thiểu vấn đề này bằng cách chỉ là một thuật toán lựa chọn nén thông minh hơn.
Dữ liệu được tải hàng loạt không được sao chép . Khi tải hàng loạt bỏ qua đường dẫn ghi, WAL không được ghi vào như một phần của quy trình. Tính năng sao chép hoạt động bằng cách đọc các tệp WAL vì vậy nó sẽ không nhìn thấy dữ liệu được tải hàng loạt - và điều này cũng xảy ra với các chỉnh sửa sử dụng Put.setWriteToWAL (true). Một cách để xử lý điều đó là chuyển các tệp thô hoặc HFiles đến cụm khác và thực hiện các xử lý khác ở đó.
Kết luận
Mục tiêu của bài đăng trên blog này là giới thiệu cho bạn các khái niệm cơ bản về tải hàng loạt của Apache HBase. Chúng tôi đã giải thích quy trình giống như thực hiện ETL và nó tốt hơn nhiều cho các tập dữ liệu lớn so với việc sử dụng API thông thường vì nó bỏ qua đường dẫn ghi. Hai ví dụ đã được đưa vào để cho thấy cách các tệp TSV đơn giản có thể được tải hàng loạt vào HBase và cách viết Mapper của riêng bạn cho các định dạng dữ liệu khác.
Bây giờ, bạn có thể thử làm điều tương tự bằng giao diện người dùng đồ họa qua Hue.