프로그래밍/개발

[개발] 샤딩이란 것을 해보자! (2)

riroan 2023. 4. 21. 19:19

지난시간에 이어 샤딩을 사용해보자.

 

라우터 생성

우리는 이름을 기준으로 라우팅을 할 것이다. 영어 소문자만 들어온다고 가정하자.

데이터베이스가 4개이니까 a~g로 시작하는건 1번, h~n은 2번, o~u는 3번, v~z는 4번 데이터베이스에 넣도록 하자.

# router.py

def insert_route(name: str):
    assert len(name) > 0
    ch = name[0]
    return (ord(ch) - ord('a')) // 7

정말 간단하다. 위 라우터는 삽입할 때 사용하는 라우터이다.

삽입쿼리 추가

# datasource.py
from router import insert_route

class DataSource:
	...

    def insert(self, name: str, age: int):
        ix = insert_route(name)
        query = f"INSERT INTO user (name, age) VALUES ('{name}', {age})"
        cursor = self.cursors[ix]
        conn = self.connections[ix]

        cursor.execute(query)
        conn.commit()

정말 간단하다. 이것만으로 우리는 삽입 샤딩을 끝낸것이다. 업데이트와 삭제는 똑같은 방식으로 하면 되므로 생략한다. (한번 해보자!)

if __name__ == "__main__":
    src = DataSource()
    src.insert("riroan", 19)

위 코드를 실행하면 실제로 적절한 데이터베이스에 데이터를 삽입하여 4개의 데이터베이스중 한 곳에만 저장이 된다.

import string
import random
if __name__ == "__main__":
    src = DataSource()
    letters = string.ascii_lowercase
    
    for _ in range(10000):
        name = ""
        for j in range(6):
            name += random.choice(letters)
        age = random.randint(1, 100)
        src.insert(name, age)

랜덤한 데이터를 10000개정도 넣어놓자.

조회 쿼리 추가

# datasource.py
class DataSource:
	...
    def select_all(self, ix):
        query = f"SELECT * FROM user"
        cursor = self.cursors[ix]
        cursor.execute(query)

        result = cursor.fetchall()

        return result

ix번째 데이터베이스에 존재하는 모든 데이터를 불러온다.

if __name__ == "__main__":
    src = DataSource()
    for i in range(4):
        result = src.select_all(i)
        print(f"{i}번째 데이터베이스에 {len(result)}개의 데이터가 있습니다.")
# 0번째 데이터베이스에 2767개의 데이터가 있습니다.
# 1번째 데이터베이스에 2665개의 데이터가 있습니다.
# 2번째 데이터베이스에 2658개의 데이터가 있습니다.
# 3번째 데이터베이스에 1911개의 데이터가 있습니다.

위 코드를 실행하여 데이터가 적절히 분산되어 저장된 것을 알 수 있다.

 

다음시간에 select의 꽃인 where을 포함한 조회 쿼리를 만들어보자.