วิธีแก้ข้อ จำกัด จำนวนลินุกซ์ไดเรกทอรีย่อย?


9

ฉันมีเว็บไซต์ที่จะเก็บภาพโปรไฟล์ผู้ใช้ แต่ละภาพจะถูกเก็บไว้ในไดเรกทอรี (Linux) เฉพาะสำหรับผู้ใช้ ขณะนี้ฉันมีฐานลูกค้า 30+ ซึ่งหมายความว่าฉันจะมี 30+ โฟลเดอร์ แต่กล่อง Linux ปัจจุบันของฉัน (ext2 / ext3) ไม่รองรับการสร้างไดเรกทอรีมากกว่า 32000 รายการ ฉันจะผ่านสิ่งนี้ได้อย่างไร แม้แต่พวก YouTube ก็มีปัญหาเดียวกันกับภาพขนาดย่อของวิดีโอ แต่พวกเขาแก้ไขมันโดยย้ายไปที่ ReiserFS เรามีทางออกที่ดีกว่าไม่ได้เหรอ?

อัปเดต: เมื่อถูกถามใน IRC ผู้คนถูกถามเกี่ยวกับการอัปเกรดเป็น ext4 ซึ่งมีขีด จำกัด 64k และแน่นอนว่าคุณสามารถผ่านมาได้เช่นกัน หรือเคอร์เนลแฮ็คเพื่อเปลี่ยนขีด จำกัด

อัปเดต: วิธีแยกฐานผู้ใช้ออกเป็นโฟลเดอร์ตามช่วงหมายเลขผู้ใช้ ความหมาย 1-1000 ในหนึ่งโฟลเดอร์ 1,000-2000 ในอีกอันหนึ่ง ดูเหมือนจะง่าย คุณพูดว่าอะไรนะ

ตรงไปตรงมาไม่มีทางอื่นอีกแล้วเหรอ?


1
ทำไมคุณไม่ต้องการเปลี่ยนระบบไฟล์? หากนี่เป็นข้อ จำกัด ของ ext2 / 3 คุณจะไม่มีการเปลี่ยนแปลงอื่นใดนอกจากเปลี่ยนระบบไฟล์หรือแยก FS ปัจจุบันออกเป็น FS ที่เล็กกว่า (จุดเชื่อมต่อที่แตกต่างกัน)
Manuel Faux

1
มานูเอล: ถ้าเขาเปลี่ยนระบบไฟล์เขาจะผูกเฉพาะ FS กับแอปพลิเคชันของเขา แม้ว่านั่นอาจจะเป็นคำตอบก็ตามฉันก็น่าจะเป็นปัญหาที่ต้องแก้ไขในระดับแอปพลิเคชัน หากคุณต้องการแฮ็คเคอร์เนลหรือระบบไฟล์คุณอาจผิดไปเสียเว้นแต่มีความต้องการพิเศษบางอย่าง
Kyle Brandt

คำตอบ:


16

ข้อ จำกัด นั้นเป็นไดเรกทอรีต่อไม่ใช่สำหรับระบบไฟล์ทั้งหมดดังนั้นคุณสามารถหลีกเลี่ยงได้โดยการแบ่งย่อยสิ่งเพิ่มเติม ตัวอย่างเช่นแทนที่จะมีไดเรกทอรีย่อยของผู้ใช้ทั้งหมดในไดเรกทอรีเดียวกันแยกพวกเขาต่อสองตัวอักษรแรกของชื่อเพื่อให้คุณมีสิ่งที่ชอบ:

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

ยิ่งไปกว่านั้นคือการสร้างแฮชบางรูปแบบของชื่อและใช้สำหรับการแบ่ง วิธีนี้คุณจะได้รับการกระจายที่ดีขึ้นในไดเรกทอรีแทนที่จะเป็นตัวอย่างตัวอักษรเริ่มต้น "da" เต็มและ "zz" ว่างเปล่าอย่างสมบูรณ์ ตัวอย่างเช่นถ้าคุณใช้ CRC หรือ MD5 ชื่อและใช้ 8 บิตแรกคุณจะได้รับเช่น:

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

สิ่งนี้สามารถขยายไปสู่ความลึกเพิ่มเติมได้ตามต้องการเช่นถ้าใช้ชื่อผู้ใช้ไม่ใช่ค่าแฮช:

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

วิธีนี้ใช้ในหลาย ๆ ที่เช่นแคชของปลาหมึกเพื่อคัดลอกตัวอย่างของลุดวิกและแคชท้องถิ่นของเว็บเบราว์เซอร์

สิ่งหนึ่งที่สำคัญที่ควรทราบคือเมื่อใช้ ext2 / 3 คุณจะเริ่มมีปัญหาด้านประสิทธิภาพก่อนที่จะถึงขีด จำกัด 32,000 ต่อไปเนื่องจากไดเรคทอรีจะค้นหาแบบเชิงเส้น การย้ายไปยังระบบไฟล์อื่น (เช่น ext4 หรือ reiser) จะลบความไร้ประสิทธิภาพนี้ (ผู้สร้างใหม่จะค้นหาไดเรกทอรีที่มี algorimth แบบแยกส่วนดังนั้นไดเรกทอรีที่มีความยาวจะได้รับการจัดการอย่างมีประสิทธิภาพมากขึ้น ext4 อาจทำได้เช่นกัน)


เพิ่งอัปเดตคำอธิบายคำถามเพื่อรวมสิ่งนี้: "อัปเดต: วิธีแยกฐานผู้ใช้ออกเป็นโฟลเดอร์ตามช่วงหมายเลขผู้ใช้ระหว่าง 1 ถึง 1,000 ในโฟลเดอร์เดียว, 1,000-2,000 รายการในรูปแบบอื่น ๆ ดูเหมือนว่าจะง่าย คุณพูดเหรอ
None-da

1
สิ่งนี้จะทำงานได้ดีและจะมีประสิทธิภาพมากกว่าแฮชหากผู้ใช้ระบุ ID ผู้ใช้โดยทั่วไปแทนชื่อผู้ใช้ (หรือรวมถึง) แม้ว่าคุณจะอ้างถึงพวกเขาตามชื่อที่อื่นในระบบคุณจะต้องเพิ่มชื่อพิเศษ -> การค้นหา id ทั่วสถานที่
David Spillett

ขอบคุณเดวิด! ฉันพยายามแก้ปัญหาที่แตกต่างกัน ฉันสร้างแทบ 4 โฟลเดอร์ที่มีช่วง 1-30000, 30000-60000 เป็นต้นฉันคิดว่าการรับไฟล์จากไดเรกทอรีขนาดใหญ่เช่นนั้นจะใช้เวลามากกว่าจากไดเรกทอรีที่มี 1,000 ไฟล์ (ก่อนหน้านี้) พูดว่าอะไรนะ?
None-da

1
ขึ้นอยู่กับระบบไฟล์ หากคุณใช้ ext2 หรือ ext3 ฉันก็จะแนะนำน้อยกว่า 30,000 ต่อไดเรกทอรี เครื่องมือบางอย่างออกคำเตือนประมาณ 10,000 คุณสามารถเปิดการทำดัชนีไดเรกทอรีใน ext3 / 4 เพื่อช่วย: tune2fs -O dir_index / dev / <volumename> แต่เพียงเก็บจำนวนของวัตถุในไดเรกทอรีที่ต่ำกว่า (สองสามพันหรือน้อยกว่า) เป็นสิ่งที่ฉันแนะนำที่นี่ .
David Spillett

@Maddy คุณต้องการโซลูชันนี้เนื่องจากข้อ จำกัด อื่น ๆ เกี่ยวกับวิธีที่ Ext2 / 3 จัดการกับไฟล์จำนวนมาก ดูserverfault.com/questions/43133/…เพื่อดูรายละเอียด การแบ่งชื่อออกเป็น buckets-as-subdirectories ช่วยลดปัญหาอื่น ๆ ที่คุณอาจพบเจอในที่สุด โปรดทราบว่านี่เป็นกลยุทธ์เดียวกับที่ Squid ใช้เมื่อตั้งค่าแคชวัตถุเป็นครั้งแรก - ตัวอย่างเช่น 64 ไดเรกทอรีแต่ละรายการที่มี 64 ไดเรกทอรีอยู่ภายในนั้นเป็นตัวอย่าง
Avery Payne

7

หากคุณผูกพันกับ ext2 / ext3 ความเป็นไปได้เพียงอย่างเดียวที่ฉันเห็นคือการแบ่งพาร์ติชันข้อมูลของคุณ ค้นหาเกณฑ์ที่แยกข้อมูลของคุณเป็นกลุ่มที่จัดการได้ที่มีขนาดใกล้เคียงกัน

หากเป็นเพียงเกี่ยวกับภาพโปรไฟล์ที่ฉันต้องการ:

  1. ใช้แฮช (เช่น SHA1) ของภาพ
  2. ใช้ SHA1 เป็นชื่อไฟล์และไดเรกทอรี

ตัวอย่างเช่นแคช SQUID ทำเช่นนี้:

f / 4b / 353ac7303854033

ไดเรกทอรีระดับบนสุดคือเลขฐานสิบหกตัวแรกระดับที่สองคือเลขฐานสิบหกสองตัวถัดไปและชื่อไฟล์คือเลขฐานสิบหกที่เหลือ


2

เรามีทางออกที่ดีกว่าได้ไหม?

คุณมีวิธีแก้ปัญหาที่ดีกว่า - ใช้ระบบไฟล์ที่แตกต่างกันมีให้เลือกมากมายซึ่งส่วนใหญ่จะเหมาะสำหรับงานที่แตกต่างกัน ดังที่คุณได้ชี้ให้เห็นว่า ReiserFS นั้นได้รับการปรับแต่งสำหรับการจัดการไฟล์จำนวนมากในไดเรกทอรี

ดูที่นี่เพื่อเปรียบเทียบระบบไฟล์

เพียงแค่ดีใจที่คุณไม่ได้ติดอยู่กับ NTFS ซึ่งเป็นสุดยอดอย่างแท้จริงสำหรับไฟล์จำนวนมากในไดเรกทอรี ฉันขอแนะนำให้ใช้ JFS แทนหากคุณไม่คิดที่จะใช้ ext4 FS ที่ค่อนข้างใหม่


คุณมีลิงค์ที่ดีต่อประสิทธิภาพของระบบไฟล์ NTFS หรือไม่?
Thorbjørn Ravn Andersen

ใช่นอกเหนือจากประสบการณ์ส่วนตัวกับแอพที่ทิ้งไว้นานเกินไปในการสร้างไฟล์ใหม่ในไดเรกทอรี .. (ใช้เวลาลบหลายชั่วโมง) และประสิทธิภาพการโค่นล้มเพิ่มขึ้นด้วยการ จำกัด จำนวนไฟล์ในไดเรกทอรีที่ 1,000 หรืออ่าน : support.microsoft.com/kb/130694ฉันไม่คิดว่าพวกเขาจะ "แก้ไข" สิ่งนี้เพราะมันยังบันทึกไว้ว่าสมบูรณ์แบบ ปรับแต่งสำหรับ NTFS
gbjbaanb

1

รูปโปรไฟล์นั้นเล็กหรือไม่? สิ่งที่เกี่ยวกับการวางไว้ในฐานข้อมูลส่วนที่เหลือของข้อมูลโปรไฟล์หรือไม่ นี่อาจไม่ใช่ตัวเลือกที่ดีที่สุดสำหรับคุณ แต่ควรพิจารณา ...

นี่คือ (เก่า) ไมโครซอฟท์เอกสารในหัวข้อ: การหยดหรือไม่ที่จะหยด


1

ฉันแฮ็กเว็บแกลเลอรี่ขนาดเล็กด้วยกันซึ่งฉันได้พบกับการเปลี่ยนแปลงของปัญหานี้ ฉัน "เท่านั้น" มี ~ 30,000 ภาพในไดเรกทอรีแคชซึ่งกลายเป็นค่อนข้างช้า (ext2 ใช้รายการที่เชื่อมโยงสำหรับดัชนีไดเรกทอรีที่ฉันจำได้)

ในที่สุดฉันก็ลงมือทำบางสิ่งตามบรรทัดเหล่านี้:

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

ซึ่งจะแบ่งพาร์ติชันข้อมูลเป็น 256 ไดเรกทอรีซึ่งให้การค้นหาไดเรกทอรีอย่างรวดเร็วสำหรับแต่ละสามระดับ

  • ฉันเลือกที่จะใช้ MD5 ผ่าน SHA-1 เนื่องจาก MD5 รับประกันผลลัพธ์ที่แตกต่างกันถ้าคุณเปลี่ยน 12 บิตจาก 32 บิตดังนั้นฉันคิดว่ามันเหมาะสมกับชื่อผู้ใช้ไดเรกทอรีและสิ่งอื่น ๆ และมันก็รวดเร็วเช่นกัน ...
  • ฉันไม่รวมแฮชทั้งหมดเนื่องจากจะสร้างไดเรกทอรีมากเกินไปและทิ้งขยะแคชในดิสก์อย่างมีประสิทธิภาพ

1
คุณอาจจะใช้กัญชาง่ายเช่นซีอาร์ซีเป็นกัญชาไม่ได้จะต้องมีการเข้ารหัสที่แข็งแกร่งเช่น MD5 หรือ SHA ... แต่แตกต่างประสิทธิภาพน่าจะเป็นอยู่แล้วเล็กน้อย ...
sleske

0

ไม่ใช่คำตอบสำหรับปัญหาของคุณในทันที แต่สิ่งที่ต้องระวังสำหรับการอ้างอิงในอนาคตคือโครงการเชื่อมโยง OpenBSD ที่เรียกว่า'Epitome'

Epitome เป็นเอ็นจิ้นที่ให้บริการ Single Instance Storage, Content Addressable Storage และ Deduplication services

ข้อมูลทั้งหมดของคุณจะถูกเก็บไว้ในแหล่งข้อมูลเป็นบล็อกที่ถูกแฮชลบบล็อกที่ไม่ซ้ำกันเพื่อลดการใช้พื้นที่และช่วยให้คุณลืมกลไกการจัดเก็บเป็นหลักเพราะคุณสามารถขอเนื้อหาจากแหล่งข้อมูลด้วย UUID

ขณะนี้สิ่งที่ดีเลิศกำลังทำการทดลอง แต่มีบางอย่างที่ต้องระวังสำหรับอนาคต


0

โดยทั่วไปคุณต้องการหลีกเลี่ยงการมีไดเรกทอรีที่มีไฟล์ / ไดเรกทอรีจำนวนมาก เหตุผลหลักคือการขยายสัญลักษณ์ในบรรทัดคำสั่งจะส่งผลให้เกิดข้อผิดพลาด "ข้อโต้แย้งมากเกินไป" ทำให้เกิดความเจ็บปวดมากเมื่อพยายามทำงานกับไดเรกทอรีเหล่านี้

ไปหาวิธีแก้ปัญหาที่ทำให้ต้นไม้ที่ลึกกว่า แต่แคบลงเช่นการสร้างโฟลเดอร์ย่อยเหมือนที่คนอื่น ๆ ได้อธิบายไว้


0

เรามีปัญหาที่คล้ายกันวิธีแก้ปัญหาตามที่กล่าวไว้ก่อนหน้านี้คือการสร้างลำดับชั้นของไดเรกทอรี

แน่นอนถ้าคุณมีแอพพลิเคชั่นที่ซับซ้อนซึ่งอาศัยโครงสร้างไดเร็กตอรี่แฟลตคุณอาจต้องทำการปะแก้มาก. ดังนั้นจึงเป็นเรื่องดีที่จะรู้ว่ามีวิธีแก้ปัญหาใช้ symlinks ซึ่งไม่มีข้อ จำกัด 32k ที่กล่าวถึง คุณมีเวลาเหลือเฟือที่จะแก้ไขแอป ...


0

ทำไมไม่ใช้วิธีการประทับเวลาจากนั้นมีตัวเลือกมากเกินไป

ตัวอย่างเช่น

ดังนั้นสมมติว่าการประทับเวลาของคุณคือ: 1366587600

งด 2 หลักสุดท้าย (มิฉะนั้นจะไร้สาระเล็กน้อย) แยกตราประทับออกเป็นชุด 4 (จำนวนไดเรกทอรีไม่ควรเกิน 9999 - หากคุณต้องการแยกมันออกต่างกัน)

สิ่งนี้จะทำให้คุณมีสิ่งนี้:

/files/1366/5876/

จากนั้นตรวจสอบจำนวนเงินภายใน dir ก่อนที่จะอัปโหลดหากได้รับการอัปโหลดจำนวนมาก (เช่น 32000 + ต่อ 100 วินาที) จากนั้นทำซ้ำไดเรกทอรีโดยใช้ตัวที่สองหรือตัวอักษรตัวอย่างเช่น

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

หรือ

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

จากนั้นบันทึกการประทับเวลา + ตัวอักษรหรือรหัสเส้นทางแบบเต็มในฐานข้อมูลพร้อมกับผู้ใช้และคุณควรตั้ง

ทางเดิน: 1366587600 หรือ 13665876a (หากใช้ตัวอักษรของคุณ)

สิ่งนี้จะจบลงด้วยไดเรกทอรีจำนวนมาก แต่มันมีประโยชน์มากสำหรับการจัดการการแก้ไขไฟล์ ตัวอย่างเช่นหากผู้ใช้ต้องการใช้รูปโปรไฟล์ใหม่คุณยังคงมีเวอร์ชันเก่าที่ประทับเวลาของรุ่นเก่าในกรณีที่ต้องการยกเลิกการเปลี่ยนแปลง (ไม่ใช่แค่เขียนทับ)


0

ฉันขอแนะนำให้เลือกจำนวนไดเรกทอรีย่อยสูงสุดที่คุณต้องการ (หรือสามารถ) ได้ในโฟลเดอร์หลัก

จากนั้นคุณต้องแปลงรหัสผู้ใช้ของคุณเพื่อให้พวกเขาเริ่มจาก 1

จากนั้นคุณสามารถทำได้: modulo = currentId % numberOfSubdirectories

moduloตอนนี้จะมีหมายเลขไดเรกทอรีย่อยของคุณซึ่งจะไม่มากกว่าที่numberOfSubdirectoriesคุณเลือก

ทำอะไรก็ได้ที่คุณต้องการด้วยโมดูโล่

ด้วยวิธีนี้ไดเรกทอรีย่อยจะถูกเติมเป็นเส้นตรง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.