Redis

From 탱이의 잡동사니
Jump to navigation Jump to search

Overview

Redis 사용법 소개

Data types

Redis 에는 5가지의 데이터 타입이 존재한다(Strings, Lists, Sets, Sorted sets, Hashes)

Strings

일반적인 key-value 이다.

- String 이라고 해서 문자열만 저장할 수 있는게 아니라, 이진 데이터도 저장이 가능하다.(정수, 실수형이 따로 없다). 
- Key 에 넣을 수 있는 데이터의 최대 크기는 512 MB이다.

Lists

Array 형태로 key 1개에 n개의 값을 가지며, 중복 값도 가능하다.

- 배열이라고 생각해도 된다. 
- 한 key 에 넣을 수 있는 요소의 최대 개수는 4,294,967,295 개이다. 
- 데이터 형의 값은 설정파일에서 정해준 조건보다 큰 경우 linkedlist 아니면 ziplist로 encoding 된다.

Sets

Group 형태로 key 1개에 n 개의 중복되지 않는 값을 가진다.

- 정렬되지 않은 집합형으로 key에 중복된 데이터는 존재하지 않는다.
- 추가, 제거 및 존재 체크 시 소모되는 시간이, sets 에 포함되 ㄴ요소의 수와 관계없이 일정하다.
- 한 key 에 넣을 수 있는 요소의 최대 개수는 4,294,967,295 개이다.
- 데이터 형의 값은 설정파일에 정해준 조건보다 큰 경우 hashtable 아니면 intset 으로 encoding 된다.

Sorted sets

Group 형태이나 각 member에 score 값을 가진다. keye-member-score

- Sorted sets 는 가잔 진보한 Redis 데이터 형이라고도 한다.
- 요소의 추가, 제거, 업데이트는 매우 빠른 방법으로 진행되는 데, 이는 "요소의 개수의 로그"에 비례하는 시간이 사용된다.
- 랭킹 시스템 등에서 사용되기 좋다.
- sets의 각 요소마다 score 라는 실수 값을 가지고 있는 형태로 score 값으로 오름차순 정렬된다.
- key에 중복된 데이터는 존재하지 않지만 score 값은 중복 가능하다.

example

redis>  ZADD myzset 1 "one"
(integer) 1

redis>  ZADD myzset 1 "uno"
(integer) 1

redis>  ZADD myzset 2 "two" 3 "three"
(integer) 2

redis>  ZRANGE myzset 0 -1 WITHSCORES
1) "one"
2) "1"
3) "uno"
4) "1"
5) "two"
6) "2"
7) "three"
8) "3"

Hashes

Obejct 형태의 key-field-value

- list 와 비슷한데, "필드명", "필드값"의 연속으로 이루어져 있다.
- 한 key 에 포함할 수 있는 field-value 쌍의 최대 개수는 4,294,967,295 개이다.
- 데이터 형의 값은 설정파일에서 정해준 조건보다 큰 경우는 hashtable 아니면 zipmap 으로 encoding 된다.

Commands

DEL

지정된 키를 삭제한다.

127.0.0.1:6379> help DEL

  DEL key [key ...]
  summary: Delete a key
  since: 1.0.0
  group: generic

GET

지정된 키 값을 가져온다.

127.0.0.1:6379> help GET

  GET key
  summary: Get the value of a key
  since: 1.0.0
  group: string

SET 명령어 사용시, 만약 Key 에 이미 다른 값이 설정되어 있다면 타입에 상관없이 덮어쓰기가 된다. Any previous time to live associated with the key is discarded on successful SET operation.

Example

redis>  GET mykey
"Hello"

INFO

Redis 서버 설정 정보를 확인할 수 있다.

127.0.0.1:6379> help INFO

  INFO [section]
  summary: Get information and statistics about the server
  since: 1.0.0
  group: server

Example

> INFO
redis_version:2.4.18
redis_git_sha1:00000000
redis_git_dirty:0
arch_bits:64
...

MONITOR

REDIS 에서 수행되는 명령어를 실시간으로 모니터링한다.

127.0.0.1:6379> help monitor

  MONITOR -
  summary: Listen for all requests received by the server in real time
  since: 1.0.0
  group: server

Example

redis 127.0.0.1:6379> monitor
OK
1465549016.028126 "monitor"

1465549888.174607 (db 10) "SELECT" "10"
1465549888.193430 (db 10) "KEYS" "accounts:127.0.0.1-user1:accountinformation"
1465549888.193779 (db 10) "HGETALL" "accounts:127.0.0.1-user1:accountinformation"
1465549888.224193 (db 10) "KEYS" "voicemail:127.0.0.1-user1:message*"
1465549892.531991 (db 10) "SELECT" "10"
1465549892.547614 (db 10) "KEYS" "accounts:127.0.0.1-user1:accountinformation"
1465549892.547991 (db 10) "HGETALL" "accounts:127.0.0.1-user1:accountinformation"
1465549892.578356 (db 10) "KEYS" "voicemail:127.0.0.1-user1:message*"
1465549892.590838 (db 10) "KEYS" "accounts:127.0.0.1-user1:accountinformation"
1465549892.591206 (db 10) "HGETALL" "accounts:127.0.0.1-user1:accountinformation"
1465549892.621536 (db 10) "KEYS" "voicemail:127.0.0.1-user1:message*"
1465549892.622748 (db 10) "HMSET" "mailboxchanges:127.0.0.1:user1" "mboxname" "user1" "old" "0" "new" "0"
...

SET

지정한 키에 값을 지정한다.

127.0.0.1:6379> help SET

  SET key value [EX seconds] [PX milliseconds] [NX|XX]
  summary: Set the string value of a key
  since: 1.0.0
  group: string

Example

redis>  SET mykey "Hello"
OK

SADD, SMEMBERS

SADD key member [member ...] 
SMEMBERS key

지정된 key에 member 들을 Sets 타입으로 add/show 한다.

redis 127.0.0.1:6379[1000]> SADD queues "a684cf64-685c-484c-8157-a53db7e7cef7"
(integer) 1
redis 127.0.0.1:6379[1000]> SADD queues "f9c7e9cf-8415-42d7-a6cd-82fa95410b33"
(integer) 1
redis 127.0.0.1:6379[1000]> SADD queues "e5631cf8-6898-486a-beac-36087c917b8a"
(integer) 1

redis 127.0.0.1:6379[1000]> SMEMBERS queues
1) "a684cf64-685c-484c-8157-a53db7e7cef7"
2) "e5631cf8-6898-486a-beac-36087c917b8a"
3) "f9c7e9cf-8415-42d7-a6cd-82fa95410b33"

ZSET

ZREMRANGEBYSCORE


SUNION

여러개의 결과 데이터를 조합하여 중복된 데이터를 제외한 결과를 리턴한다.

key1 = {a,b,c,d}
key2 = {c}
key3 = {a,c,e}
SUNION key1 key2 key3 = {a,b,c,d,e}

SINTER

여러개의 결과 데이터를 조합하여 공통적으로 속해있는 결과만을 리턴한다.

key1 = {a,b,c,d}
key2 = {c}
key3 = {a,c,e}
SINTER key1 key2 key3 = {c}

비어있는(empty) 혹은 존재하지 않는 키와의 SINTER 는 항상 empty list 를 반환한다.

Example

redis>  SADD key1 "a"
(integer) 1
redis>  SADD key1 "b"
(integer) 1
redis>  SADD key1 "c"
(integer) 1
redis>  SADD key2 "c"
(integer) 1
redis>  SADD key2 "d"
(integer) 1
redis>  SADD key2 "e"
(integer) 1
redis>  SINTER key1 key2
1) "c"

SCAN, SSCAN, ZSCAN, HSCAN

KEYS 와 비슷한 기능을 수행하지만 KEYS와는 달리 Table lock 을 생성하지 않는다.

SCAN cursor [MATCH pattern] [COUNT count]
SSCAN key cursor [MATCH pattern] [COUNT count]
ZSCAN key cursor [MATCH pattern] [COUNT count]
HSCAN key cursor [MATCH pattern] [COUNT count]

얼핏보기에는 KEYS 의 문제점을 모두 해결한 것 같지만, 다음과 같은 한계를 가진다.

  • 기본적으로 SCAN의 경우 table 의 한 블럭을 가져오는 것이라서, 여기에 갯수가 많으면 시간이 많이 걸릴 수도 있다(다만, re-hashing 테이블이 bitmasking 크기만큼 커지므로, 한 블럭이 극단적으로 커질 가능성은 높지 않다).
  • SET/SORTED_SET/HASH 의 내부 구조가 hash table 이나 skiplist 가 아닐 경우(ziplist 로 구현되어 있을 경우), 한 컬렉션의 모든 데이터를 가져오므로, KEYS 명령과 비슷한 문제가 그대로 발생할 수 있다.
  • 명령의 옵션으로 count 값을 지정할 수 있지만, 정확히 그 갯수를 보장하지는 않는다.
  • 순회가 시작(cursor 값을 0으로 지정한 SCAN 명령)된 이후에 추가된 항목은 전체 순회(full iteration; scan 명령의 반환된 cursor 값이 0)가 끝날 때까지 반환되지 않는다(Cursor 가 이미 지나갔으므로).
  • HASH table 이 확장/축소/re-hashing 될 때 다시 스캔하지 않기 때문에 같은 항목이 여러번 반환될 수 있다. 반환된 키 값으로 다른 명령을 실행하려면 주의해야 한다.

SLAVEOF

Slave 설정을 변경한다.

127.0.0.1:6379> help SLAVEOF

  SLAVEOF host port
  summary: Make the server a slave of another instance, or promote it as master
  since: 1.0.0
  group: server

slave 설정시, 모든 데이터는 master 와 동기화 된다. 즉, 동기화 하기 전에 slave 쪽에 중복되는 데이터가 있다면, master 쪽의 데이터로 덮어써지게 된다.

See also

RENAME

Key 를 업데이트/변경 한다.

RENAME key newkey 

Errors

Cannot allocate memory

Redis 는 기본적으로 In-memory database 이다. 이 말은 모든 데이터베이스 정보들을 메모리에 저장한다는 뜻이다. 그런데, 만약 Redis 에 쌓여가는 데이터는 늘어만가고, 더이상 할당 가능한 메모리가 없다면 어떻게 될까?

속도가 엄청나게 느려진다. 보통은 1초안에 끝나는 검색이 10초 이상이 소요되게 된다.

그리고 로그 파일에는 다음과 같은 로그가 나타나게 된다.

[16451] 18 Jun 13:53:02 # Can't save in background: fork: Cannot allocate memory
[16451] 18 Jun 13:53:02 * 1 changes in 900 seconds. Saving... 

해결방법으로는 이곳<ref>http://pydelion.com/2013/05/27/redis-cant-save-in-background-fork-cannot-allocate-memory/</ref>을 참조하면 된다. 간단히, 아래 명령어를 사용하면 문제를 해결할 수 있다.

$ sysctl -w vm.overcommit_memory=1

하지만 이는 어디까지나, 단편적이고, 일회용적인 해결 방법이다. 재부팅을 하게되면 원래 설정대로 돌아간다. 주의하자.

보다, 근본적인 문제는, In-Memory DB 에서 저장해야 할 데이터는 많은데, 사용가능한 메모리가 부족하다는 것이다. 저장되는 데이터를 줄이거나, 메모리 크기를 늘리는 것이 해답이다.

See also

References

<references />