8.5 NoSql 데이터 스토어

8.5.1 dbm 형식

import dbm
db = dbm.open('definitions', 'c')
db['mustard'] = 'yellow'
db['ketchup'] = 'red'
db['pesto'] = 'green'
len(db)

3

db

<_gdbm.gdbm at 0x7f0de568c0d0>

db['pesto']

b’green’

db.close()
db = dbm.open('definitions', 'r')
db['mustard']

b’yellow’

8.5.2 Memcached

  • 키에 대한 값을 설정하고 얻는다.
  • 값을 증가하거나 감소시킨다.
  • 키를 삭제 한다.
    import memcache
    db = memcache.Client(['127.0.0.1:8800'], debug=True)
    db.set('marco', 'polo')
    

    MemCached: MemCache: inet:127.0.0.1:8800: connect: [Errno 111] Connection refused. Marking dead. 0

    print(db.get('marco'))
    

    None

    import memcache
    mc = memcache.Client(['127.0.0.1:11211'], debug=0)
    mc.set('marco1', 'polo1')
    try:
    print(mc.get('marco1'))
    except (mc.MemcachedKeyTypeError, mc.MemcachedKeyNoneError,
    TypeError, mc.MemcachedKeyCharacterError,
    mc.MemcachedKeyError, mc.MemcachedKeyLengthError,
    mc.MemcachedStringEncodingError) as e:
    print(e)
    

    None

    8.5.3 Redis

  • 서버의 재시작과 신뢰성을 위해 데이터를 디스크에 저장한다.
  • 기존 데이터를 유지한다.
  • 간단한 문자열 이상의 자료구조를 제공한다.

    Redis서버의 호스트의 기본 값 (localhost:6379)

    문자열

    import redis
    conn = redis.Redis()
    
    conn.keys('*')
    

    []

    conn.set('secret', 'ni!')
    

    True

    conn.set('carats', 24)
    

    True

    conn.set('fever', '101.5')
    

    True

    conn.get('secret')
    

    b’ni!’

    conn.get('carats')
    

    b’24’

    conn.get('fever')
    

    b’101.5’

    conn.setnx('secret', 'icky-icky--icky-ptang-zoop-boing!')
    

    False

    conn.get('secret')
    

    b’ni!’

    conn.getset('secret', 'icky-icky-icky-ptang.zoop-boing')
    

    b’ni!’

    conn.get('secret')
    

    b’icky-icky-icky-ptang.zoop-boing’

    conn.getrange('secret', -6, -1)
    

    b’-boing’

    conn.setrange('secret', 0, 'ICKY')
    

    31

    conn.get('secret')
    

    b’ICKY-icky-icky-ptang.zoop-boing’

    conn.mset({'pie':'cherry', 'cordial':'sherry'})
    

    True

    conn.mget(['fever','carats'])
    

    [b’101.5’, b’24’]

    conn.delete('fever')
    

    1

    conn.incr('carats')
    

    25

    conn.incr('carats')
    

    26

    conn.incr('carats', 10)
    

    36

    conn.decr('carats')
    

    35

    conn.decr('carts', 15)
    

    -15

    conn.decr('carats', 15)
    

    20

    conn.set('fever', '101.5')
    

    True

    conn.incrbyfloat('fever')
    

    102.5

    conn.incrbyfloat('fever', 0.5)
    

    103.0

    conn.incrbyfloat('fever', -2.0)
    

    101.0

    리스트

  • 문자열만 포함 가능
    conn.lpush('zoo', 'bear')
    

    1

    conn.lpush('zoo', 'alligator', 'duck')
    

    3

    conn.linsert('zoo', 'before', 'bear', 'beaver')
    

    4

    conn.linsert('zoo', 'after', 'bear', 'cassowary')
    

    2

    conn.lset('zoo', 2, 'marmoset')
    

    True

    conn.rpush('zoo', 'yak')
    

    6

    conn.lindex('zoo', 4)
    

    b’cassowary’

    conn.lrange('zoo', 0, 2)
    

    [b’duck’, b’alligator’, b’marmoset’]

    conn.ltrim('zoo', 1, 4)
    

    True

    conn.lrange('zoo', 0, -1)
    

    [b’alligator’, b’marmoset’, b’bear’, b’cassowary’]

    해시

  • 문자열만 포함 가능
  • 중첩구조가 아닌 한 단계 깊이의 구조를 만듬
    conn.hmset('song', {'do':'a deer', 're':'about a deer'})
    

    True

    conn.hset('song', 'mi', 'a note to follow re')
    

    1

    conn.hgetall('song')
    

    {b’do’: b’a deer’, b’mi’: b’a note to follow re’, b’re’: b’about a deer’}

    conn.hget('song', 'mi')
    

    b’a note to follow re’

    conn.hmget('song', 're', 'do')
    

    [b’about a deer’, b’a deer’]

    conn.hkeys('song')
    

    [b’do’, b’re’, b’mi’]

    conn.hvals('song')
    

    [b’a deer’, b’about a deer’, b’a note to follow re’]

    conn.hlen('song')
    

    3

    conn.hgetall('song')
    

    {b’do’: b’a deer’, b’mi’: b’a note to follow re’, b’re’: b’about a deer’}

    conn.hsetnx('song', 'fa', 'a note that rhymes with la')
    

    1

    conn.delete('zoo')
    

    1

    conn.sadd('zoo', 'duck', 'goat', 'turkey')
    

    3

    conn.scard('zoo')
    

    3

    conn.smembers('zoo')
    

    {b’duck’, b’goat’, b’turkey’}

    conn.srem('zoo', 'turkey')
    

    1

    conn.smembers('zoo')
    

    {b’duck’, b’goat’}

    conn.sadd('better_zoo', 'tiger', 'wolf', 'duck')
    

    3

    conn.sinter('zoo', 'better_zoo')
    

    {b’duck’}

    conn.sinterstore('fowl_zoo', 'zoo', 'better_zoo')
    

    1

    conn.smembers('fowl_zoo')
    

    {b’duck’}

    conn.sunion('zoo', 'better_zoo')
    

    {b’duck’, b’goat’, b’tiger’, b’wolf’}

    conn.sunionstore('fabulous_zoo', 'zoo', 'better_zoo')
    

    4

    conn.smembers('fabulous_zoo')
    

    {b’duck’, b’goat’, b’tiger’, b’wolf’}

    conn.sdiff('zoo', 'better_zoo')
    

    {b’goat’}

    conn.sdiffstore('zoo_sale', 'zoo', 'better_zoo')
    

    1

    conn.smembers('zoo_sale')
    

    {b’goat’}

    정렬된 셋

  • Redis의 데이터 타입중 가장 많은 용도로 쓰이는 것은 정렬된 셋이다 zset
  • 유일한 값의 셋이지만, 각 값은 연관된 부동 소수점의 점수를 가진다.
  • 게임 순위판, 보조인덱스, 타임스탬프를 점수로 사용하는 시계열
    import time
    now = time.time()
    now
    

    1519695250.5823567

    conn.zadd('logins', 'smeagol', now)
    

    1

    conn.zadd('logins', 'sauron', now+(5*60))
    

    1

    conn.zadd('logins', 'bilbo', now+(2*60*60))
    

    1

    conn.zadd('logins', 'treebeard', now+(24*60*60))
    

    1

    conn.zrank('logins', 'bilbo')
    

    2

    conn.zrank('logins', 'smeagol')
    

    0

    conn.zscore('logins', 'bilbo')
    

    1519702450.5823567

    conn.zrange('logins', 0, -1)
    

    [b’smeagol’, b’sauron’, b’bilbo’, b’treebeard’]

    conn.zrange('logins', 0, -1, withscores=True)
    

    [(b’smeagol’, 1519695250.5823567), (b’sauron’, 1519695550.5823567), (b’bilbo’, 1519702450.5823567), (b’treebeard’, 1519781650.5823567)]

    비트

  • 대량의 숫자 집합을 공간-효율적인 방식으로 빠르게 처리 한다.
    import redis
    conn = redis.Redis()
    days = ['2013-02-25', '2013-02-26', '2013-02-27']
    big_spender = 1089
    tire_kicker = 40459
    late_joiner = 550212
    
    conn.setbit(days[0], big_spender, 1)
    

    0

    conn.setbit(days[1], tire_kicker, 1)
    

    0

    conn.setbit(days[1], big_spender, 1)
    

    0

    conn.setbit(days[2], big_spender, 1)
    

    0

    conn.setbit(days[2], late_joiner, 1)
    

    0

    for day in days:
    print(conn.bitcount(day))
    

    1 2 2

    conn.getbit(days[0], tire_kicker)
    

    0

    conn.bitop('and', 'everyday', *days)
    

    68777

    conn.bitcount('everyday')
    

    1

    캐시와 만료

  • 모든 Redis의 키는 TTL, 즉 만료일을 가진다.
  • 키가 유지되는 시간을 지정하기 위해 expire()함수를 사용한다.
    import time
    key = 'now you see it'
    
    conn.set(key, 'but not for long')
    

    True

    conn.expire(key, 5)
    

    True

    conn.ttl(key)
    

    5

    conn.get(key)
    

    b’but not for long’

    conn.get(key)
    

    8.5.4 기타 NoSQL

Comments