Làm thế nào để giải quyết giới hạn số lượng thư mục con linux?


9

Tôi có một trang web sẽ lưu trữ hình ảnh hồ sơ người dùng. Mỗi hình ảnh được lưu trữ trong một thư mục (Linux) dành riêng cho người dùng. Hiện tại tôi có một cơ sở khách hàng từ 30+ trở lên, có nghĩa là tôi sẽ có hơn 30 thư mục. Nhưng hộp Linux hiện tại của tôi (ext2 / ext3) không hỗ trợ tạo hơn 32000 thư mục. Làm thế nào để tôi vượt qua điều này? Ngay cả những người trên YouTube cũng gặp vấn đề tương tự, với hình thu nhỏ của video. Nhưng họ đã giải quyết nó bằng cách chuyển sang ReiserFS. Chúng ta có thể có một giải pháp tốt hơn không?

Cập nhật: Khi được hỏi trong IRC, mọi người đã hỏi về việc nâng cấp nó lên ext4, có giới hạn 64k và tất nhiên bạn cũng có thể vượt qua điều đó . Hoặc hack kernel để thay đổi giới hạn.

Cập nhật: Cách chia cơ sở người dùng thành các thư mục dựa trên phạm vi người dùng. Có nghĩa là 1-1000 trong một thư mục, 1000-2000 trong thư mục khác như thế. Điều này có vẻ đơn giản. Các bạn nói gì?

Thành thật mà nói, không có cách nào khác?


1
Tại sao bạn không muốn thay đổi hệ thống tập tin? Nếu đây là giới hạn của ext2 / 3, bạn sẽ không có bất kỳ thay đổi nào khác ngoài việc thay đổi hệ thống tệp hoặc tách FS hiện tại thành các FS nhỏ hơn (nhiều điểm gắn khác nhau hơn).
Manuel Faux

1
Manuel: Nếu anh ấy thay đổi hệ thống tập tin, anh ấy đang buộc một FS cụ thể vào ứng dụng của mình. Mặc dù đó có thể là câu trả lời, nhưng đây có lẽ là một vấn đề cần được giải quyết ở cấp ứng dụng. Nếu bạn cần hack kernel hoặc hệ thống tập tin, có lẽ bạn đang đi sai đường dẫn trừ khi một số yêu cầu rất đặc biệt.
Kyle Brandt

Câu trả lời:


16

Giới hạn đó là cho mỗi thư mục, không phải cho toàn bộ hệ thống tập tin, vì vậy bạn có thể làm việc xung quanh nó bằng cách phân chia các thứ khác. Chẳng hạn, thay vì có tất cả các thư mục con người dùng trong cùng một thư mục, hãy chia chúng cho hai ký tự đầu tiên của tên để bạn có một cái gì đó như:

top_level_dir
|---aa
|   |---aardvark1
|   |---aardvark2
|---da
|   |---dan
|   |---david
|---do
    |---don

Thậm chí tốt hơn là tạo ra một số dạng băm của tên và sử dụng nó cho phân chia. Bằng cách này, bạn sẽ có được sự lan truyền tốt hơn giữa các thư mục thay vì, với ví dụ về các chữ cái ban đầu, "da" rất đầy đủ và "zz" hoàn toàn trống rỗng. Chẳng hạn, nếu bạn lấy tên CRC hoặc MD5 và sử dụng 8 bit đầu tiên, bạn sẽ nhận được đôi khi như:

top_level_dir
|---00
|   |---some_username
|   |---some_username
|---01
|   |---some_username
...
|---FF
|   |---some_username

Điều này có thể được mở rộng đến độ sâu hơn nữa nếu cần, ví dụ như vậy nếu sử dụng tên người dùng không phải là giá trị băm:

top_level_dir
|---a
|   |---a
|       |---aardvark1
|       |---aardvark2
|---d
    |---a
    |   |---dan
    |   |---david
    |---o
        |---don

Phương pháp này được sử dụng ở nhiều nơi như bộ đệm của mực, để sao chép ví dụ của Ludwig và bộ đệm cục bộ của trình duyệt web.

Một điều quan trọng cần lưu ý là với ext2 / 3, bạn sẽ bắt đầu gặp các vấn đề về hiệu suất trước khi bạn tiến gần đến giới hạn 32.000, vì các thư mục được tìm kiếm tuyến tính. Di chuyển sang hệ thống tập tin khác (ví dụ ext4 hoặc reiser) sẽ loại bỏ tính không hiệu quả này (thư mục tìm kiếm lại với một algorimth phân chia nhị phân để các thư mục dài được xử lý hiệu quả hơn nhiều, ext4 cũng có thể làm như vậy) cũng như giới hạn cố định cho mỗi thư mục.


Chỉ cần cập nhật mô tả câu hỏi để bao gồm điều này: "Cập nhật: Cách chia cơ sở người dùng thành các thư mục dựa trên phạm vi người dùng. Chuyển 1-1000 trong một thư mục, 1000-2000 trong thư mục khác như thế. Điều này có vẻ đơn giản. bạn có nói không
Không-da

1
Điều đó sẽ hoạt động tốt và sẽ hiệu quả hơn hàm băm, nếu người dùng thường được xác định bởi ID người dùng thay vì (hoặc cũng như) tên người dùng. Mặc dù nếu bạn luôn gọi chúng theo tên ở những nơi khác trong hệ thống, bạn sẽ phải thêm tên-> tra cứu id ở khắp mọi nơi.
David Spillett

Cảm ơn bạn David! Tôi đã thử giải pháp thậm chí khác nhau. Tôi đã tạo hầu như 4 thư mục với phạm vi 1-30000, 30000-60000, v.v. Tôi nghĩ rằng việc lấy một tệp từ một thư mục lớn như vậy sẽ mất nhiều thời gian hơn từ một thư mục có 1000 tệp (cách tiếp cận trước đó). bạn nói gì?
Không-da

1
Điều đó phụ thuộc vào hệ thống tập tin. Nếu bạn đang sử dụng ext2 hoặc ext3 thì tôi khuyên bạn nên nhỏ hơn 30.000 mỗi thư mục. Một số công cụ đưa ra cảnh báo khoảng 10.000. Bạn có thể bật lập chỉ mục thư mục trong ext3 / 4 để trợ giúp: Tune2fs -O dir_index / dev / <volumename> nhưng chỉ giữ số lượng đối tượng trong một thư mục thấp hơn (vài nghìn hoặc ít hơn?) Là những gì tôi khuyên dùng ở đây .
David Spillett

@Maddy, bạn muốn giải pháp này do những hạn chế khác về cách Ext2 / 3 xử lý số lượng lớn tệp. Xem serverfault.com/questions/43133/ trên để biết thêm chi tiết. Việc chia nhỏ các tên thành các thư mục con như các thư mục con làm giảm bớt các vấn đề khác mà cuối cùng bạn sẽ gặp phải. Lưu ý rằng đây là chiến lược tương tự mà Squid sử dụng khi thiết lập bộ đệm đối tượng lần đầu tiên - ví dụ: 64 thư mục mỗi thư mục có 64 thư mục bên trong chúng, giống như một ví dụ.
Avery Payne

7

Nếu bạn bị ràng buộc với ext2 / ext3, khả năng duy nhất tôi thấy là phân vùng dữ liệu của bạn. Tìm một tiêu chí phân chia dữ liệu của bạn thành các phần có thể quản lý có kích thước tương tự.

Nếu đó chỉ là về hình ảnh hồ sơ tôi sẽ làm:

  1. Sử dụng hàm băm (ví dụ SHA1) của hình ảnh
  2. Sử dụng SHA1 làm tên tệp và thư mục

Ví dụ: bộ đệm SQUID thực hiện theo cách này:

f / 4b / 353ac7303854033

Thư mục cấp cao nhất là chữ số hex đầu tiên, cấp thứ hai là hai chữ số hex tiếp theo và tên tệp là các chữ số hex còn lại.


2

Không thể chúng ta có một giải pháp tốt hơn?

Bạn có một giải pháp tốt hơn - sử dụng một hệ thống tệp khác, có sẵn rất nhiều, nhiều trong số đó được tối ưu hóa cho các tác vụ khác nhau. Như bạn đã chỉ ra ReiserFS được tối ưu hóa để xử lý nhiều tệp trong một thư mục.

Xem ở đây để so sánh các hệ thống tập tin.

Hãy vui mừng vì bạn không bị mắc kẹt với NTFS, thứ thực sự đáng sợ cho rất nhiều tệp trong một thư mục. Tôi muốn giới thiệu JFS thay thế nếu bạn không thích sử dụng ext4 FS tương đối mới (nhưng dường như ổn định).


Bạn có liên kết tốt đến hiệu suất hệ thống tập tin NTFS?
Thorbjørn Ravn Andersen

có, ngoài kinh nghiệm cá nhân với một ứng dụng còn quá lâu để tạo các tệp mới trong một thư mục .. (mất hàng giờ để xóa tất cả) và tăng hiệu suất lật đổ bằng cách giới hạn số lượng tệp trong một thư mục xuống 1000. Hoặc đọc : support.microsoft.com/kb/130694 Tôi không nghĩ họ đã từng "sửa" cái này vì nó vẫn được ghi nhận là một sự hoàn hảo. chỉnh cho NTFS.
gbjbaanb

1

Là hình ảnh hồ sơ nhỏ? Điều gì về việc đưa nó vào cơ sở dữ liệu với phần còn lại của dữ liệu hồ sơ? Đây có thể không phải là lựa chọn tốt nhất cho bạn, nhưng đáng để xem xét ...

Đây là một whitepaper của Microsoft (cũ hơn) về chủ đề: Đến BLOB hoặc không BLOB .


1

Tôi đã hack cùng một phòng trưng bày web nhỏ, nơi tôi đã kết thúc với một biến thể của vấn đề này; Tôi "chỉ" có ~ 30.000 hình ảnh trong thư mục bộ đệm, hóa ra khá chậm (ext2 sử dụng danh sách được liên kết cho các chỉ mục thư mục, như tôi nhớ).

Tôi cuối cùng đã làm một cái gì đó dọc theo những dòng này:

def key2path(key):
    hash = md5(key)
    return os.path.join(hash[0], hash[1], key)

Điều này sẽ phân vùng dữ liệu trong 256 thư mục, giúp tìm kiếm thư mục nhanh cho mỗi trong ba cấp độ.

  • Tôi đã chọn sử dụng MD5 trên SHA-1, vì MD5 đảm bảo đầu ra khác nếu bạn thay đổi bất kỳ 12 bit nào của 32, vì vậy tôi thấy nó phù hợp để băm tên người dùng, thư mục và các nội dung ngắn khác. Và nó cũng nhanh thôi ...
  • Tôi không bao gồm toàn bộ hàm băm, vì nó sẽ tạo ra quá nhiều thư mục và làm hỏng bộ đệm đĩa một cách hiệu quả.

1
Bạn có thể có thể sử dụng hàm băm đơn giản hơn như CRC, vì hàm băm không cần mã hóa mạnh như MD5 hoặc SHA ... nhưng dù sao thì sự khác biệt về hiệu suất có thể không đáng kể ...
sleske

0

Không phải là một câu trả lời ngay lập tức cho vấn đề của bạn, nhưng một cái gì đó để xem để tham khảo trong tương lai là dự án được liên kết OpenBSD có tên là 'Epitome'

Epitome là một công cụ cung cấp dịch vụ lưu trữ đơn lẻ, lưu trữ địa chỉ nội dung và dịch vụ chống trùng lặp.

Tất cả dữ liệu của bạn được lưu trữ trong kho lưu trữ dữ liệu dưới dạng các khối băm, loại bỏ các khối không duy nhất để cắt giảm mức sử dụng không gian và cho phép bạn quên cơ chế lưu trữ vì bạn có thể yêu cầu nội dung từ kho lưu trữ dữ liệu bằng UUID.

Epitome hiện đang thử nghiệm, nhưng một cái gì đó để xem cho tương lai.


0

Nói chung, bạn muốn tránh có các thư mục có số lượng lớn tệp / thư mục trong đó. Lý do chính là việc mở rộng ký tự đại diện trên dòng lệnh, sẽ dẫn đến lỗi "Quá nhiều đối số" dẫn đến nhiều đau đớn khi cố gắng làm việc với các thư mục này.

Đi đến một giải pháp làm cho cây sâu hơn nhưng hẹp hơn, ví dụ bằng cách tạo các thư mục con như những người khác đã mô tả.


0

Chúng tôi đã có một vấn đề tương tự, giải pháp - như đã đề cập trước đây - là tạo ra một hệ thống phân cấp các thư mục.

Tất nhiên, nếu bạn có một ứng dụng phức tạp dựa trên cấu trúc thư mục phẳng, có lẽ bạn sẽ cần rất nhiều bản vá. Vì vậy, thật tốt khi biết rằng có một cách giải quyết, hãy sử dụng các liên kết tượng trưng không có giới hạn 32k được đề cập. Sau đó, bạn có nhiều thời gian để sửa ứng dụng ...


0

Tại sao không sử dụng một cách tiếp cận dấu thời gian, và sau đó có một tùy chọn tràn.

Ví dụ

Vì vậy, giả sử dấu thời gian của bạn là: 1366587600

Bỏ qua 2 chữ số cuối (nếu không nó chỉ hơi vô lý). Tách tem thành bộ 4 (số lượng thư mục không nên đạt hơn 9999 - nếu bạn muốn, bạn có thể tách nó theo cách khác).

Điều này sẽ để lại cho bạn một cái gì đó như thế này:

/files/1366/5876/

Sau đó, cũng kiểm tra số lượng trong thư mục trước khi tải lên, nếu nó nhận được số lượng tải lên lớn (ví dụ 32000 + trên 100 giây), sau đó lặp lại thư mục bằng giây hoặc một chữ cái, ví dụ:

/files/1366/5876/a/file.txt

hoặc là

/files/1366/5876/00/file.txt

Sau đó đăng nhập dấu thời gian + chữ cái hoặc mã đường dẫn đầy đủ vào một db cùng với người dùng và bạn sẽ được đặt.

pathstamp: 1366587600 hoặc 13665876a (nếu bạn sử dụng chữ cái).

Điều này không kết thúc với một số lượng lớn các thư mục, nhưng nó có thể thực sự hữu ích để xử lý các sửa đổi tập tin. Ví dụ: nếu người dùng muốn sử dụng ảnh hồ sơ mới, bạn vẫn có phiên bản cũ được đánh dấu thời gian cũ của trường hợp cũ hơn mà họ muốn hoàn tác các thay đổi (không chỉ là ghi đè).


0

Tôi đề nghị quyết định có bao nhiêu thư mục con tối đa bạn muốn (hoặc có thể) có trong thư mục mẹ.

Sau đó, bạn cần chuyển đổi id người dùng của mình để họ bắt đầu từ 1.

Sau đó, bạn có thể làm: modulo = currentId % numberOfSubdirectories

modulobây giờ sẽ chứa số thư mục con của bạn sẽ không bao giờ lớn hơn số numberOfSubdirectoriesbạn đã chọn.

Làm bất cứ điều gì bạn muốn với modulo, băm nó, ví dụ.

Ngoài ra, cách này các thư mục con sẽ được điền tuyến tính.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.