Redis

Design

  • head가 우측에 있다가 생각하자. tail은 좌측에.
         --------------------------------
         [tail]                    [head]       
         --------------------------------
    
  • rpoplpush

Redis Topic

Server Side Script in Redis ( LUA )

  • EVAL: evaluate scripts using the Lua interpreter ( Lua script을 실행한다 )
    • EVAL <script> <따라올 key의 갯수> key1 key2.. arg1 arg2 ...
      • Key의 갯수 중요하다. 없으면 0
      • arg는 ARGV[1], ARGV[2] ... 요런식으로 Lua script에서 사용 가능하다.
        EVAL script numkeys key [key ...] arg [arg ...]
        
        127.0.0.1:8289[6]> eval "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 first second
        1) "key1"
        2) "key2"
        3) "first"
        4) "second"
        127.0.0.1:8289[6]> eval "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 first second third
        1) "key1"
        2) "key2"
        3) "first"
        4) "second"
        127.0.0.1:8289[6]> eval "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 first second third forth
        1) "key1"
        2) "key2"
        3) "first"
        4) "second"
        127.0.0.1:8289[6]> eval "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 first second third forth fifth
        1) "key1"
        2) "key2"
        3) "first"
        4) "second"
        127.0.0.1:8289[6]> eval "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2],ARGV[3]}" 2 key1 key2 first second third forth fifth
        1) "key1"
        2) "key2"
        3) "first"
        4) "second"
        5) "third"
        127.0.0.1:8289[6]> eval "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2],ARGV[3]}" 2 key1 first second third forth fifth
        1) "key1"
        2) "first"
        3) "second"
        4) "third"
        5) "forth"
        
    • eval 실행하면, 해당 script은 Redis에 cached된다. 따라서, evalsha를 이용하여 cached된 script을 sha1 digest로 실행 가능하다.
      redis> evalsha 1b936e3fe509bcbc9cd0664897bbe8fd0cac101b 0
      (error) NOSCRIPT No matching script. Please use EVAL.
      redis> eval "return 'hello'" 0
      "hello"
      redis> evalsha 1b936e3fe509bcbc9cd0664897bbe8fd0cac101b 0
      "hello"
      
  • EVALSHA: SHA1 digest를 이용하여 server에 cached된 script을 실행한다. 없다면, 에러가 남.
    redis> evalsha 1b936e3fe509bcbc9cd0664897bbe8fd0cac101b 0
    "hello"
    
    redis> evalsha e0e1f9fabfc9d4800c877a703b823ac0578ff8db 0
    (error) NOSCRIPT No matching script. Please use EVAL.
    
  • SCRIPT FLUSH: Flush the Lua scripts cache. ( 모두 지워짐 )
    redis> script flush
    
  • SCRIPT LOAD: Load a script into the scripts cache, without executing it. ( 실행하지 않고, 로딩/캐싱만 해 놓음 )
    • script가 cache에 loading 된 이후에는 evalsha를 통해서 실행 가능하다.
    • 한번 로딩(cached)된 script는 SCRIPT FLUSH를 하지 않는한 계속하여 존재한다.
    • 같은 script가 이미 존재해도, 정상적으로 로딩(cached) 된다.
      redis> script load "return 'hello'"
      "1b936e3fe509bcbc9cd0664897bbe8fd0cac101b"
      redis> evalsha 1b936e3fe509bcbc9cd0664897bbe8fd0cac101b 0
      "hello"
      
  • SCRIPT EXISTS: check scripts exist in cache. return 1 if exists, or 0.
    • 여러개의 SHA1 key의 존재 여부도 확인 가능하다.
      redis> script exists 1b936e3fe509bcbc9cd0664897bbe8fd0cac101b
      1) (integer) 1
      

Writing LUA for Redis Server Side Script

  • Null / nil / None
    redis> eval "return false" 0
    (nil)
    
  • return value of hdel if key doesn't exist
    redis> eval "return redis.call('hdel', 'hash::test', 111)" 0
    (integer) 0
    

Writing LUA Redis Server Side Script in PHP

Writing LUA Redis Server Side Script in Python

Redis.py

  • Python interface to use Redis

redis.py connect

redis.py connect through TCP

import redis
redis.Redis(host, port=6379, password="whatever", db=0)

redis.py connect through unixsocket

  • still need password for AUTH if requirepass is enabled in redis.conf. If not, then password param doesn't need to be set.
import redis
redis.Redis(unix_socket_path='/tmp/redis.sock', db=<db>, password='<passwd>')

redis.py pipeline 어떻게 쓰나?

  • 여러개의 redis commands를 atomically 실행한다.
  • 여러개의 redis commands가 한번의 요청으로 실행 되므로 performance가 향상된다.
  • pipeline는 여러개의 redis commands를 buffer해서 한번에 서버쪽에서 실행하는 것이므로, 실행된 command에 대한 값들은 redis.execute가 실행된 후 한번에 돌아온다. 이 말은 즉, pipeline과 execute 사이에서 실행한 command에 대한 값을 이용해서 다음 command를 실행 할 수 없다는 말이 된다.
  • 간단하게 말해서, pipeline은 여러개의 commands를 buffer에 쌓아 두었다가, execute가 실행되었을때, 한번에 server쪽으로 보내서 atomically 전체 명령어를 실행한다는 것이다
    >>> r = redis.Redis(...)
    >>> pipe = r.pipeline()
    >>> pipe.set('foo', 'bar')
    >>> pipe.get('bing')
    >>> pipe.execute()
    [True, 'baz']
    

Redis CLI

  • connect to local redis w/ default port and requirepass disabled
    redis-cli
    
    redis-cli -h 127.0.0.1
    
  • unix socket ( if redis.sock location is defined /tmp/redis.sock
    redis-cli -s /tmp/redis.sock
    

Count matched String KEY

redis> eval "return #redis.pcall('keys', 'abc:*')" 0

Redis Operation

configuration

  • /etc/redis.conf
  • port: TCP socket port
    • default: 6379
    • if port is set 0, then Redis won't listen TCP socket. ( unixsocket can be used. )
      port 6379
      
  • unixsocket
    • default: disabled
    • redis need to be restarted.
    • unix socket user permission: redis:redis
      unixsocket /tmp/redis.sock
      unixsocketperm 700
      

Check Size of Key

  • install rdb package
    yum -y install python-rdbtools.noarch python-setuptools
    
  • check the directory of redis
    egrep ^dir /etc/redis.conf
    
  • run rdb to generate CSV formatted report ( size in byte )
    rdb -c memory /mnt/memory.rdb > memory.csv
    
  • and sum the byte in file
    cat memory.csv | cut -d ',' -f 4 | grep -v byte | awk '{s+=$1} END {print s}'
    
  • by using redis-memory-for-key
    redis-memory-for-key -s <host> -p <port> -a <passwd> -d <db> <key_to_check>
    

maxclients

  • without restarting maxclients can be applied.
    redis> config get maxclients
    1) "maxclients"
    2) "10000"
    
    redis> config set maxclients 20000
    OK
    

maxmemory

  • without restarting maxmemory can be applied
    redis> config get maxmemory
    1) "maxmemory"
    2) "62000000000"
    
    redis> config set maxmemory 62000000000
    OK
    

Redis SCAN Command

MATCH option

COUNT option

hscan

sscan

zscan

external references

Last modified 2 years ago Last modified on 10/04/17 17:44:05