관리 메뉴

HAMA 블로그

Neo4j 인사이드 : 파일 스토리지 본문

NoSQL

Neo4j 인사이드 : 파일 스토리지

[하마] 이승현 (wowlsh93@gmail.com) 2015. 10. 30. 12:07

Neo4j Hello world~!!


인사이드를 살펴보기전에 Neo4j 의 사용 예를 간단하게 체크하자.


-  Relationship 타입을 enum 으로 만든다. 

private static enum RelTypes implements RelationshipType { KNOWS // 아는 관계 ( 친구 , 가족 뭐 그런..) }


- 관련 변수 선언 

GraphDatabaseService graphDb;
Node firstNode;
Node secondNode;
Relationship relationship;


- 데이터 베이스 시작 

graphDb = new GraphDatabaseFactory().newEmbeddedDatabase( DB_PATH );
registerShutdownHook( graphDb );


- 트랜잭션으로 todo list  감싸기  

try ( Transaction tx = graphDb.beginTx() )
{
    // Database operations go here
    tx.success();
}


- 작은 그래프 만들어보자.

firstNode = graphDb.createNode();
firstNode.setProperty( "message", "Hello, " );
secondNode = graphDb.createNode();
secondNode.setProperty( "message", "World!" );

relationship = firstNode.createRelationshipTo( secondNode, RelTypes.KNOWS );
relationship.setProperty( "message", "brave Neo4j " );

  



- 그래프를 출력해보고 

System.out.print( firstNode.getProperty( "message" ) );
System.out.print( relationship.getProperty( "message" ) );
System.out.print( secondNode.getProperty( "message" ) );

- 그래프  데이터를 삭제해보자

// let's remove the data
firstNode.getSingleRelationship( RelTypes.KNOWS, Direction.OUTGOING ).delete();
firstNode.delete();
secondNode.delete();


위의 소스를 보면 중요한 3가지 특성이 있다는것을 알수있다.

1. 노드  (firstNode, SecondNode) : '노드 속성을 가지고있다'

2. 관계  (relationship) : '관계 타입, 노드 속성 , 노드  방향을 가지고있다.'

3. 속성  ( 노드속성 :  "hello" , 'world'  /  관계 속성 : "brave neo4j")


이제 이정도만 기억해두고 이런 정보들을 과연 파일에 어떻게 저장하는지에 관해 알아보자.


Neo4j Internals: File Storage



1.저장되는  파일 이름들 

   - 노드 .db  파일  (neostore.nodestore.db)
   - 관계 .db  파일  (neostore.relationshipstore.db)
   - 노드 .id   파일  (neostore.nodestore.db.id)
   - .propertystore   파일  (neostore.propertystore.db)
   - .index   파일  (neostore.propertystore.db.index)


2. 재 사용되는 Ids

    neo 의 데이터가 동일한 사이즈의 청크로 저장된다고 가정해보자. 이걸 "chunks records" 라고 말한다고 치고, 
각각 레코드들은 그것과 연계된 id 를 가지고있다고하자.  파일안에서 데이터를 어떻게 찾을수있을까?
만약 데이타베이스에 대해서 좀 알고있다면 , 다양한 파일 엑세스 기법들에 대해서 떠오를것이다.
제일 쉬운방법은 id 를 자동적으로 하나씩 증가하게하면, 파일내에서 id 의 위치는 id * 레코드사이즈가 될것이다.
이때 문제가 하나 생기는데, 중간에 id 들이 삭제되면 어떻게 될냐는건데, 새로운 노드를 그 중간에 붕 뜬 자리에 
넣어주면되는데, 위에서 말한바와 같이 id 와 파일에서의 offset 은 id * 레코드사이즈라는 관계가 있다는 문제가 있다.
그래서 이걸 해결하기위한 방법은 지워진 id 를 기억해두었다가, 새로운 레코드에 적용시켜주면 되는것이다.
결국 id 를 요청하면 , 서버는 재사용되는 id 가 있으면 할당해주고, 없으면 새로운 id 를 만들어주는 전력을 취하면된다.


3. idGenerator 와 데이터 파일 

    - neo 서버가 영원히 메모리위에 있을수가 없기때문에, 저런 재사용 ids 를 파일에 저장해두어야한다.
 - org.neo4j.kernel.impl.nioneo.store.IdGenerator 와 이것의 구현체인 IdGeneratorImpl 클래스가 사용된다.
 - 모든 데이터파일의 관리자는 IdGenerator 를 유지해야한다. 
 - "id" 파일은 ".db" 파일과  나란히 연결되있다.
 - 위에 헬로월드를 실행시키고 (삭제하기전에)  neostore.nodestore.db.id 파일을 살펴보면 , 9바이트를 볼수있는데
   처음 0 은 클린 셧다운을 말하고, 나머지 8 바이트는 3 의 long 타입이다. 이 3은 다음 사용될 id 를 나타낸다. 
   1과 2는 이미 사용되고있다. 지워진 노드가 없기때문에 재사용 ids 도 물론 없다. 

4. Neo4j 의 두가지 저장법.

      가.org.neo4j.kernel.impl.nioneo.store.AbstractStore
           -  고정된 사이즈의 레코드를 다룬다.

      나. org.neo4j.kernel.impl.nioneo.store.AbstractDynamicStore
          -  다양한 사이즈의 레코드를 블럭안에 저장한다. 그리고 LinkedList 같이 디스크상에서 연결해서  저장한다. 

       - 두가지 모두 그들의 빌딩블록들과 연결된 ids 를 사용한다. 차이점은 AbstractStore 는 바깥 세상과 ids 를 가지고
         소통한다는 점이고, DynamicStore 의 ids 는 오직 클래스안에서 의미를 가진다는점이다. 



Record - oriented storage : The primitives


 5. 노드 스토어 

        - org.neo4j.kernel.impl.nioneo.store.NodeStore 는 neostore.nodestore.db 파일을 만든다.
        - 모든 노드는 여기에 저장된다.
        - 간단하게 9 바이트의 고정 레코드를 살펴보면, 첫바이트는 사용 플레그이고, 그 다음 4바이트 integer 는
          relationships 의 첫번째 id 이고, 마지막 4 byte 는 이 노드가 가지고있는 첫번째 속성의 id 이다.  
        - AbstractStore 안의 레코드들은 ids 를 저장하지 않는다.  그들의 파일에서의 오프셋은 그들의 id 를 정의하며 
          그들의 id 는 그들의 파일에서의 오프셋을 정의한다. 


 6.  관계 스토어 

         - org.neo4j.kernel.impl.nioneo.store.RelationshipStore 는 neostore.relationshipstore.db 파일을 만든다.
         - 33  바이트의 관계 레코드에서, 
                * 첫번째 바이트는 사용플레그
                * 4 바이트 :  첫번째 노드의 id 
                * 4 바이트 :  두번째 노드의 id
                * 4 바이트 :  이 관계의 타입을 나타내는 레코드의 id   
                * 4 바이트 * 4  : 첫번째 노드의 이전관계 id  /  첫번째 노드의 다음 관계 id  /   
                                          두번째 노드의 이전관계 id  /  두번째 노드의 다음 관계 id  
                * 4 바이트 : 이 관계의 첫번째 속성의 id 
            - 관계는 디스크상에서 이중링크드리스트의 형태이다.

 7.  관계 타입  스토어 

         org.neo4j.kernel.impl.nioneo.store.RelationshipTypeStore 는 neostore.relationshipTypestore.db 파일 생성. 

         - 관계 타입 이름을 저장하기위한 장소가 필요한데 neostore.relationshipTypestore.db.names 파일이다.    


  8 . 속성  스토어  

         org.neo4j.kernel.impl.nioneo.store.PropertyStore 는 neostore.propertystore.db 파일을 만든다. 

           - 각각의 속성 레코드들은 in_use 바이트과 속성의 타입을 저장하는 integer 로 시작된다.


  Block - oriented storage: Strings and arrays


 * 이전 스토리지엔진들은 고정크기의 레코드들을 가지고, 다른 레코드들로의 포인터 및 작은 데이터로  구성되었다. 
   당신의  소중하고, 다양한크기를 가진 문자열 또는 배열 속성 값들은 다른 방식으로 다루어져야한다.  
   이것이 DynamicStores 가 만들어진 이유이다. 우리는 이미 PropertyStore 나 RelaltionshipTypeStore 의 부분으로 
   그것의 사용법을 살펴보았는데, 모두다 .Strings 나 배열같은 자바 기본 요소가 필요하다.
   이제 그들의 구조를 살펴보자.

   9.   일반 블록 구조 

    다양한 사이즈의 임의의 데이터는  dynamic store 파일안에 이중 링크드 블럭 구조에 의해  수용되어진다.
   여기서 필요로
 되어지는것은 in_use byte /  이전 블럭 / 다음 블럭으로의 포인터 / 데이타의 크기 및 데이터이다. 
   이것의 크기는  파일안에서의 오프셋을 발견하기 위해 가능한 맥시점 블럭사이즈 에 의해 한계가 지어진다. 만약 하나의
   데이터가  blockSize 보다 더 큰 
공간을 요구하면, 그 만큼의 블럭들이 그것의 체인에 알맞게 추가된다.
   그러나 체인의 마지막 블럭은 (만약 하나라면 첫번째)
 할당된 양보다 적게  사용가능하다. 

    각각 블럭헤더의 레이아웃은 in_use byte, 이전 블럭의 int id (만약 -1 이면 첫번째) , 길이 , 다음블럭의 int id,  이 
    13바이트 
이후에는 맥스 blockSize 크기의 데이터가 온다.전체 블럭의 크기는 고로 13 + blockSize 이다. 


  10.   Strings vs Arrays 


org.neo4j.kernel.impl.nioneo.store.DynamicArrayStore 

org.neo4j.kernel.impl.nioneo.store.DynamicStringStore 


  11.   개인적 노트



  12. 마무리

  몇몇 부분 정확한 이해없이 대략 정리한것이기때문에 잘못된것이 있을수 있습니다. 

  하기 레퍼런스를 보시면 더 정확한 정보를 알수있습니다.           



레퍼런스:

http://neo4j.com/docs/stable/tutorials-java-embedded-hello-world.html

http://digitalstain.blogspot.kr/2010/10/neo4j-internals-file-storage.html

'NoSQL' 카테고리의 다른 글

Neo4j - Traversal  (0) 2015.10.30
Neo4j - 인덱스 사용하기  (0) 2015.10.30
시계열 DB (OpenTSDB , 인플럭스 DB , Graphite ) 정리  (0) 2015.10.22
MongoDB vs Couchbase (2)  (0) 2015.09.03
MongoDB vs Couchbase (1)  (0) 2015.09.03
Comments