Lý thuyết và thực hành sử dụng HBase

Chào buổi chiều Tên tôi là Danil Lipovoy, nhóm của chúng tôi tại Sbertech đã bắt đầu sử dụng HBase làm nơi lưu trữ dữ liệu vận hành. Trong quá trình nghiên cứu nó, kinh nghiệm đã tích lũy được mà tôi muốn hệ thống hóa và mô tả (chúng tôi hy vọng rằng nó sẽ hữu ích cho nhiều người). Tất cả các thử nghiệm bên dưới được thực hiện với phiên bản HBase 1.2.0-cdh5.14.2 và 2.0.0-cdh6.0.0-beta1.

  1. Kiến trúc tổng thể
  2. Ghi dữ liệu vào HBASE
  3. Đọc dữ liệu từ HBASE
  4. Bộ nhớ đệm dữ liệu
  5. Xử lý dữ liệu hàng loạt MultiGet/MultiPut
  6. Chiến lược chia bảng thành các vùng (split)
  7. Khả năng chịu lỗi, nén và định vị dữ liệu
  8. Cài đặt và hiệu suất
  9. Bài kiểm tra về áp lực
  10. Những phát hiện

1. Kiến trúc tổng thể

Lý thuyết và thực hành sử dụng HBase
Master dự phòng lắng nghe nhịp tim của nút đang hoạt động trên nút ZooKeeper và trong trường hợp biến mất, nó sẽ đảm nhận các chức năng của master.

2. Ghi dữ liệu vào HBASE

Trước tiên, hãy xem trường hợp đơn giản nhất - viết một đối tượng khóa-giá trị vào bảng bằng cách sử dụng put(rowkey). Trước tiên, máy khách phải tìm ra vị trí của Máy chủ vùng gốc (RRS), nơi lưu trữ bảng hbase:meta. Anh ấy nhận được thông tin này từ ZooKeeper. Sau đó, nó truy cập RRS và đọc bảng hbase:meta, từ đó nó trích xuất thông tin về RegionServer (RS) nào chịu trách nhiệm lưu trữ dữ liệu cho một khóa hàng nhất định trong bảng quan tâm. Để sử dụng trong tương lai, bảng meta được máy khách lưu vào bộ nhớ đệm và do đó các cuộc gọi tiếp theo sẽ diễn ra nhanh hơn, trực tiếp tới RS.

Tiếp theo, RS, sau khi nhận được yêu cầu, trước hết sẽ ghi nó vào WriteAheadLog (WAL), cần thiết để khôi phục trong trường hợp xảy ra sự cố. Sau đó lưu dữ liệu vào MemStore. Đây là bộ đệm trong bộ nhớ chứa tập hợp các khóa được sắp xếp cho một vùng nhất định. Một bảng có thể được chia thành các vùng (phân vùng), mỗi vùng chứa một bộ khóa riêng biệt. Điều này cho phép bạn đặt các vùng trên các máy chủ khác nhau để đạt được hiệu suất cao hơn. Tuy nhiên, bất chấp sự hiển nhiên của tuyên bố này, sau này chúng ta sẽ thấy rằng điều này không đúng trong mọi trường hợp.

Sau khi đặt một mục vào MemStore, một phản hồi sẽ được trả về cho khách hàng rằng mục đó đã được lưu thành công. Tuy nhiên, trên thực tế, nó chỉ được lưu trữ trong bộ đệm và chỉ được đưa vào đĩa sau một khoảng thời gian nhất định hoặc khi nó chứa đầy dữ liệu mới.

Lý thuyết và thực hành sử dụng HBase
Khi thực hiện thao tác “Xóa”, dữ liệu sẽ không bị xóa về mặt vật lý. Chúng được đánh dấu đơn giản là đã xóa và việc hủy bỏ xảy ra tại thời điểm gọi hàm rút gọn chính, được mô tả chi tiết hơn trong đoạn 7.

Các tệp ở định dạng HFile được tích lũy trong HDFS và đôi khi quy trình thu gọn nhỏ được khởi chạy, quy trình này chỉ đơn giản là hợp nhất các tệp nhỏ thành tệp lớn hơn mà không xóa bất kỳ thứ gì. Theo thời gian, điều này trở thành một vấn đề chỉ xuất hiện khi đọc dữ liệu (chúng ta sẽ quay lại vấn đề này sau).

Ngoài quá trình tải được mô tả ở trên, còn có một quy trình hiệu quả hơn nhiều, có lẽ là mặt mạnh nhất của cơ sở dữ liệu này - BulkLoad. Thực tế là chúng tôi tạo HFiles một cách độc lập và đưa chúng vào đĩa, điều này cho phép chúng tôi mở rộng quy mô một cách hoàn hảo và đạt được tốc độ rất tốt. Trên thực tế, hạn chế ở đây không phải là HBase mà là khả năng của phần cứng. Dưới đây là kết quả khởi động trên một cụm bao gồm 16 RegionServers và 16 NodeManager YARN (CPU Xeon E5-2680 v4 @ 2.40GHz * 64 thread), phiên bản HBase 1.2.0-cdh5.14.2.

Lý thuyết và thực hành sử dụng HBase

Ở đây bạn có thể thấy rằng bằng cách tăng số lượng phân vùng (vùng) trong bảng, cũng như trình thực thi Spark, chúng ta sẽ tăng tốc độ tải xuống. Ngoài ra, tốc độ còn phụ thuộc vào âm lượng ghi. Các khối lớn làm tăng MB/giây, các khối nhỏ về số lượng bản ghi được chèn trên một đơn vị thời gian, tất cả những thứ khác đều bằng nhau.

Bạn cũng có thể bắt đầu tải vào hai bảng cùng lúc và đạt tốc độ gấp đôi. Dưới đây bạn có thể thấy rằng việc ghi các khối 10 KB vào hai bảng cùng một lúc xảy ra với tốc độ khoảng 600 MB/giây trong mỗi bảng (tổng cộng 1275 MB/giây), trùng với tốc độ ghi vào một bảng là 623 MB/giây (xem số 11 ở trên)

Lý thuyết và thực hành sử dụng HBase
Nhưng lần chạy thứ hai với bản ghi 50 KB cho thấy tốc độ tải xuống đang tăng nhẹ, điều này cho thấy nó đang tiến gần đến giá trị giới hạn. Đồng thời, bạn cần lưu ý rằng thực tế không có tải nào được tạo trên chính HBASE, tất cả những gì cần thiết trước tiên là cung cấp dữ liệu từ hbase:meta và sau khi xếp HFiles, hãy đặt lại dữ liệu BlockCache và lưu Bộ đệm MemStore vào đĩa, nếu nó không trống.

3. Đọc dữ liệu từ HBASE

Nếu chúng tôi giả định rằng máy khách đã có tất cả thông tin từ hbase:meta (xem điểm 2), thì yêu cầu sẽ chuyển trực tiếp đến RS nơi lưu trữ khóa bắt buộc. Đầu tiên, việc tìm kiếm được thực hiện trong MemCache. Bất kể có dữ liệu ở đó hay không, việc tìm kiếm cũng được thực hiện trong bộ đệm BlockCache và nếu cần, trong HFiles. Nếu dữ liệu được tìm thấy trong tệp, nó sẽ được đặt trong BlockCache và sẽ được trả về nhanh hơn trong yêu cầu tiếp theo. Tìm kiếm trong HFile tương đối nhanh nhờ sử dụng bộ lọc Bloom, tức là. Sau khi đọc một lượng nhỏ dữ liệu, nó sẽ ngay lập tức xác định xem tệp này có chứa khóa cần thiết hay không và nếu không thì chuyển sang tệp tiếp theo.

Lý thuyết và thực hành sử dụng HBase
Sau khi nhận được dữ liệu từ ba nguồn này, RS sẽ tạo ra phản hồi. Đặc biệt, nó có thể chuyển một số phiên bản tìm thấy của một đối tượng cùng một lúc nếu khách hàng yêu cầu phiên bản.

4. Bộ nhớ đệm dữ liệu

Bộ đệm MemStore và BlockCache chiếm tới 80% bộ nhớ RS trên heap được phân bổ (phần còn lại được dành riêng cho các tác vụ dịch vụ RS). Nếu chế độ sử dụng thông thường là các quá trình ghi và đọc ngay lập tức cùng một dữ liệu, thì việc giảm BlockCache và tăng MemStore là hợp lý, bởi vì Khi việc ghi dữ liệu không vào được cache để đọc thì BlockCache sẽ ít được sử dụng hơn. Bộ đệm BlockCache bao gồm hai phần: LruBlockCache (luôn ở trên heap) và BucketCache (thường ở ngoài heap hoặc trên ổ SSD). BucketCache nên được sử dụng khi có nhiều yêu cầu đọc và chúng không phù hợp với LruBlockCache, dẫn đến Garbage Collector hoạt động tích cực. Đồng thời, bạn không nên mong đợi hiệu suất tăng lên đáng kể khi sử dụng bộ đệm đọc, nhưng chúng tôi sẽ quay lại vấn đề này trong đoạn 8

Lý thuyết và thực hành sử dụng HBase
Có một BlockCache cho toàn bộ RS và có một MemStore cho mỗi bảng (một cho mỗi Column Family).

làm sao mô tả về lý thuyết, khi ghi, dữ liệu không đi vào bộ đệm và thực tế, các tham số CACHE_DATA_ON_WRITE cho bảng và “Cache DATA on Write” cho RS được đặt thành false. Tuy nhiên, trong thực tế, nếu chúng ta ghi dữ liệu vào MemStore, sau đó xóa nó vào đĩa (do đó xóa nó), sau đó xóa tệp kết quả, thì bằng cách thực hiện yêu cầu get, chúng ta sẽ nhận được dữ liệu thành công. Hơn nữa, ngay cả khi bạn tắt hoàn toàn BlockCache và điền dữ liệu mới vào bảng, sau đó đặt lại MemStore vào đĩa, xóa chúng và yêu cầu chúng từ một phiên khác, chúng vẫn sẽ được truy xuất từ ​​đâu đó. Vì vậy HBase không chỉ lưu trữ dữ liệu mà còn lưu trữ cả những bí ẩn bí ẩn.

hbase(main):001:0> create 'ns:magic', 'cf'
Created table ns:magic
Took 1.1533 seconds
hbase(main):002:0> put 'ns:magic', 'key1', 'cf:c', 'try_to_delete_me'
Took 0.2610 seconds
hbase(main):003:0> flush 'ns:magic'
Took 0.6161 seconds
hdfs dfs -mv /data/hbase/data/ns/magic/* /tmp/trash
hbase(main):002:0> get 'ns:magic', 'key1'
 cf:c      timestamp=1534440690218, value=try_to_delete_me

Tham số "Cache DATA on Read" được đặt thành false. Nếu bạn có bất kỳ ý tưởng nào, vui lòng thảo luận trong phần bình luận.

5. Xử lý dữ liệu hàng loạt MultiGet/MultiPut

Xử lý các yêu cầu đơn lẻ (Nhận/Đặt/Xóa) là một thao tác khá tốn kém, vì vậy nếu có thể, bạn nên kết hợp chúng thành Danh sách hoặc Danh sách, điều này cho phép bạn tăng hiệu suất đáng kể. Điều này đặc biệt đúng đối với thao tác ghi, nhưng khi đọc lại có cạm bẫy sau. Biểu đồ bên dưới hiển thị thời gian đọc 50 bản ghi từ MemStore. Việc đọc được thực hiện trong một luồng và trục ngang hiển thị số lượng khóa trong yêu cầu. Ở đây bạn có thể thấy rằng khi tăng lên một nghìn khóa trong một yêu cầu, thời gian thực hiện sẽ giảm xuống, tức là. tốc độ tăng lên. Tuy nhiên, với chế độ MSLAB được bật theo mặc định, sau ngưỡng này, hiệu suất sẽ bắt đầu giảm đáng kể và lượng dữ liệu trong bản ghi càng lớn thì thời gian hoạt động càng lâu.

Lý thuyết và thực hành sử dụng HBase

Các thử nghiệm được thực hiện trên máy ảo, 8 lõi, phiên bản HBase 2.0.0-cdh6.0.0-beta1.

Chế độ MSLAB được thiết kế để giảm sự phân mảnh vùng heap, xảy ra do trộn lẫn dữ liệu thế hệ mới và cũ. Như một giải pháp thay thế, khi bật MSLAB, dữ liệu sẽ được đặt vào các ô tương đối nhỏ (khối) và được xử lý theo khối. Kết quả là khi dung lượng trong gói dữ liệu được yêu cầu vượt quá kích thước được phân bổ, hiệu suất sẽ giảm mạnh. Mặt khác, việc tắt chế độ này cũng là điều không nên làm vì nó sẽ dẫn đến tình trạng dừng do GC trong những thời điểm xử lý dữ liệu chuyên sâu. Một giải pháp tốt là tăng âm lượng ô trong trường hợp hoạt động ghi thông qua put cùng lúc với việc đọc. Cần lưu ý rằng sự cố sẽ không xảy ra nếu sau khi ghi, bạn chạy lệnh xóa để đặt lại MemStore vào đĩa hoặc nếu bạn tải bằng BulkLoad. Bảng bên dưới cho thấy rằng các truy vấn từ MemStore đối với dữ liệu lớn hơn (và cùng số lượng) sẽ dẫn đến tình trạng chậm lại. Tuy nhiên, bằng cách tăng kích thước chunk, chúng tôi sẽ đưa thời gian xử lý trở lại bình thường.

Lý thuyết và thực hành sử dụng HBase
Ngoài việc tăng kích thước khối, việc chia nhỏ dữ liệu theo vùng sẽ giúp ích, tức là. chia bảng. Điều này dẫn đến ít yêu cầu đến từng khu vực hơn và nếu chúng phù hợp với một ô thì phản hồi vẫn tốt.

6. Chiến lược chia bảng thành các vùng (split)

Vì HBase là nơi lưu trữ khóa-giá trị và việc phân vùng được thực hiện bằng khóa nên việc chia đều dữ liệu cho tất cả các vùng là cực kỳ quan trọng. Ví dụ: việc phân vùng một bảng như vậy thành ba phần sẽ dẫn đến dữ liệu được chia thành ba vùng:

Lý thuyết và thực hành sử dụng HBase
Điều này xảy ra là điều này sẽ dẫn đến tình trạng chậm lại đáng kể nếu dữ liệu được tải sau đó trông giống như các giá trị dài, chẳng hạn như hầu hết chúng đều bắt đầu bằng cùng một chữ số, chẳng hạn:

1000001
1000002
...
1100003

Vì các khóa được lưu trữ dưới dạng mảng byte nên tất cả chúng sẽ bắt đầu giống nhau và thuộc cùng một vùng số 1 lưu trữ phạm vi khóa này. Có một số chiến lược phân vùng:

HexStringSplit – Biến khóa thành chuỗi được mã hóa thập lục phân trong phạm vi "00000000" => "FFFFFFFF" và đệm ở bên trái bằng số XNUMX.

Thống nhấtSplit – Biến khóa thành một mảng byte với mã hóa thập lục phân trong phạm vi "00" => "FF" và đệm ở bên phải bằng số XNUMX.

Ngoài ra, bạn có thể chỉ định bất kỳ phạm vi hoặc bộ khóa nào để phân tách và định cấu hình tự động phân tách. Tuy nhiên, một trong những cách tiếp cận đơn giản và hiệu quả nhất là UnitySplit và sử dụng phép nối băm, ví dụ: cặp byte quan trọng nhất từ ​​việc chạy khóa thông qua hàm CRC32(rowkey) và chính khóa hàng đó:

hàm băm + phím hàng

Khi đó tất cả dữ liệu sẽ được phân bổ đều giữa các khu vực. Khi đọc, hai byte đầu tiên sẽ bị loại bỏ và khóa gốc vẫn còn. RS cũng kiểm soát lượng dữ liệu và khóa trong vùng và nếu vượt quá giới hạn, nó sẽ tự động chia dữ liệu thành nhiều phần.

7. Khả năng chịu lỗi và vị trí dữ liệu

Vì chỉ có một khu vực chịu trách nhiệm cho mỗi bộ khóa nên giải pháp cho các vấn đề liên quan đến sự cố hoặc ngừng hoạt động của RS là lưu trữ tất cả dữ liệu cần thiết trong HDFS. Khi RS rơi, máy chủ sẽ phát hiện điều này thông qua việc không có nhịp tim trên nút ZooKeeper. Sau đó, nó chỉ định vùng được phục vụ cho một RS khác và vì các HFiles được lưu trữ trong hệ thống tệp phân tán nên chủ sở hữu mới sẽ đọc chúng và tiếp tục phục vụ dữ liệu. Tuy nhiên, vì một số dữ liệu có thể nằm trong MemStore và không có thời gian để vào HFiles, nên WAL, cũng được lưu trữ trong HDFS, được sử dụng để khôi phục lịch sử hoạt động. Sau khi các thay đổi được áp dụng, RS có thể phản hồi các yêu cầu, nhưng động thái này dẫn đến thực tế là một số dữ liệu và quy trình phục vụ chúng kết thúc ở các nút khác nhau, tức là. địa phương ngày càng giảm.

Giải pháp cho vấn đề là nén chặt - quy trình này di chuyển các tệp đến các nút chịu trách nhiệm về chúng (nơi đặt vùng của chúng), do đó trong quy trình này, tải trên mạng và đĩa tăng mạnh. Tuy nhiên, trong tương lai, việc truy cập dữ liệu sẽ được tăng tốc rõ rệt. Ngoài ra, Major_compaction thực hiện việc hợp nhất tất cả các HFiles thành một tệp trong một vùng và cũng xóa dữ liệu tùy thuộc vào cài đặt bảng. Ví dụ: bạn có thể chỉ định số lượng phiên bản của một đối tượng phải được giữ lại hoặc thời gian tồn tại sau đó đối tượng đó sẽ bị xóa về mặt vật lý.

Quy trình này có thể có tác động rất tích cực đến hoạt động của HBase. Hình ảnh bên dưới cho thấy hiệu suất bị suy giảm như thế nào do việc ghi dữ liệu đang hoạt động. Tại đây bạn có thể thấy 40 luồng được ghi vào một bảng và 40 luồng đọc dữ liệu đồng thời như thế nào. Các luồng viết tạo ra ngày càng nhiều HFiles, được đọc bởi các luồng khác. Kết quả là ngày càng có nhiều dữ liệu cần được xóa khỏi bộ nhớ và cuối cùng GC bắt đầu hoạt động, điều này thực tế làm tê liệt mọi công việc. Việc bắt đầu quá trình nén chặt đã dẫn đến việc dọn sạch các mảnh vụn và khôi phục năng suất.

Lý thuyết và thực hành sử dụng HBase
Thử nghiệm được thực hiện trên 3 DataNodes và 4 RS (CPU Xeon E5-2680 v4 @ 2.40GHz * 64 thread). Phiên bản HBase 1.2.0-cdh5.14.2

Điều đáng chú ý là quá trình nén chính đã được thực hiện trên một bảng "trực tiếp", trong đó dữ liệu được ghi và đọc tích cực. Có một tuyên bố trực tuyến rằng điều này có thể dẫn đến phản hồi không chính xác khi đọc dữ liệu. Để kiểm tra, một quy trình đã được khởi chạy nhằm tạo ra dữ liệu mới và ghi nó vào bảng. Sau đó, tôi ngay lập tức đọc và kiểm tra xem giá trị kết quả có trùng khớp với những gì được viết ra hay không. Trong khi quá trình này đang chạy, quá trình đầm nén lớn đã được thực hiện khoảng 200 lần và không một lỗi nào được ghi nhận. Có lẽ sự cố hiếm khi xuất hiện và chỉ xuất hiện khi tải cao, vì vậy sẽ an toàn hơn nếu dừng quá trình ghi và đọc theo kế hoạch và thực hiện dọn dẹp để ngăn chặn tình trạng rút GC như vậy.

Ngoài ra, việc nén chính không ảnh hưởng đến trạng thái của MemStore, để chuyển nó vào đĩa và nén nó, bạn cần sử dụng lệnh tuôn ra (connection.getAdmin().flush(TableName.valueOf(tblName))).

8. Cài đặt và hiệu suất

Như đã đề cập, HBase cho thấy thành công lớn nhất của nó khi không cần phải làm gì khi thực thi BulkLoad. Tuy nhiên, điều này áp dụng cho hầu hết các hệ thống và con người. Tuy nhiên, công cụ này phù hợp hơn để lưu trữ dữ liệu hàng loạt theo khối lớn, trong khi nếu quy trình yêu cầu nhiều yêu cầu đọc và ghi cạnh tranh thì các lệnh Nhận và Đặt được mô tả ở trên sẽ được sử dụng. Để xác định các tham số tối ưu, việc khởi chạy được thực hiện với nhiều sự kết hợp khác nhau của các tham số và cài đặt bảng:

  • 10 luồng được khởi chạy đồng thời 3 lần liên tiếp (hãy gọi đây là khối luồng).
  • Thời gian hoạt động của tất cả các luồng trong một khối được tính trung bình và là kết quả cuối cùng của hoạt động của khối.
  • Tất cả các chủ đề đều hoạt động với cùng một bảng.
  • Trước mỗi lần bắt đầu khối luồng, việc nén chính được thực hiện.
  • Mỗi khối chỉ thực hiện một trong các thao tác sau:

-Đặt
-Lấy
—Nhận + Đặt

  • Mỗi khối thực hiện 50 lần lặp lại hoạt động của nó.
  • Kích thước khối của bản ghi là 100 byte, 1000 byte hoặc 10000 byte (ngẫu nhiên).
  • Các khối được khởi chạy với số lượng khóa được yêu cầu khác nhau (một khóa hoặc 10).
  • Các khối được chạy trong các cài đặt bảng khác nhau. Các thông số đã thay đổi:

— BlockCache = bật hoặc tắt
— Kích thước khối = 65 KB hoặc 16 KB
— Phân vùng = 1, 5 hoặc 30
- MSLAB = bật hoặc tắt

Vì vậy, khối trông như thế này:

Một. Chế độ MSLAB đã được bật/tắt.
b. Một bảng đã được tạo trong đó các tham số sau đã được đặt: BlockCache = true/none, BlockSize = 65/16 Kb, Phân vùng = 1/5/30.
c. Nén được đặt thành GZ.
d. 10 luồng đã được khởi chạy đồng thời thực hiện các thao tác put/get/get+put 1/10 vào bảng này với các bản ghi 100/1000/10000 byte, thực hiện 50 truy vấn liên tiếp (khóa ngẫu nhiên).
đ. Điểm d được lặp lại ba lần.
f. Thời gian hoạt động của tất cả các chủ đề được tính trung bình.

Tất cả các kết hợp có thể đã được thử nghiệm. Có thể dự đoán rằng tốc độ sẽ giảm khi kích thước bản ghi tăng lên hoặc việc tắt bộ nhớ đệm sẽ gây chậm. Tuy nhiên, mục tiêu là để hiểu mức độ và tầm quan trọng của ảnh hưởng của từng tham số, do đó dữ liệu thu thập được đưa vào đầu vào của hàm hồi quy tuyến tính, giúp đánh giá mức độ quan trọng bằng cách sử dụng thống kê t. Dưới đây là kết quả của các khối thực hiện thao tác Put. Trọn bộ kết hợp 2*2*3*2*3 = 144 tùy chọn + 72 tk. một số đã được thực hiện hai lần. Do đó, có tổng cộng 216 lượt chạy:

Lý thuyết và thực hành sử dụng HBase
Thử nghiệm được thực hiện trên một cụm nhỏ gồm 3 DataNodes và 4 RS (CPU Xeon E5-2680 v4 @ 2.40GHz * 64 thread). Phiên bản HBase 1.2.0-cdh5.14.2.

Tốc độ chèn cao nhất là 3.7 giây đạt được khi tắt chế độ MSLAB, trên một bảng có một phân vùng, bật BlockCache, BlockSize = 16, bản ghi 100 byte, 10 miếng mỗi gói.
Tốc độ chèn thấp nhất là 82.8 giây đạt được khi bật chế độ MSLAB, trên một bảng có một phân vùng, bật BlockCache, BlockSize = 16, các bản ghi 10000 byte, mỗi bản ghi 1 byte.

Bây giờ chúng ta hãy nhìn vào mô hình. Chúng tôi thấy chất lượng tốt của mô hình dựa trên R2, nhưng hoàn toàn rõ ràng rằng phép ngoại suy bị chống chỉ định ở đây. Hành vi thực tế của hệ thống khi các tham số thay đổi sẽ không tuyến tính; mô hình này cần thiết không phải để dự đoán mà để hiểu điều gì đã xảy ra trong các tham số đã cho. Ví dụ: ở đây, theo tiêu chí của Sinh viên, chúng tôi thấy rằng các tham số BlockSize và BlockCache không quan trọng đối với thao tác Put (điều này thường khá dễ đoán):

Lý thuyết và thực hành sử dụng HBase
Nhưng thực tế là việc tăng số lượng phân vùng dẫn đến giảm hiệu suất là điều hơi bất ngờ (chúng tôi đã thấy tác động tích cực của việc tăng số lượng phân vùng với BulkLoad), mặc dù có thể hiểu được. Đầu tiên, để xử lý, bạn phải tạo yêu cầu tới 30 vùng thay vì một vùng và khối lượng dữ liệu không đủ để mang lại lợi ích. Thứ hai, tổng thời gian hoạt động được xác định bởi RS chậm nhất và do số lượng DataNodes ít hơn số lượng RS nên một số vùng có vị trí bằng XNUMX. Chà, hãy nhìn vào top XNUMX:

Lý thuyết và thực hành sử dụng HBase
Bây giờ hãy đánh giá kết quả thực hiện khối Get:

Lý thuyết và thực hành sử dụng HBase
Số lượng phân vùng đã mất đi ý nghĩa, điều này có thể được giải thích là do dữ liệu được lưu trữ tốt và bộ nhớ đệm đọc là tham số (theo thống kê) quan trọng nhất. Đương nhiên, việc tăng số lượng tin nhắn trong một yêu cầu cũng rất hữu ích cho hiệu suất. Điểm cao nhất:

Lý thuyết và thực hành sử dụng HBase
Chà, cuối cùng, chúng ta hãy xem mô hình của khối đầu tiên thực hiện get và sau đó put:

Lý thuyết và thực hành sử dụng HBase
Tất cả các tham số đều có ý nghĩa ở đây. Và kết quả của người đứng đầu:

Lý thuyết và thực hành sử dụng HBase

9. Kiểm tra tải

Chà, cuối cùng thì chúng tôi cũng sẽ tung ra một tải ít nhiều khá tốt, nhưng sẽ luôn thú vị hơn khi bạn có thứ gì đó để so sánh. Trên trang web của DataStax, nhà phát triển chính của Cassandra, có phát hiện NT của một số kho lưu trữ NoSQL, bao gồm cả phiên bản HBase 0.98.6-1. Quá trình tải được thực hiện bởi 40 luồng, kích thước dữ liệu 100 byte, đĩa SSD. Kết quả kiểm tra các thao tác Read-Modify-Write cho kết quả như sau.

Lý thuyết và thực hành sử dụng HBase
Theo tôi hiểu, việc đọc được thực hiện theo khối 100 bản ghi và đối với 16 nút HBase, thử nghiệm DataStax cho thấy hiệu suất 10 nghìn thao tác mỗi giây.

Thật may mắn khi cụm của chúng tôi cũng có 16 nút, nhưng cũng không “may mắn” lắm khi mỗi nút có 64 lõi (luồng), trong khi ở thử nghiệm DataStax chỉ có 4. Mặt khác, chúng có ổ SSD, trong khi chúng tôi có ổ cứng HDD. hoặc hơn, phiên bản mới của HBase và mức sử dụng CPU trong quá trình tải thực tế không tăng đáng kể (về mặt trực quan là 5-10%). Tuy nhiên, hãy thử bắt đầu sử dụng cấu hình này. Cài đặt bảng mặc định, việc đọc được thực hiện trong phạm vi chính từ 0 đến 50 triệu một cách ngẫu nhiên (tức là về cơ bản là mới mỗi lần). Bảng chứa 50 triệu bản ghi, được chia thành 64 phân vùng. Các khóa được băm bằng crc32. Cài đặt bảng là mặc định, MSLAB được bật. Khởi chạy 40 luồng, mỗi luồng đọc một bộ 100 khóa ngẫu nhiên và ngay lập tức ghi lại 100 byte được tạo vào các khóa này.

Lý thuyết và thực hành sử dụng HBase
Chân đế: 16 DataNode và 16 RS (CPU Xeon E5-2680 v4 @ 2.40GHz * 64 thread). Phiên bản HBase 1.2.0-cdh5.14.2.

Kết quả trung bình là gần 40 nghìn thao tác mỗi giây, tốt hơn đáng kể so với thử nghiệm DataStax. Tuy nhiên, vì mục đích thử nghiệm, bạn có thể thay đổi các điều kiện một chút. Rất khó có khả năng tất cả công việc sẽ được thực hiện độc quyền trên một bảng và cũng chỉ trên các phím duy nhất. Giả sử rằng có một bộ phím “nóng” nhất định tạo ra tải chính. Do đó, hãy thử tạo tải với các bản ghi lớn hơn (10 KB), cũng theo lô 100, trong 4 bảng khác nhau và giới hạn phạm vi khóa được yêu cầu ở mức 50 nghìn. Biểu đồ bên dưới hiển thị khởi chạy 40 luồng, mỗi luồng đọc một bộ 100 phím và ghi ngay 10 KB ngẫu nhiên vào các phím này.

Lý thuyết và thực hành sử dụng HBase
Chân đế: 16 DataNode và 16 RS (CPU Xeon E5-2680 v4 @ 2.40GHz * 64 thread). Phiên bản HBase 1.2.0-cdh5.14.2.

Trong quá trình tải, đầm nén chính được tiến hành nhiều lần, như đã trình bày ở trên, nếu không có quy trình này, hiệu suất sẽ giảm dần, tuy nhiên, tải trọng bổ sung cũng phát sinh trong quá trình thực hiện. Việc rút tiền được gây ra bởi nhiều lý do. Đôi khi các luồng hoạt động xong và có sự tạm dừng trong khi chúng được khởi động lại, đôi khi các ứng dụng của bên thứ ba tạo ra tải trên cụm.

Đọc và viết ngay lập tức là một trong những tình huống làm việc khó khăn nhất đối với HBase. Nếu bạn chỉ thực hiện các yêu cầu đặt nhỏ, chẳng hạn như 100 byte, kết hợp chúng thành các gói 10-50 nghìn phần, bạn có thể nhận được hàng trăm nghìn thao tác mỗi giây và tình huống cũng tương tự với các yêu cầu chỉ đọc. Điều đáng chú ý là kết quả hoàn toàn tốt hơn so với kết quả mà DataStax thu được, hầu hết là do yêu cầu theo khối 50 nghìn.

Lý thuyết và thực hành sử dụng HBase
Chân đế: 16 DataNode và 16 RS (CPU Xeon E5-2680 v4 @ 2.40GHz * 64 thread). Phiên bản HBase 1.2.0-cdh5.14.2.

10. Kết luận

Hệ thống này được cấu hình khá linh hoạt, tuy nhiên vẫn chưa rõ ảnh hưởng của một số lượng lớn các tham số. Một số trong số chúng đã được thử nghiệm nhưng không được đưa vào bộ thử nghiệm thu được. Ví dụ: các thử nghiệm sơ bộ cho thấy tầm quan trọng không đáng kể của tham số như DATA_BLOCK_ENCODING, tham số này mã hóa thông tin bằng cách sử dụng các giá trị từ các ô lân cận, điều này có thể hiểu được đối với dữ liệu được tạo ngẫu nhiên. Nếu bạn sử dụng một số lượng lớn các đối tượng trùng lặp thì mức tăng có thể rất đáng kể. Nhìn chung, chúng ta có thể nói rằng HBase tạo ấn tượng về một cơ sở dữ liệu khá nghiêm túc và được cân nhắc kỹ lưỡng, có thể hoạt động khá hiệu quả khi thực hiện các thao tác với khối dữ liệu lớn. Đặc biệt nếu có thể tách biệt kịp thời quá trình đọc và viết.

Nếu theo ý kiến ​​​​của bạn có điều gì đó chưa được tiết lộ đầy đủ, tôi sẵn sàng nói với bạn chi tiết hơn. Chúng tôi mời bạn chia sẻ kinh nghiệm của bạn hoặc thảo luận nếu bạn không đồng ý với điều gì đó.

Nguồn: www.habr.com

Thêm một lời nhận xét