2012-02-13 32 views
21

Điều này giống như một câu hỏi dài vì tất cả ngữ cảnh. Có 2 câu hỏi bên trong tiểu thuyết bên dưới. Cảm ơn bạn đã dành thời gian để đọc điều này và cung cấp hỗ trợ.Bộ nhớ ánh xạ MappedByteBuffer hoặc ByteBuffer trực tiếp để thực hiện DB?

Tình hình

Tôi đang làm việc trên một kho dữ liệu thực hiện khả năng mở rộng có thể hỗ trợ làm việc với các tập tin dữ liệu từ một vài KB đến một TB hoặc nhiều hơn trong kích thước trên một hệ thống 32-bit hoặc 64-bit.

Kho dữ liệu sử dụng thiết kế Sao chép trên ghi; luôn bổ sung dữ liệu mới hoặc sửa đổi vào cuối tệp dữ liệu và không bao giờ thực hiện chỉnh sửa tại chỗ cho dữ liệu hiện có.

Hệ thống có thể lưu trữ 1 hoặc nhiều cơ sở dữ liệu; mỗi đại diện bởi một tập tin trên đĩa.

Chi tiết triển khai không quan trọng; chi tiết quan trọng duy nhất là tôi cần phải liên tục thêm vào tệp và phát triển nó từ KB, thành MB, sang GB thành TB trong khi đồng thời ngẫu nhiên bỏ qua tệp để đọc hoạt động để trả lời yêu cầu của khách hàng.

First-Suy nghĩ

Thoạt nhìn tôi biết tôi muốn sử dụng tập tin bộ nhớ ánh xạ vì vậy tôi có thể đẩy gánh nặng quản lý có hiệu quả trong bộ nhớ trạng thái của dữ liệu vào hệ điều hành máy chủ và ngoài ma cua toi. Sau đó, tất cả các mã của tôi cần phải lo lắng về là serializing các hoạt động phụ thêm vào tập tin on-write, và cho phép bất kỳ số lượng độc giả đồng thời tìm kiếm trong tập tin để trả lời các yêu cầu.

Thiết kế

Bởi vì dữ liệu tập tin cá nhân có thể phát triển vượt quá giới hạn 2GB một MappedByteBuffer, tôi hy vọng rằng thiết kế của tôi sẽ phải bao gồm một lớp trừu tượng mà phải mất một ghi bù đắp và chuyển đổi nó thành một bù đắp bên trong phân khúc 2GB cụ thể.

Cho đến nay rất tốt ...

vấn đề

Đây là nơi tôi bắt đầu để có được treo lên và nghĩ rằng sẽ có một thiết kế khác nhau (đề xuất dưới đây) có thể là cách tốt hơn để làm điều này.

Từ đọc qua 20 câu hỏi liên quan đến bộ nhớ "được ánh xạ" ở đây trên SO, có vẻ như các cuộc gọi mmap nhạy cảm với việc chạy bộ nhớ liền kề khi được cấp phát. Vì vậy, ví dụ, trên hệ điều hành máy chủ 32 bit nếu tôi cố gắng chèn một tệp 2GB, do phân mảnh bộ nhớ, cơ hội của tôi mỏng nên ánh xạ sẽ thành công và thay vào đó tôi nên sử dụng một thứ gì đó giống như một chuỗi 128MB ánh xạ để kéo toàn bộ Khi tôi nghĩ về thiết kế đó, thậm chí nói sử dụng kích thước 1024MB mmap, cho một DBMS lưu trữ một vài cơ sở dữ liệu khổng lồ được biểu diễn bằng các tệp 1TB nói, bây giờ tôi có hàng ngàn của vùng bộ nhớ ánh xạ trong bộ nhớ và trong thử nghiệm của riêng tôi trên Windows 7 cố gắng tạo vài trăm mmaps trên một tệp nhiều GB, tôi không chỉ chạy vào ngoại lệ, tôi thực sự có JVM để segfault mỗi khi tôi cố gắng phân bổ quá nhiều và trong một trường hợp nhận được video trong máy tính Windows 7 của tôi để cắt bỏ và khởi tạo lại với một cửa sổ bật lên lỗi hệ điều hành mà tôi chưa bao giờ thấy trước đây.

Bất kể đối số "bạn sẽ không bao giờ xử lý các tệp lớn" hoặc "đây là ví dụ giả tạo", thực tế là tôi có thể mã hóa thứ gì đó giống như vậy với các loại tác dụng phụ đó đặt báo thức nội bộ của tôi cảnh giác cao và được coi là một phương án thay thế (bên dưới). BESIDES vấn đề đó, sự hiểu biết của tôi về các tập tin ánh xạ bộ nhớ là tôi phải tạo lại ánh xạ mỗi lần tệp được phát triển, vì vậy trong trường hợp tệp này chỉ nối thêm trong thiết kế, nó liên tục theo nghĩa đen. phát triển.

Tôi có thể chống lại điều này ở mức độ nào đó bằng cách phát triển tệp theo khối (8MB mỗi lần) và chỉ tạo lại ánh xạ mỗi 8MB, nhưng cần phải liên tục tạo lại các ánh xạ này. không rõ ràng unmap feature supported in Java.

Câu hỏi # 1 trong tổng số 2

Với tất cả các phát hiện của tôi đến thời điểm này, tôi sẽ bỏ tập tin bộ nhớ ánh xạ như một giải pháp tốt cho chủ yếu đọc nặng giải pháp hay read-only giải pháp, nhưng không các giải pháp ghi nặng cho nhu cầu tái tạo bản đồ liên tục. Sau đó tôi nhìn xung quanh xung quanh tôi với các giải pháp như MongoDB bao gồm các tập tin ánh xạ bộ nhớ khắp nơi và tôi cảm thấy mình thiếu một số thành phần cốt lõi ở đây (tôi biết nó allocs trong một cái gì đó giống như 2GB extents tại một thời gian, vì vậy tôi tưởng tượng họ đang làm việc xung quanh chi phí bản đồ lại với logic này VÀ giúp duy trì tuần tự chạy trên đĩa). Tại thời điểm này tôi không biết vấn đề là Java thiếu một hoạt động unmap làm cho điều này trở nên nguy hiểm và không phù hợp với việc sử dụng của tôi hoặc nếu hiểu biết của tôi không đúng và ai đó có thể chỉ cho tôi miền Bắc.

Thiết kế Alternative

Một thiết kế để thay thế cho bộ nhớ ánh xạ một đề xuất ở trên mà tôi sẽ đi với nếu sự hiểu biết của tôi về mmap là đúng là như sau:

Xác định a direct ByteBuffer có kích thước cấu hình hợp lý (2, 4, 8, 16, 32, 64, 128KB) giúp dễ dàng tương thích với bất kỳ nền tảng máy chủ nào (không cần phải lo lắng về bản thân DBMS gây ra tình huống đập) và sử dụng FileChannel gốc, thực hiện specific-offset reads của tệp 1 đệm-dung lượng-chunk tại một thời điểm, hoàn toàn gửi đi bộ nhớ-ánh xạ các tập tin ở tất cả.

Nhược điểm là bây giờ mã của tôi phải lo lắng về những thứ như "tôi đã đọc đủ từ tệp để tải bản ghi đầy đủ chưa?"

Một mặt khác là tôi không tận dụng được logic bộ nhớ ảo của hệ điều hành, cho phép nó tự động lưu dữ liệu "nóng" trong bộ nhớ cho tôi; thay vào đó, tôi chỉ phải hy vọng bộ nhớ cache của tệp được sử dụng bởi hệ điều hành đủ lớn để làm điều gì đó hữu ích cho tôi ở đây.

Câu hỏi # 2 của 2

Tôi đã hy vọng để có được một xác nhận sự hiểu biết của tôi về tất cả điều này. Ví dụ, có thể bộ nhớ cache của tệp là tuyệt vời, trong cả hai trường hợp (bộ nhớ ánh xạ hoặc đọc trực tiếp), hệ điều hành chủ sẽ giữ càng nhiều dữ liệu nóng càng tốt và hiệu suất của tệp lớn không đáng kể.

Hoặc có thể sự hiểu biết của tôi về các yêu cầu nhạy cảm đối với tệp ánh xạ bộ nhớ (bộ nhớ tiếp giáp) không chính xác và tôi có thể bỏ qua tất cả những điều đó.

+0

Nếu bạn đã đạt được một số hiểu biết kể từ khi đặt câu hỏi của bạn, xin vui lòng gửi cho họ như một câu trả lời. Rất nhiều người đọc câu hỏi này và họ có thể sử dụng cái nhìn sâu sắc. Có rất nhiều lỗi "sẽ không sửa" xung quanh việc lấy mẫu, như http://bugs.sun.com/view_bug.do?bug_id=6893654 (mặc dù JVM segfault và trình điều khiển đồ họa bị lỗi thậm chí còn tồi tệ hơn!) Thật thú vị cách đơn giản , tính năng bản địa thanh lịch trở nên phức tạp và xấu xí trong thế giới được quản lý. –

+0

@AleksandrDubinsky bạn chính xác đúng (về thanh lịch trở nên không phù hợp) - phát hiện cuối cùng của tôi là các tệp mmap'ed không thể được tạo nhanh chóng mà không đưa ra sự bất ổn đáng kể vào hệ thống (Tôi không biết liệu tôi có làm rõ trong chuỗi này hay không) Tôi đã quản lý màn hình xanh của máy tính Windows của mình). Chi tiết này làm cho tôi muốn dính vào asyncfilechannel sử dụng cho tập tin I/O và tránh mmap tất cả cùng nhau, mặc dù peter (dưới đây) đã có thành công đáng kể trong Chronicle. –

+0

@AleksandrDubinsky Khi tôi có thể mang cả máy ảo và máy của tôi đến đầu gối bằng cách sử dụng các tệp mmapped rõ ràng "mis-use", tôi đã thực hiện với việc đi xuống đường dẫn đó. Chúng rất tao nhã và có hiệu suất tuyệt vời, nhưng từ đọc nhiều hơn tôi đã làm trên AsyncFileChannel có vẻ như bạn có thể nhận được khá gần với cùng một hiệu suất (cho phép hệ điều hành sử dụng FS và bộ điều khiển đĩa và I/O để tối ưu hóa yêu cầu). Nếu bạn thực sự muốn đi xuống con đường mmap, Peter là chuyên gia ở đây. –

Trả lời

15

Bạn có thể quan tâm https://github.com/peter-lawrey/Java-Chronicle

Trong này tôi có thể tạo nhiều bản đồ hóa bộ nhớ để cùng một tập tin (kích thước là một sức mạnh của 2 lên đến 1 GB) Các tập tin có thể được bất kỳ kích thước (lên đến kích thước của ổ cứng của bạn)

Nó cũng tạo một chỉ mục để bạn có thể tìm thấy bất kỳ bản ghi nào một cách ngẫu nhiên và mỗi bản ghi có thể có kích thước bất kỳ.

Nó có thể được chia sẻ giữa các quy trình và được sử dụng cho các sự kiện có độ trễ thấp giữa các quy trình.

Tôi đưa ra giả định rằng bạn đang sử dụng hệ điều hành 64 bit nếu bạn muốn sử dụng lượng lớn dữ liệu. Trong trường hợp này một Danh sách các MappedByteBuffer sẽ là tất cả những gì bạn cần. Nó có ý nghĩa để sử dụng các công cụ thích hợp cho công việc. ;)

tôi đã tìm thấy nó hoạt động tốt ngay cả với kích thước dữ liệu xung quanh 10x kích thước bộ nhớ chính của bạn (Tôi đã sử dụng một ổ đĩa SSD nhanh do đó, YMMV)

+0

không nhận ra bạn là tác giả của Chronicle; Cảm ơn vi đa trả lơi. Làm thế nào để bạn xử lý việc ghi vào tập tin, có phải là thông qua MBB hay bạn chỉ cần gọi trực tiếp FileChannel và mỗi khi một op đọc đến, bên ngoài giới hạn của MBB furthers, bạn chỉ cần tạo một cái mới và thêm nó vào danh sách dataBuffers? Một chi tiết cốt lõi tôi đang thiếu là những gì * rất nhiều * của các tập tin được ánh xạ lớn không để sử dụng bộ nhớ của hệ điều hành máy chủ lưu trữ. (tiếp theo bình luận tiếp theo ...) –

+0

vì có vẻ là một yêu cầu của "tiếp giáp ram" khi mem-ánh xạ một tập tin, nói rằng tôi quyết định một cái gì đó an toàn như 64 hoặc 128MB và như tập tin DB phát triển và yêu cầu đi vào cho dữ liệu vượt quá giới hạn bản đồ hiện tại tôi chỉ tạo ra nhiều hơn khi đang bay.Sau đó, chúng ta hãy nói rằng tập tin dữ liệu của tôi được 100s của GB và tôi có 100s nếu không 1000 bộ đệm byte ánh xạ mem ... nó có vẻ như tôi đang thiết lập máy chủ của tôi để bắt đầu phân trang như điên như VM được lấp đầy. Tôi muốn được nhận thức của các trường hợp gotcha và nhược điểm là mấu chốt của những gì tôi yêu cầu. –

+0

Mỗi tệp ánh xạ bộ nhớ có phần đắt tiền (tôi không có chi tiết chính xác) Tôi biết nếu bạn tạo nhiều ánh xạ 1 MB, bạn sẽ hết tài nguyên một cách nhanh chóng. Tuy nhiên nếu bạn sử dụng bộ đệm 1 GB, bạn có thể tạo tệp 8 TB. Bạn có thể xác định số tiền quá nhiều cho hệ thống của mình bằng cách tạo ra nhiều thứ nhỏ cho hệ thống của bạn (ví dụ: 4 KB) –

2

Tôi nghĩ bạn không nên lo lắng về việc nhập các tệp mmap'ping có kích thước tối đa 2GB.

Nhìn vào các nguồn của MongoDB như một ví dụ về DB sử dụng các tệp ánh xạ bộ nhớ bạn sẽ thấy nó luôn luôn ánh xạ tệp dữ liệu đầy đủ trong MemoryMappedFile::mapWithOptions() (gọi MemoryMappedFile::map()). Dữ liệu DB trải rộng trên nhiều tệp có kích thước tối đa 2GB. Ngoài ra nó preallocates tập tin dữ liệu vì vậy không cần phải remap khi dữ liệu phát triển và điều này ngăn ngừa phân mảnh tập tin. Nói chung bạn có thể truyền cảm hứng cho chính mình với mã nguồn của DB này.

+1

@Thomas Tôi đã cập nhật các liên kết nhưng tôi nghĩ rằng mã đó là khá nhiều lỗi thời, MongoDB đã trải qua rất nhiều thay đổi kể từ đó. – pingw33n

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