2012-01-24 27 views
10

Tôi có câu hỏi liên quan đến thiết kế lược đồ HBase. Vấn đề là khá đơn giản - tôi đang lưu trữ "thông báo" trong HBase, mỗi trong số đó có một trạng thái ("mới", "nhìn thấy", và "đọc"). Dưới đây là các API Tôi cần cung cấp:Thiết kế giản đồ HBase để hỗ trợ tốt nhất các truy vấn cụ thể

  • Nhận tất cả các thông báo cho người dùng
  • Nhận tất cả các thông báo "mới" cho người dùng
  • Lấy số của tất cả các thông báo "mới" cho người dùng
  • tình trạng cập nhật cho một thông báo
  • tình trạng cập nhật cho tất cả các thông báo của người dùng
  • Nhận tất cả các thông báo "mới" accross cơ sở dữ liệu
  • Notifications sho uld có thể quét được theo thứ tự thời gian đảo ngược và cho phép phân trang.

Tôi có một vài ý tưởng và tôi muốn xem liệu một trong số đó có rõ ràng nhất hay không hoặc nếu tôi đã bỏ lỡ một chiến lược hoàn toàn tốt. Chung cho cả ba, tôi nghĩ rằng có một hàng cho mỗi thông báo và có id người dùng trong rowkey là con đường để đi. Để có được thứ tự thời gian để phân trang, tôi cũng cần có dấu thời gian ngược trong đó. Tôi muốn giữ tất cả các notif trong một bảng (vì vậy tôi không phải hợp nhất sắp xếp cho cuộc gọi "nhận tất cả notificatiosn cho người dùng") và không muốn viết các công việc hàng loạt cho các bảng chỉ mục phụ (kể từ khi cập nhật đến số lượng và trạng thái phải theo thời gian thực).

Cách đơn giản nhất để làm điều đó là (1) khóa hàng là "userId_reverseTimestamp" và lọc cho trạng thái ở phía máy khách. Điều này có vẻ ngây thơ, vì chúng tôi sẽ gửi rất nhiều dữ liệu không cần thiết thông qua mạng.

Khả năng tiếp theo là (2) cũng mã hóa trạng thái thành hàng khóa, do đó, hoặc "userId_reverseTimestamp_status" và sau đó thực hiện lọc regex hàng tuần trên quét. Vấn đề đầu tiên tôi thấy là cần phải xóa một hàng và sao chép dữ liệu thông báo sang một hàng mới khi thay đổi trạng thái (có thể xảy ra chính xác hai lần cho mỗi thông báo). Ngoài ra, vì trạng thái là phần cuối cùng của khóa hàng, đối với mỗi người dùng, chúng tôi sẽ quét nhiều hàng bổ sung. Đây có phải là một hit hiệu suất lớn không? Cuối cùng, để thay đổi trạng thái, tôi sẽ cần phải biết trạng thái trước đó là gì (để tạo khóa hàng) hoặc nếu không tôi sẽ cần thực hiện một lần quét khác.

Ý tưởng cuối cùng tôi có là (3) có hai họ cột, một cho dữ liệu thông báo tĩnh và một là cờ cho trạng thái, tức là "s: read" hoặc "s: new" with 's 'là cf và trạng thái là vòng loại. Sẽ có chính xác một hàng trên mỗi hàng và tôi có thể thực hiện một MultipleColumnPrefixFilter hoặc SkipFilter w/ColumnPrefixFilter dựa vào đó Ở đây cũng vậy, tôi sẽ phải xóa và tạo các cột về thay đổi trạng thái, nhưng nó sẽ nhẹ hơn nhiều so với việc sao chép toàn bộ các hàng. Mối quan tâm duy nhất của tôi là cảnh báo trong cuốn sách HBase rằng HBase không làm tốt với "hơn 2 hoặc 3 cột gia đình" - có lẽ nếu hệ thống cần được mở rộng với nhiều khả năng truy vấn hơn, chiến lược đa cf sẽ không mở rộng .

Vì vậy, (1) có vẻ như nó sẽ có quá nhiều chi phí mạng. (2) có vẻ như nó sẽ lãng phí chi phí sao chép dữ liệu và (3) có thể gây ra vấn đề với quá nhiều gia đình. Giữa (2) và (3), loại bộ lọc nào sẽ cho hiệu suất tốt hơn? Trong cả hai trường hợp, quá trình quét sẽ xem xét từng hàng cho một người dùng, có lẽ hầu như đã đọc thông báo - điều này sẽ có hiệu suất tốt hơn. Tôi nghĩ rằng tôi đang nghiêng về phía (3) - có những lựa chọn khác (hoặc tinh chỉnh) mà tôi đã bỏ qua?

+0

Các thông báo có nói là 'mới' và 'đã đọc' chỉ với một chuyển đổi có thể có từ mới sang đọc? Khối lượng của các thông báo này là bao nhiêu? – Gevorg

Trả lời

2

Bạn đã suy nghĩ rất nhiều về điều này và tôi nghĩ cả ba đều hợp lý!

Bạn muốn có khóa chính là tên người dùng được ghép với dấu thời gian vì hầu hết các truy vấn của bạn là "theo người dùng". Điều này sẽ giúp phân trang dễ dàng bằng tính năng quét và có thể tìm nạp thông tin người dùng khá nhanh chóng.

Tôi nghĩ điểm mấu chốt của vấn đề là phần trạng thái thay đổi này. Nói chung, một cái gì đó giống như một "đọc" -> "xóa" -> "viết lại" giới thiệu tất cả các loại vấn đề tương tranh. Điều gì xảy ra nếu nhiệm vụ của bạn không thành công? Bạn có dữ liệu ở trạng thái không hợp lệ không? Bạn sẽ thả một bản ghi?

Tôi đề nghị bạn thay vì coi bảng là "chỉ nối". Về cơ bản, hãy làm những gì bạn đề xuất cho # 3, nhưng thay vì xóa cờ, hãy giữ nó ở đó. Nếu một cái gì đó đã được đọc, nó có thể có ba "s: see", "s: read" ở đó (nếu nó là mới, chúng ta có thể giả sử nó là trống). Bạn cũng có thể được ưa thích và đặt một dấu thời gian trong mỗi ba để hiển thị khi sự kiện đó đã được hài lòng. Bạn sẽ không thấy nhiều ảnh hưởng đến việc thực hiện điều này và sau đó bạn không phải lo lắng về sự tương tranh, vì tất cả các thao tác đều chỉ ghi và nguyên tử.

Tôi hy vọng điều này hữu ích. Tôi không chắc liệu tôi có trả lời mọi thứ vì câu hỏi của bạn quá rộng không. Vui lòng theo dõi các câu hỏi bổ sung và tôi sẽ thích xây dựng hoặc thảo luận điều gì đó khác.

+0

Điểm Gppd về cách làm cho nó chỉ ghi. Không phải hack các bản cập nhật nguyên tử làm cho nó ít phức tạp hơn - bộ lọc của tôi sẽ chỉ là "miễn là không có trạng thái chưa đọc". Một tùy chọn khác mà ai đó đề xuất là có nhiều cột mỗi hàng, trong đó một hàng là tất cả các thông báo cho người dùng. Có lẽ, các cột được sắp xếp tương tự như các hàng. Câu hỏi của tôi là, điều này có cho chúng tôi điều gì không? Họ cũng đề xuất chỉ cần thực hiện một ValueFilter trên notif (để có trạng thái sống trong chính dữ liệu, cần phải được cập nhật, chứ không phải là một CF riêng biệt). Đoán của tôi là điều này sẽ có hiệu suất tồi tệ hơn. Suy nghĩ? – dyross

1

Giải pháp của tôi là:

Không lưu trạng thái thông báo (nhìn thấy, mới) trong hbase cho từng thông báo. Đối với các thông báo sử dụng lược đồ đơn giản. Khóa: userid_timestamp - cột: notification_message.

Khi khách hàng hỏi API "Nhận tất cả thông báo mới", hãy lưu dấu thời gian (Tất cả thông báo mới được đẩy). Chính: userid - colimn: All_new_notifications_pushed_time

Mọi thông báo với timestamp là thấp hơn "Tất cả các thông báo mới đẩy" giả "nhìn thấy", và nếu lớn hơn giả "New"

Để có được tất cả các thông báo mới: trước hết là nhận được giá trị (dấu thời gian) cho All_new_notifications_pushed_time bởi userid sau đó thực hiện quét phạm vi trên cột notification_message theo khóa: từ current_timestamp đến All_new_notifications_pushed_time.

Điều này sẽ giới hạn đáng kể các cột bị ảnh hưởng và hầu hết trong số các cột này phải ở trong cửa hàng ghi nhớ.

Đếm thông báo mới trên máy khách.

Các vấn đề liên quan