리눅스 서브 디렉토리 수 제한을 해결하는 방법?


9

사용자 프로필 이미지를 저장할 웹 사이트가 있습니다. 각 이미지는 사용자 고유의 디렉토리 (Linux)에 저장됩니다. 현재 30 개 이상의 고객 기반을 보유하고 있으며 이는 30 개 이상의 폴더를 갖게됩니다. 그러나 현재 Linux 상자 (ext2 / ext3)는 32000 개 이상의 디렉토리 생성을 지원하지 않습니다. 이걸 어떻게 지나가나요? YouTube 사용자도 동영상 미리보기 이미지에서 동일한 문제를 겪었습니다. 그러나 그들은 ReiserFS로 옮겨서 해결했습니다. 더 나은 솔루션을 가질 수 없습니까?

업데이트 : IRC에서 물었을 때 사람들은 64k 한도를 가진 ext4로 업그레이드하는 것에 대해 묻고 있었으며 물론 그것도 지나칠 수 있습니다 . 또는 커널 해킹으로 한계를 변경하십시오.

업데이트 : 사용자 기반을 기반으로 사용자 기반을 폴더로 분할하는 방법에 대해 설명합니다. 한 폴더에서 1-1000을 의미하고 다른 폴더에서는 1000-2000을 의미합니다. 이것은 간단한 것 같습니다. 얘들 아?

솔직히 다른 방법이 없습니까?


1
파일 시스템을 변경하고 싶지 않은 이유는 무엇입니까? 이것이 ext2 / 3의 제한 사항 인 경우 파일 시스템을 변경하거나 현재 FS를 더 작은 FS (더 다른 마운트 지점)로 분할하는 것 외에 다른 변경은 없습니다.
Manuel Faux

1
Manuel : 파일 시스템을 변경하면 특정 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

이 방법은 오징어 캐시, Ludwig의 예 및 웹 브라우저의 로컬 캐시를 복사하는 데 사용됩니다.

주의해야 할 중요한 사항 중 하나는 ext2 / 3를 사용하면 디렉토리가 선형으로 검색되므로 32,000 한계에 근접하기 전에 성능 문제가 발생하기 시작한다는 것입니다. 다른 파일 시스템 (예 : ext4 또는 reiser)으로 이동하면이 비 효율성이 제거됩니다 (레이저는 이진 분할 알고리즘을 사용하여 디렉토리를 검색하므로 긴 디렉토리를 훨씬 효율적으로 처리하고 ext4도 처리 할 수 ​​있음).


다음과 같이 질문 설명을 업데이트했습니다. "업데이트 : 사용자 기반을 사용자 ID 범위를 기준으로 폴더로 분할하는 방법. 한 폴더에서 1-1000, 다른 폴더에서 1000-2000을 의미합니다. 이것은 간단 해 보입니다. "말하니?"
None-da

1
사용자가 일반적으로 사용자 이름이 아닌 사용자 ID로 식별되는 경우 잘 작동하며 해시보다 효율적입니다. 시스템의 다른 곳에서 항상 이름으로 참조하는 경우 이름-> ID 조회를 추가해야합니다.
David Spillett

고마워 데이빗! 나는 다른 해결책을 시도했다. 나는 1-30000, 30000-60000 등의 범위를 가진 4 개의 폴더를 거의 만들지 않았습니다. 그런 큰 디렉토리에서 파일을 얻는 데 1000 개의 파일이있는 디렉토리 (이전 접근법)보다 시간이 더 걸릴 것이라고 생각합니다. 당신은 무엇을 말합니까?
None-da

1
파일 시스템에 따라 다릅니다. ext2 또는 ext3을 사용하는 경우 디렉토리 당 30,000보다 훨씬 작은 것이 좋습니다. 일부 도구는 약 10,000 경고를 발행합니다. ext3 / 4에서 디렉토리 인덱싱을 켜면 다음과 같은 도움이됩니다. .
David Spillett

@Maddy, Ext2 / 3가 많은 파일을 처리하는 방법에 대한 다른 제한으로 인해이 솔루션을 원합니다. 자세한 내용은 serverfault.com/questions/43133/… 을 참조하십시오 . 하위 디렉토리로 버킷으로 이름을 분류하면 결국 발생했을 다른 문제가 완화됩니다. 이는 Squid가 처음으로 개체 캐시를 설정할 때 사용하는 것과 같은 전략입니다 (예 : 내부에 64 개의 디렉토리가있는 64 개의 디렉토리).
Avery Payne

7

ext2 / ext3에 바인딩되어 있다면 데이터를 분할하는 것이 유일한 가능성입니다. 데이터를 비슷한 크기의 관리 가능한 덩어리로 나누는 기준을 찾으십시오.

프로필 이미지에 관한 것이라면 :

  1. 이미지의 해시 (예 : SHA1)를 사용하십시오.
  2. SHA1을 파일 및 디렉토리 이름으로 사용

예를 들어 SQUID 캐시는 다음과 같이 수행합니다.

f / 4b / 353ac7303854033

최상위 디렉터리는 첫 번째 16 진수이고, 두 번째 수준은 다음 두 16 진수이며, 파일 이름은 나머지 16 진수입니다.


2

더 나은 해결책이 있습니까?

더 나은 솔루션이 있습니다-다른 파일 시스템을 사용하십시오. 사용 가능한 것이 많으며 대부분이 다른 작업에 최적화되어 있습니다. 지적했듯이 ReiserFS는 디렉토리에서 많은 파일을 처리하는 데 최적화되어 있습니다.

파일 시스템 비교는 여기참조하십시오 .

디렉토리에있는 많은 파일들에 대해서는 정말 열악한 NTFS에 얽매이지 않고 다행입니다. 비교적 새로운 (그러나 안정적으로) ext4 FS를 사용하지 않으려면 JFS를 대체물로 사용하는 것이 좋습니다.


NTFS 파일 시스템 성능과 연결되어 있습니까?
Thorbjørn Ravn Andersen

예, 디렉토리에서 새 파일을 생성하는 데 너무 오래 남은 앱에 대한 개인적인 경험과는 별도로 (모든 파일을 삭제하는 데 시간이 걸렸습니다) 디렉토리의 파일 수를 1000으로 제한하여 하위 버전 성능이 향상되었습니다. : support.microsoft.com/kb/130694 여전히 성능으로 언급 된 것처럼 "고정"된 것으로 생각하지 않습니다. NTFS를 조정하십시오.
gbjbaanb

1

프로필 이미지가 작습니까? 나머지 프로파일 데이터와 함께 데이터베이스에 넣는 것은 어떻습니까? 이것은 최선의 선택은 아니지만 고려할 가치가 있습니다 ...

: 여기 (이상) 마이크로 소프트 백서 주제에 대한 것입니다 으로 BLOB 여부에 BLOB .


1

작은 웹 갤러리를 해킹하여이 문제의 변형으로 끝났습니다. 나는 캐시 디렉토리에 ~ 30.000 개의 이미지를 가지고 있었는데 꽤 느렸다 (ext2는 내가 기억하는 것처럼 디렉토리 인덱스에 링크 된 목록을 사용한다).

나는이 라인을 따라 무언가를했다.

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

이렇게하면 데이터가 256 개 디렉토리로 분할되어 세 가지 레벨 각각에 대한 빠른 디렉토리 조회가 제공됩니다.

  • MD5는 32의 12 비트를 변경하면 다른 출력을 보장하므로 SHA1보다 MD5를 사용하기로 선택했기 때문에 사용자 이름, 디렉토리 및 기타 짧은 항목을 해시하는 데 적합합니다. 그리고 그것은 또한 빠릅니다 ...
  • 너무 많은 디렉토리를 생성하고 디스크 캐시를 계속해서 휴지통에 버릴 것이므로 전체 해시를 포함하지 않습니다.

1
해시가 MD5 나 SHA와 같이 암호화 적으로 강력 할 필요는 없기 때문에 CRC와 같은 더 간단한 해시를 사용할 수 있습니다. 그러나 성능 차이는 무시할 수 있습니다 ...
sleske

0

문제에 대한 즉각적인 답변은 아니지만 나중에 참조해야 할 사항은 'Epitome' 이라는 OpenBSD 링크 프로젝트입니다.

Epitome은 단일 인스턴스 스토리지, 컨텐츠 주소 지정 가능 스토리지 및 중복 제거 서비스를 제공하는 엔진입니다.

모든 데이터는 데이터 저장소에 해시 블록으로 저장되어 고유하지 않은 블록을 제거하여 공간 사용량을 줄이고, UUID로 데이터 저장소에서 콘텐츠를 간단하게 요청할 수 있으므로 스토리지 메커니즘을 잊어 버릴 수 있습니다.

에피 톰은 현재 실험적이지만 미래를 지켜봐야 할 것입니다.


0

일반적으로 많은 수의 파일 / 디렉토리가있는 디렉토리를 피하려고합니다. 주된 이유는 명령 행에서 와일드 카드 확장으로 인해 "너무 많은 인수"오류가 발생하여 이러한 디렉토리에 대해 작업 할 때 많은 고통을 초래하기 때문입니다.

더 깊지 만 더 좁은 트리를 만드는 솔루션을 찾으십시오 (예 : 다른 설명과 같이 하위 폴더 생성).


0

우리는 비슷한 문제를 겪었습니다. 앞에서 언급했듯이 해결책은 디렉토리의 계층 구조를 만드는 것입니다.

물론 플랫 디렉토리 구조에 의존하는 복잡한 응용 프로그램이 있다면 많은 패치가 필요할 것입니다. 따라서 해결 방법이 있다는 것을 아는 것이 좋습니다. 언급 된 32k 제한이없는 심볼릭 링크를 사용하십시오. 그런 다음 앱을 고칠 시간이 충분합니다 ...


0

타임 스탬프 접근 방식을 사용하고 오버플로 옵션이없는 이유는 무엇입니까?

예를 들어

타임 스탬프는 다음과 같습니다. 1366587600

마지막 두 자리를 생략하십시오 (그렇지 않으면 약간 어리 석습니다). 스탬프를 4 세트로 분리하십시오 (디렉토리 수는 9999를 초과하지 않아야합니다-원하는 경우 다르게 분리 할 수 ​​있습니다).

이것은 당신에게 다음과 같은 것을 남길 것입니다 :

/files/1366/5876/

그런 다음 업로드하기 전에 디렉토리 내에서 양을 확인하십시오 (예 : 100 초당 32000 +).

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

또는

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

그런 다음 타임 스탬프 + 문자 또는 전체 경로 코드를 사용자와 함께 DB에 기록하면 설정해야합니다.

경로 스탬프 : 1366587600 또는 13665876a (문자를 사용하는 경우).

이것은 많은 디렉토리로 끝나지 만 파일 개정을 처리하는 데 실제로 유용 할 수 있습니다. 예를 들어, 사용자가 새 프로필 사진을 사용하려는 경우 변경 내용을 취소하려는 경우를 대비하여 이전 타임 스탬프 된 이전 버전의 버전이 여전히 남아 있습니다 (덮어 쓰지 않음).


0

부모 폴더에 가질 수있는 최대 하위 디렉토리 수를 결정하는 것이 좋습니다.

그런 다음 1부터 시작하도록 사용자 ID를 변환해야합니다.

그럼 당신은 할 수 있습니다 : modulo = currentId % numberOfSubdirectories

modulo이제 numberOfSubdirectories선택한 것보다 더 큰 하위 디렉토리 번호가 포함됩니다 .

예를 들어 모듈러스로 원하는 것을 해시하십시오.

또한이 방법으로 하위 디렉토리는 선형으로 채워집니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.