2009-10-15 41 views
8

Tôi cần lưu trữ các bản ghi vào bộ nhớ lâu dài và truy xuất dữ liệu theo yêu cầu. Yêu cầu như sau:Lưu trữ và truy xuất dữ liệu nhanh Java

  1. Vô cùng nhanh chóng phục hồi và chèn
  2. Mỗi bản ghi sẽ có một khóa duy nhất. Khóa này sẽ được sử dụng để lấy các bản ghi
  3. Các dữ liệu được lưu trữ nên được tức là dai dẳng nên có sẵn trên JVM khởi động lại
  4. Một quá trình riêng biệt sẽ chuyển hồ sơ cũ để RDBMS một lần một ngày

gì làm các bạn nghĩ sao? Tôi không thể sử dụng cơ sở dữ liệu chuẩn vì các vấn đề về độ trễ. Các cơ sở dữ liệu bộ nhớ như HSQLDB/H2 có các đường viền thực hiện. Hơn nữa các bản ghi là các đối tượng chuỗi đơn giản và không đủ điều kiện cho SQL. Tôi đang nghĩ đến một loại giải pháp dựa trên tập tin phẳng. Ý tưởng nào? Bất kỳ dự án mã nguồn mở nào? Tôi chắc chắn, phải có một người đã giải quyết vấn đề này trước đây.

+1

Bạn có ý nghĩa gì bởi "Cực kỳ nhanh"? –

+0

Độ trễ dưới miligiây để lưu trữ và truy xuất – AAK

+2

Tỷ lệ ghi của bạn để đọc là bao nhiêu? khi đọc, mẫu truy cập là gì (ngẫu nhiên, vón cục, ...)? bản chất của khóa duy nhất cho mỗi bản ghi (không quan trọng, uuid, dấu thời gian) là gì? – Ron

Trả lời

2

MySQL với phân đoạn có thể là một ý tưởng hay. Tuy nhiên, nó phụ thuộc vào khối lượng dữ liệu, giao dịch mỗi giây và thời gian chờ bạn cần.

Trong cơ sở dữ liệu bộ nhớ cũng là một ý tưởng hay. Trong thực tế, MySQL cung cấp các bảng dựa trên bộ nhớ.

+0

vâng ... trong bộ nhớ cơ sở dữ liệu là tốt ... nhưng kinh nghiệm trước đây của tôi với HSQLDB không phải là tuyệt vời ... trong thực tế, chúng tôi đã xác định HQSQL db đã dành thời gian đáng kể trong chế biến của chúng tôi ... Không chắc chắn về MSQL mặc dù – AAK

1

Bạn đã thực sự chứng minh rằng việc sử dụng cơ sở dữ liệu SQL quá hạn như MySQL hay SQL Server quá chậm, hay đây có phải là giả định không?

Bạn có thể sử dụng phương pháp cơ sở dữ liệu SQL kết hợp với bộ nhớ cache trong bộ nhớ để đảm bảo rằng các lần truy xuất không chạm vào cơ sở dữ liệu. Mặc dù thực tế là các bản ghi là bản rõ nhưng tôi vẫn khuyên bạn nên sử dụng SQL trên một giải pháp tệp phẳng (ví dụ: sử dụng một cột văn bản trong lược đồ bảng) của bạn vì RDBMS sẽ thực hiện tối ưu hóa hệ thống tệp không thể (ví dụ: lưu vào bộ nhớ cache các trang được truy cập gần đây, v.v.) .

Tuy nhiên, không có thêm thông tin về mẫu truy cập của bạn, thông lượng dự kiến, v.v. Tôi không thể cung cấp nhiều hơn nữa theo cách đề xuất.

+0

Có . Hệ thống cũ của chúng tôi sử dụng RDBMS và mất vài phần nghìn giây để truy xuất dữ liệu. Đây là ứng dụng tần số cao, tốc độ yêu cầu trong phần nghìn giây cho toàn bộ quá trình xử lý tin nhắn, nơi lưu trữ và truy xuất chỉ là một phần của quá trình xử lý tin nhắn – AAK

+0

Quan trọng hơn, mẫu truy cập của bạn là gì? Dữ liệu tuần tự (ví dụ: chuỗi thời gian)? Dữ liệu được viết một lần và đọc nhiều lần hay có thể được cập nhật? Có các giải pháp riêng biệt cho điều này (ví dụ: KDB) nhưng phần lớn phụ thuộc vào trường hợp sử dụng của bạn. – Adamski

-1

Tất cả các bản ghi và khóa bạn cần có vừa trong bộ nhớ cùng một lúc không? Nếu có, bạn chỉ có thể sử dụng một chuỗi HashMap <, String >, vì nó có thể được Serializable.

+0

-1 từ tôi. Bạn sẽ cần phải tự serialize toàn bộ HashMap trên mỗi chèn, mà rõ ràng là rất chậm. –

+0

nhưng ... làm thế nào về dữ liệu thời gian thực tồn tại? Tôi cần phải kiên trì dữ liệu khi nó đến để nếu JVM bị treo tôi không bị mất dữ liệu ... – AAK

+0

@AAK: bạn chỉ có thể tuần tự hóa và lưu trữ từng thay đổi. Sau đó, bạn không có bộ nhớ lưu trữ có thể sử dụng ngay lập tức, nhưng có nhật ký mà từ đó bạn có thể tạo lại bộ nhớ trong trường hợp có lỗi. –

1

Có vấn đề gì nếu bạn mất một hoặc hai bản ghi? Họ đến từ đâu? Bạn có mối quan hệ giao dịch với nguồn không?

Nếu bạn có yêu cầu về độ tin cậy nghiêm trọng thì tôi nghĩ bạn có thể cần phải chuẩn bị sẵn sàng để trả một số chi phí đầu vào DB.

Có lẽ bạn có thể tách sự cố liên tục khỏi sự cố trong bộ nhớ. Sử dụng phương pháp tiếp cận phụ-pup. Một người đăng ký trông nom trong bộ nhớ, người kia vẫn kiên trì dữ liệu sẵn sàng cho khởi động tiếp theo?

Các sản phẩm đóng gói phân phối như WebSphere eXtreme Scale (không phụ thuộc vào Java EE) có thể phù hợp nếu bạn có thể mua thay vì xây dựng.

+0

Yêu cầu độ tin cậy là khá cao. Tôi cũng nghiêng về một số giải pháp lưu trữ. EHCache? – AAK

1

Sẽ tệ đến mức nào nếu bạn mất một vài mục trong trường hợp xảy ra sự cố?

Nếu không phải là xấu, phương pháp sau đây có thể phù hợp với bạn:

Tạo tệp phẳng cho mỗi mục nhập, tên tệp bằng id. Có thể một tệp cho số lượng mục nhập liên tiếp không quá lớn.

Đảm bảo bộ điều khiển của bạn có bộ nhớ cache tốt và/hoặc sử dụng một trong các bộ nhớ cache hiện có được triển khai trong Java.

Nói chuyện với chuyên gia về hệ thống tệp để thực hiện điều này nhanh chóng

Rất đơn giản và có thể nhanh chóng. Tất nhiên bạn mất giao dịch bao gồm các nguyên tắc ACID.

+0

Yêu cầu độ tin cậy khá cao. Chúng tôi không thể mất bất kỳ dữ liệu nào sau khi gặp sự cố ... – AAK

4

Nếu tất cả dữ liệu phù hợp trong bộ nhớ, MySQL có thể chạy trong bộ nhớ thay vì từ đĩa (MySQL Cluster, Hybrid Storage). Sau đó nó có thể xử lý lưu trữ chính nó vào đĩa cho bạn.

1

Nếu bạn đang tìm kiếm một cửa hàng khóa-giá trị đơn giản và không cần truy vấn sql phức tạp, Berkeley DB có thể đáng xem.

Một giải pháp thay thế khác là Tokyo Cabinet, triển khai DBM hiện đại.

1

Sub mili giây r/w nghĩa là bạn không thể phụ thuộc vào đĩa và bạn phải cẩn thận về độ trễ của mạng. Chỉ cần quên đi các giải pháp dựa trên SQL tiêu chuẩn, bộ nhớ chính hay không. Trong một ms, bạn không thể nhận được hơn 100 KByte trên một mạng GBit. Hỏi kỹ sư viễn thông, họ được sử dụng để giải quyết những vấn đề này.

7

Có rất nhiều công cụ và phương pháp đa dạng, nhưng tôi nghĩ không ai trong số họ có thể tỏa sáng trong tất cả các yêu cầu.

Đối với độ trễ thấp, bạn chỉ có thể dựa vào quyền truy cập dữ liệu trong bộ nhớ - đĩa quá chậm (và ổ SSD). Nếu dữ liệu không phù hợp với bộ nhớ của một máy đơn lẻ, chúng tôi phải phân phối dữ liệu của chúng tôi đến nhiều nút hơn để tổng hợp đủ bộ nhớ.

Đối với kiên trì, sau đó chúng tôi phải ghi dữ liệu của mình vào đĩa. Giả sử tổ chức tối ưu điều này có thể được thực hiện dưới dạng hoạt động nền, không ảnh hưởng đến độ trễ. Tuy nhiên, đối với độ tin cậy (failover, HA hoặc bất cứ điều gì), hoạt động đĩa không thể hoàn toàn độc lập với các phương pháp truy cập: chúng ta phải đợi cho đĩa khi sửa đổi dữ liệu để làm cho hoạt động của chúng tôi sẽ không biến mất. Đồng thời cũng thêm một số độ phức tạp và độ trễ.

Mô hình dữ liệu không giới hạn ở đây: hầu hết các phương pháp hỗ trợ truy cập dựa trên khóa duy nhất.

Chúng tôi phải quyết định,

  • nếu dữ liệu phù hợp trong bộ nhớ của một máy, hoặc chúng ta phải tìm ra giải pháp phân phối,
  • nếu đồng thời là một vấn đề, hoặc không có hoạt động song song,
  • nếu độ tin cậy là nghiêm ngặt, chúng tôi không thể sửa đổi nhỏ, hoặc chúng ta có thể sống với thực tế là một vụ tai nạn ngoài kế hoạch sẽ dẫn đến mất dữ liệu.

Giải pháp có thể là

  • tự thực hiện cấu trúc dữ liệu sử dụng thư viện java tiêu chuẩn, các tập tin vv có thể không phải là giải pháp tốt nhất, vì độ tin cậy và độ trễ thấp yêu cầu triển khai thông minh và rất nhiều thử nghiệm,
  • RDBMS s có mô hình dữ liệu linh hoạt, hoạt động bền, nguyên tử và bị cô lập, bộ nhớ đệm, v.v. - chúng thực sự biết quá nhiều và hầu như khó phân phối. Đó là lý do tại sao chúng quá chậm, nếu bạn không thể tắt các tính năng không mong muốn, thường là như vậy.
  • NoSQLcửa hàng khóa giá trị là các lựa chọn thay thế tốt. Những thuật ngữ này khá mơ hồ và bao gồm rất nhiều công cụ. Ví dụ:
    • BerkeleyDB hoặc Kyoto Tủ dưới dạng các cửa hàng khóa-giá trị liên tục một máy (sử dụng B-trees): có thể được sử dụng nếu tập dữ liệu đủ nhỏ để vừa với bộ nhớ của một máy.
    • Dự án Voldemort như một kho khóa giá trị phân phối: sử dụng phiên bản javaDB bên trong, đơn giản và phân phối,
    • ScalienDB như một kho khóa giá trị phân phối: đáng tin cậy, nhưng không quá chậm để viết.
    • MemcacheDB, Redis cơ sở dữ liệu bộ nhớ đệm khác với sự kiên trì,
    • các hệ thống NoSQL phổ biến như Cassandra, CouchDB, HBase v.v. được sử dụng chủ yếu cho dữ liệu lớn.

Danh sách các công cụ NoSQL có thể được tìm thấy, ví dụ: here.

Voldemort's performance tests báo cáo thời gian đáp ứng mili giây, và chúng có thể đạt được khá dễ dàng, tuy nhiên chúng tôi cũng phải cẩn thận với phần cứng (như thuộc tính mạng được đề cập ở trên).

3

Tôi sẽ sử dụng một số BlockingQueue cho điều đó. Đơn giản và được tích hợp vào Java.
Tôi làm điều gì đó tương tự bằng cách sử dụng dữ liệu thời gian thực từ Chicago Merchantile Exchange.
Dữ liệu được gửi đến một nơi để sử dụng trong thời gian thực ... và đến một nơi khác (qua TCP), bằng cách sử dụng BlockingQueue (Nhà sản xuất/Người tiêu dùng) để lưu dữ liệu vào cơ sở dữ liệu (Oracle, H2).
Người tiêu dùng sử dụng cam kết thời gian bị trì hoãn để tránh các vấn đề đồng bộ hóa fdisk trong cơ sở dữ liệu.
(Cơ sở dữ liệu kiểu H2 không đồng bộ cam kết theo mặc định và tránh vấn đề đó) Tôi ghi lại sự bền bỉ trong Người tiêu dùng để theo dõi kích thước hàng đợi để chắc chắn
nó có thể theo kịp với Nhà sản xuất. Hoạt động khá tốt cho tôi.

0

MapDB cung cấp HashMaps/TreeMaps có hiệu năng cao được lưu vào đĩa. Một thư viện duy nhất mà bạn có thể nhúng vào chương trình Java của bạn.

0

Chronicle Map là triển khai ConcurrentMap lưu trữ khóa và giá trị ngoài heap, trong tệp ánh xạ bộ nhớ. Vì vậy, bạn có kiên trì trên JVM khởi động lại.

ChronicleMap.get() liên tục nhanh hơn 1 chúng tôi, đôi khi nhanh tới 100 ns/hoạt động. Đó là giải pháp the fastest trong lớp học.

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