Bagaimana cara mengatasi batas nomor subdirektori linux?

9

Saya memiliki situs web yang akan menyimpan gambar profil pengguna. Setiap gambar disimpan dalam direktori (Linux) khusus untuk pengguna. Saat ini saya memiliki basis pelanggan 30+, yang berarti saya akan memiliki 30+ folder. Tetapi kotak Linux saya saat ini (ext2 / ext3) tidak mendukung pembuatan lebih dari 32000 direktori. Bagaimana saya bisa melewati ini? Bahkan orang-orang YouTube punya masalah yang sama, dengan thumbnail video. Tetapi mereka menyelesaikannya dengan pindah ke ReiserFS. Tidak bisakah kita memiliki solusi yang lebih baik?

Pembaruan: Ketika ditanya di IRC, orang-orang bertanya tentang memutakhirkannya ke ext4, yang memiliki batas 64 ribu dan tentu saja Anda bahkan bisa melewatinya juga . Atau peretasan kernel untuk mengubah batas.

Pembaruan: Bagaimana membagi basis pengguna ke dalam folder berdasarkan rentang userid. Berarti 1-1000 dalam satu folder, 1000-2000 di yang lain seperti itu. Ini tampaknya sederhana. Bagaimana menurutmu, kawan?

Terus terang, tidak ada cara lain?

Tidak ada-da
sumber
1
Mengapa Anda tidak ingin mengubah sistem file? Jika ini adalah batasan ext2 / 3, Anda tidak akan memiliki perubahan selain mengubah sistem file atau memecah FS saat ini menjadi FS yang lebih kecil (lebih banyak titik pemasangan berbeda).
Manuel Faux
1
Manuel: Jika dia mengubah sistem file dia mengikat FS spesifik untuk aplikasinya. Meskipun itu mungkin akhirnya menjadi jawabannya, saya akan ini mungkin merupakan masalah yang perlu diselesaikan di tingkat aplikasi. Jika Anda perlu meretas kernel atau sistem file, Anda mungkin salah jalan kecuali beberapa persyaratan yang sangat khusus.
Kyle Brandt

Jawaban:

16

Batas itu adalah per-direktori, bukan untuk keseluruhan sistem file, sehingga Anda bisa mengatasinya dengan melakukan sub-pembagian lebih lanjut. Misalnya, alih-alih memiliki semua subdirektori pengguna dalam direktori yang sama, pisahkan per dua karakter pertama dari nama tersebut sehingga Anda memiliki sesuatu seperti:

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

Bahkan yang lebih baik adalah membuat beberapa bentuk hash dari nama-nama dan menggunakannya untuk divisi. Dengan cara ini Anda akan mendapatkan penyebaran yang lebih baik di antara direktori daripada, dengan contoh huruf awal, "da" menjadi sangat penuh dan "zz" benar-benar kosong. Misalnya jika Anda mengambil nama CRC atau MD5 dan menggunakan 8 bit pertama Anda akan mendapatkan sesuatu seperti:

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

Ini dapat diperluas ke kedalaman lebih lanjut sesuai kebutuhan, misalnya seperti jika menggunakan nama pengguna bukan nilai hash:

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

Metode ini digunakan di banyak tempat seperti cache squid, untuk menyalin contoh Ludwig, dan cache lokal browser web.

Satu hal penting yang perlu diperhatikan adalah bahwa dengan ext2 / 3 Anda akan mulai mengenai masalah kinerja sebelum Anda mendekati batas 32.000, karena direktori dicari secara linear. Pindah ke sistem file lain (ext4 atau reiser misalnya) akan menghapus inefisiensi ini (reiser mencari direktori dengan algoritma binary-split sehingga direktori lama ditangani jauh lebih efisien, ext4 mungkin juga melakukannya) serta batas tetap per direktori.

David Spillett
sumber
Baru saja memperbarui deskripsi pertanyaan untuk memasukkan ini: "Pembaruan: Bagaimana kalau membagi basis pengguna ke dalam folder berdasarkan rentang userid. Membuat 1-1000 dalam satu folder, 1000-2000 dalam yang lain seperti itu. Ini tampaknya sederhana. Apa katamu? "
Tidak ada-da
1
Itu akan bekerja dengan baik, dan akan lebih efisien daripada hash, jika pengguna umumnya diidentifikasi dengan ID pengguna, bukan (atau juga) nama pengguna. Meskipun jika Anda selalu merujuk mereka dengan nama di tempat lain dalam sistem Anda harus menambahkan nama tambahan-> id pencarian di semua tempat.
David Spillett
David terima kasih! Saya mencoba solusi yang berbeda. Saya membuat hampir 4 folder dengan kisaran 1-30000, 30000-60000 dll. Saya pikir mendapatkan file dari direktori besar akan memakan waktu lebih lama daripada dari direktori yang memiliki 1000 file (pendekatan sebelumnya). Apa yang kamu katakan?
Tidak ada-da
1
Itu tergantung pada sistem file. Jika Anda menggunakan ext2 atau ext3 maka saya akan merekomendasikan jauh lebih kecil dari 30.000 per direktori. Beberapa alat mengeluarkan peringatan sekitar 10.000. Anda dapat mengaktifkan pengindeksan direktori di ext3 / 4 untuk membantu: tune2fs -O dir_index / dev / <volumename> tetapi hanya menjaga jumlah objek dalam direktori lebih rendah (beberapa ribu atau kurang?) Adalah apa yang saya sarankan di sini .
David Spillett
@ Maddy, Anda menginginkan solusi ini karena keterbatasan lain tentang cara Ext2 / 3 menangani sejumlah besar file. Lihat serverfault.com/questions/43133/… untuk beberapa detail. Memecah nama menjadi bucket-as-subdirectories mengurangi masalah lain yang pada akhirnya akan Anda hadapi. Perhatikan bahwa ini adalah strategi yang sama yang digunakan Squid ketika mengatur cache objek untuk pertama kalinya - misalnya, masing-masing 64 direktori dengan 64 direktori di dalamnya, hanya sebagai contoh.
Avery Payne
7

Jika Anda terikat ke ext2 / ext3 satu-satunya kemungkinan yang saya lihat adalah mempartisi data Anda. Temukan kriteria yang membagi data Anda menjadi potongan-potongan yang dapat dikelola dengan ukuran yang sama.

Jika hanya tentang gambar profil yang akan saya lakukan:

  1. Gunakan hash (misalnya SHA1) dari gambar
  2. Gunakan SHA1 sebagai nama file dan direktori

Sebagai contoh, cache SQUID melakukannya dengan cara ini:

f / 4b / 353ac7303854033

Direktori level atas adalah hex-digit pertama, level kedua adalah dua hex-digit berikutnya, dan nama file adalah hex-digit yang tersisa.

Ludwig Weinzierl
sumber
2

Tidak bisakah kita memiliki solusi yang lebih baik?

Anda memang memiliki solusi yang lebih baik - gunakan sistem file yang berbeda, ada banyak yang tersedia, banyak di antaranya dioptimalkan untuk tugas yang berbeda. Seperti yang Anda tunjukkan, ReiserFS dioptimalkan untuk menangani banyak file dalam direktori.

Lihat di sini untuk perbandingan sistem file.

Hanya senang Anda tidak terjebak dengan NTFS yang benar-benar buruk untuk banyak file di direktori. Saya akan merekomendasikan JFS sebagai pengganti jika Anda tidak suka menggunakan ext4 FS yang relatif baru (tetapi tampaknya stabil).

gbjbaanb
sumber
Apakah Anda memiliki tautan yang baik ke kinerja sistem file NTFS?
Thorbjørn Ravn Andersen
ya, terlepas dari pengalaman pribadi dengan aplikasi yang terlalu lama membuat file baru di direktori .. (butuh waktu berjam-jam untuk menghapus semuanya), dan kinerja subversi meningkat dengan membatasi jumlah file dalam direktori menjadi 1000. Atau baca : support.microsoft.com/kb/130694 Saya tidak berpikir mereka pernah "memperbaiki" ini karena masih tercatat sebagai perf. tweak untuk NTFS.
gbjbaanb
1

Apakah gambar profil kecil? Bagaimana dengan memasukkannya ke dalam basis data dengan data profil lainnya? Ini mungkin bukan pilihan terbaik untuk Anda, tetapi patut dipertimbangkan ...

Berikut adalah whitepaper Microsoft (yang lebih lama) tentang topik: Untuk BLOB atau bukan BLOB .

Kyle Brandt
sumber
1

Saya telah meretas galeri web kecil, di mana saya berakhir dengan variasi masalah ini; Saya "hanya" memiliki ~ 30.000 gambar di direktori cache, yang ternyata sangat lambat (ext2 menggunakan daftar yang ditautkan untuk indeks direktori, seperti yang saya ingat).

Saya akhirnya melakukan sesuatu seperti ini:

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

Ini akan mempartisi data dalam 256 direktori, yang memberikan pencarian direktori cepat untuk masing-masing dari tiga level.

  • Saya telah memilih untuk menggunakan MD5 daripada SHA-1, karena MD5 menjamin output yang berbeda jika Anda mengubah 12 bit 32, jadi saya merasa cocok untuk hash nama pengguna, direktori dan hal-hal pendek lainnya. Dan itu cepat, juga ...
  • Saya tidak menyertakan seluruh hash, karena akan menghasilkan direktori terlalu banyak dan secara efektif membuang cache-disk berulang-ulang.
Morten Siebuhr
sumber
1
Anda mungkin bisa menggunakan hash sederhana seperti CRC, sebagai hash tidak perlu cryptographically kuat seperti MD5 atau SHA ... tapi perbedaan kinerja mungkin diabaikan pula ...
sleske
0

Bukan jawaban langsung untuk masalah Anda, tetapi sesuatu yang harus diperhatikan untuk referensi di masa mendatang adalah proyek terkait OpenBSD yang disebut 'Epitome'

Epitome adalah mesin yang menyediakan layanan Penyimpanan Instans Tunggal, Penyimpanan Beralamat Konten, dan Deduplikasi.

Semua data Anda disimpan di penyimpanan data sebagai blok hash, menghapus blok non-unik untuk mengurangi penggunaan ruang, dan memungkinkan Anda untuk melupakan mekanisme penyimpanan karena Anda hanya dapat meminta konten dari penyimpanan data oleh UUID.

Epitome saat ini bersifat eksperimental, tetapi sesuatu yang harus diperhatikan untuk masa depan.

Melenguh
sumber
0

Secara umum Anda ingin menghindari memiliki direktori dengan banyak file / direktori di dalamnya. Alasan utama adalah bahwa ekspansi wildcard pada baris perintah, akan menghasilkan kesalahan "Terlalu banyak argumen" yang mengakibatkan banyak rasa sakit ketika mencoba untuk bekerja dengan direktori ini.

Carilah solusi yang membuat pohon lebih dalam tetapi lebih sempit, misalnya dengan membuat subfolder seperti yang telah dijelaskan orang lain.

Thorbjørn Ravn Andersen
sumber
0

Kami memiliki masalah serupa, solusinya - seperti yang disebutkan sebelumnya - adalah membuat hierarki direktori.

Tentu saja jika Anda memiliki aplikasi kompleks yang bergantung pada struktur direktori datar, Anda mungkin perlu banyak perbaikan. Jadi, baik untuk mengetahui bahwa ada solusi, gunakan symlink yang tidak memiliki batas 32k yang disebutkan. Maka Anda punya banyak waktu untuk memperbaiki aplikasi ...

Karoly Horvath
sumber
0

Mengapa tidak menggunakan pendekatan timestamp, dan kemudian memiliki opsi overflow.

Sebagai contoh

Jadi katakanlah cap waktu Anda adalah: 1366587600

Abaikan 2 digit terakhir (atau hanya sedikit konyol). Pisahkan cap ke dalam kumpulan 4 (jumlah direktori tidak boleh lebih dari 9999 - jika Anda mau, Anda bisa memisahkannya secara berbeda).

Ini seharusnya memberi Anda sesuatu seperti ini:

/files/1366/5876/

Kemudian juga periksa jumlah dalam dir sebelum mengunggah, jika mendapatkan jumlah besar unggahan (yaitu 32000 + per 100 detik), kemudian iterasikan direktori dengan huruf kedua atau huruf, misalnya:

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

atau

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

Kemudian catat stempel waktu + huruf atau kode jalur lengkap ke db bersama dengan pengguna dan Anda harus mengaturnya.

pathstamp: 1366587600 atau 13665876a (jika Anda menggunakan huruf).

Ini memang berakhir dengan sejumlah besar direktori, tetapi bisa sangat berguna untuk menangani revisi file. Misalnya, jika pengguna ingin menggunakan gambar profil baru, Anda masih memiliki versi timestamped lama dari yang lebih tua jika mereka ingin membatalkan perubahan (tidak hanya tertulis berlebihan).

Fireacer
sumber
0

Saya sarankan memutuskan berapa banyak subdirektori maksimum yang Anda inginkan (atau dapat) miliki di folder induk.

Maka Anda perlu mengonversi id pengguna Anda sehingga mereka mulai dari 1.

Maka Anda dapat melakukan: modulo = currentId % numberOfSubdirectories

modulosekarang akan berisi nomor subdirektori Anda yang tidak akan pernah lebih besar dari yang numberOfSubdirectoriesAnda pilih.

Lakukan apa pun yang Anda inginkan dengan modulo, hash, misalnya.

Juga subdirektori cara ini akan diisi secara linear.

vitro
sumber