WebエンジニアのためのはじめてのredisWebエンジニアのためのはじめてのredis
@nasa9084@nasa9084
$ whoami$ whoami
Masahiro Kitamura
@nasa9084
VirtualTech Japan Inc.
KEYWORDS: emacs python golang(new!) whiske?y
redisredis
What is "redis"?What is "redis"?
remote dictionary server
Key-Value Store (KVS)
Varied Data Structure
in-memory
having persistence
easy and fast
compatible w/Python, Ruby, …
→web engineers should learn redis!
Key-value Store (KVS)Key-value Store (KVS)
dict(Python)
hash(Perl, Ruby)
map(C++, Java, Go)
namespaces
Comparison with RDBMSsComparison with RDBMSs
Function RDBMS Redis
using simply △ ◎
high speed processing △ ◎
horizontal distribution × ◎
high availability △ ◎
persistency ◎ ○
complex query ◎ ×
transaction ◎ △
consistency ◎ △
Comparison with memcachedComparison with memcached
memcached redis
good at Cache Cache
data structure only string varied structure
persistency × ○
Disk I/O NOT DO can be disable
speed high high
multi thread ○ ×
memory efficiency △ ○
Redis Data StructureRedis Data Structure
StringString
String
replace
get length
number
INCR / DECR
max: 512MB
binary safe
can insert pictures, etc
StringString
redis python
> SET hoge fugafuga
OK
> GET hoge
"fugafuga"
> SET point 10
OK
> GET point
"10"
> INCR point
(integer) 11
> GET point
"11"
from redis import Redis
redis = Redis()
redis.set('hoge', 'fugafuga')
print(redis.get('hoge'))
#=> b'fugafuga'
redis.set('point', 10)
print(redis.get('point'))
#=> b'10'
redis.incr('point')
print(redis.get('point'))
#=> b'11'
ListList
List of Strings
Implemented with Linked List
insert or access to head or tail:
access to mid:
max size: 232-1 elements
O(1)
O(N)
ListList
redis python
> LPUSH 1 2 3
(integer) 3
> LRANGE piyo 0 -1
"3"
"2"
"1"
> LPOP piyo
"3"
> LRANGE piyo 0 -1
"2"
"1"
from redis import Redis
redis = Redis()
redis.lpush('piyo', 1, 2, 3)
print(redis.lrange('piyo', 0, -1))
#=> [b'3', b'2', b'1']
print(redis.lpop('piyo'))
#=> b'3'
print(redis.lrange('piyo', 0, -1))
#=> [b'2', b'1']
SetSet
Set of Strings
un-ordered
no duplication
add, delete, access avarage:
max size: 232-1 elements
O(1)
SetSet
redis python
> SADD foo 1 3 5
(integer) 3
> SMEMBERS foo
"1"
"3"
"5"
> SADD foo 1
(integer) 0
> SMEMBERS foo
"1"
"3"
"5"
from redis import Redis
redis = Redis()
redis.sadd('foo', 1, 3, 5)
print(redis.smembers('foo'))
#=>{b'3', b'5', b'1'}
redis.sadd('foo', 1)
print(redis.smembers('foo'))
#=>{b'3', b'5', b'1'}
Sorted Set (ZSet)Sorted Set (ZSet)
Set of Strings
no duplication
each members are ordered with its Score
take Score:
add:
O(1)
O(log N)
Sorted Set (ZSet)Sorted Set (ZSet)
redis python
> ZADD bar 20 ham
(integer) 1
> ZADD bar 10 egg
(integer) 1
> ZADD bar 30 spam
(integer) 1
> ZRANGE bar 0 -1 WITHSCORES
1) "egg"
2) "10"
3) "ham"
4) "20"
5) "spam"
6) "30"
from redis import Redis
redis = Redis()
redis.zadd('bar', 'ham', 20)
redis.zadd('bar', 'egg', 10)
redis.zadd('bar', 'spam', 30)
print(
redis.zrange('bar', 0, -1, withscores=True)
)
#=>[(b'egg', 10.0), (b'ham', 20.0), (b'spam', 30.0)]
HashHash
String to String map
Java: HashMap<String, String>
Go: ~map[string]string
add, delete, access:
max size: 232-1 pairs
O(1)
HashHash
redis python
> HSET bar 0:00 5
(integer) 1
> HGETALL bar
1) "0:00"
2) "5"
> HMSET bar 1:00 5 2:00 6
(integer) 2
> HKEYS bar
1) "0:00"
2) "1:00"
3) "2:00"
> HGET bar 0:00
"5"
from redis import Redis
redis = Redis()
redis.hset('bar', '0:00', '5')
print(redis.hgetall('bar'))
#=>{b'0:00': b'5'}
add_dict = {
'1:00': '5',
'2:00': '6'
}
redis.hmset('bar', add_dict)
print(redis.hkeys('bar'))
#=>[b'0:00', b'1:00', b'2:00]
print(redis.hget('bar', '0:00'))
#=>b'5'
UsecasesUsecases
data having expirationdata having expiration
can set expiration to key
EXPIRE key seconds
`key` is expired after `seconds` seconds
EXPIREAT key timestamp
`key` is expired on `timestamp`
for example,for example,
Session ID
One Time Token
Sample CodeSample Code
from redis import Redis
from uuid import uuid4
class User:
def generate_apikey(self):
redis = Redis(host='localhost', port=6389)
if redis.exists(self.token):
return self.token
new_apikey = 'hbt-' + str(uuid4())
ttl = 10 * 60 * 60 # 10 minutes
redis.setex(new_apikey, self.name, ttl)
self.apikey = new_apikey
return self.apikey
https://github.com/web-apps-tech/hubotmaker.git
https://hubot.web-apps.tech/
Real Time RankingReal Time Ranking
sorted set
zadd key score member
keyにscore点を持ったmemberを追加する add
a `member` that has `score` to `key`
zincrby key increment member
increment score of `member` of `key`
zrange key start stop
get `key`s members from `start` to `stop`
Sample CodeSample Code
from redis import Redis
redis = Redis()
while True:
print('input member:score> ', end='')
ipt = input()
if ipt == 'show': # command 'show'
ranking = redis.zrange('ranking', 0, 5, withscores=True)[::-1]
for i, m in enumerate(ranking):
values = {
'rank': i+1,
'member': m[0].decode(),
'point': m[1]
}
print('{rank}: {member} ({point}pt)'.format(**values))
continue
member, score = args.split(':')
redis.zadd('ranking', member, int(score))
print('good bye')
https://github.com/nasa9084/samples.git
try to use redistry to use redis
try redistry redis
http://try.redis.io/
official docker containerofficial docker container
$ docker run redis
in conclusionin conclusion
in-memory KVS
having persistency
very varied data structure
String, List, Set, Hash, SortedSet
you can try to use redis with `try redis`

Webエンジニアのためのはじめてのredis

  • 1.
  • 2.
    $ whoami$ whoami MasahiroKitamura @nasa9084 VirtualTech Japan Inc. KEYWORDS: emacs python golang(new!) whiske?y
  • 3.
  • 4.
    What is "redis"?Whatis "redis"? remote dictionary server Key-Value Store (KVS) Varied Data Structure in-memory having persistence easy and fast compatible w/Python, Ruby, … →web engineers should learn redis!
  • 5.
    Key-value Store (KVS)Key-valueStore (KVS) dict(Python) hash(Perl, Ruby) map(C++, Java, Go) namespaces
  • 6.
    Comparison with RDBMSsComparisonwith RDBMSs Function RDBMS Redis using simply △ ◎ high speed processing △ ◎ horizontal distribution × ◎ high availability △ ◎ persistency ◎ ○ complex query ◎ × transaction ◎ △ consistency ◎ △
  • 7.
    Comparison with memcachedComparisonwith memcached memcached redis good at Cache Cache data structure only string varied structure persistency × ○ Disk I/O NOT DO can be disable speed high high multi thread ○ × memory efficiency △ ○
  • 8.
  • 9.
    StringString String replace get length number INCR /DECR max: 512MB binary safe can insert pictures, etc
  • 10.
    StringString redis python > SEThoge fugafuga OK > GET hoge "fugafuga" > SET point 10 OK > GET point "10" > INCR point (integer) 11 > GET point "11" from redis import Redis redis = Redis() redis.set('hoge', 'fugafuga') print(redis.get('hoge')) #=> b'fugafuga' redis.set('point', 10) print(redis.get('point')) #=> b'10' redis.incr('point') print(redis.get('point')) #=> b'11'
  • 11.
    ListList List of Strings Implementedwith Linked List insert or access to head or tail: access to mid: max size: 232-1 elements O(1) O(N)
  • 12.
    ListList redis python > LPUSH1 2 3 (integer) 3 > LRANGE piyo 0 -1 "3" "2" "1" > LPOP piyo "3" > LRANGE piyo 0 -1 "2" "1" from redis import Redis redis = Redis() redis.lpush('piyo', 1, 2, 3) print(redis.lrange('piyo', 0, -1)) #=> [b'3', b'2', b'1'] print(redis.lpop('piyo')) #=> b'3' print(redis.lrange('piyo', 0, -1)) #=> [b'2', b'1']
  • 13.
    SetSet Set of Strings un-ordered noduplication add, delete, access avarage: max size: 232-1 elements O(1)
  • 14.
    SetSet redis python > SADDfoo 1 3 5 (integer) 3 > SMEMBERS foo "1" "3" "5" > SADD foo 1 (integer) 0 > SMEMBERS foo "1" "3" "5" from redis import Redis redis = Redis() redis.sadd('foo', 1, 3, 5) print(redis.smembers('foo')) #=>{b'3', b'5', b'1'} redis.sadd('foo', 1) print(redis.smembers('foo')) #=>{b'3', b'5', b'1'}
  • 15.
    Sorted Set (ZSet)SortedSet (ZSet) Set of Strings no duplication each members are ordered with its Score take Score: add: O(1) O(log N)
  • 16.
    Sorted Set (ZSet)SortedSet (ZSet) redis python > ZADD bar 20 ham (integer) 1 > ZADD bar 10 egg (integer) 1 > ZADD bar 30 spam (integer) 1 > ZRANGE bar 0 -1 WITHSCORES 1) "egg" 2) "10" 3) "ham" 4) "20" 5) "spam" 6) "30" from redis import Redis redis = Redis() redis.zadd('bar', 'ham', 20) redis.zadd('bar', 'egg', 10) redis.zadd('bar', 'spam', 30) print( redis.zrange('bar', 0, -1, withscores=True) ) #=>[(b'egg', 10.0), (b'ham', 20.0), (b'spam', 30.0)]
  • 17.
    HashHash String to Stringmap Java: HashMap<String, String> Go: ~map[string]string add, delete, access: max size: 232-1 pairs O(1)
  • 18.
    HashHash redis python > HSETbar 0:00 5 (integer) 1 > HGETALL bar 1) "0:00" 2) "5" > HMSET bar 1:00 5 2:00 6 (integer) 2 > HKEYS bar 1) "0:00" 2) "1:00" 3) "2:00" > HGET bar 0:00 "5" from redis import Redis redis = Redis() redis.hset('bar', '0:00', '5') print(redis.hgetall('bar')) #=>{b'0:00': b'5'} add_dict = { '1:00': '5', '2:00': '6' } redis.hmset('bar', add_dict) print(redis.hkeys('bar')) #=>[b'0:00', b'1:00', b'2:00] print(redis.hget('bar', '0:00')) #=>b'5'
  • 19.
  • 20.
    data having expirationdatahaving expiration can set expiration to key EXPIRE key seconds `key` is expired after `seconds` seconds EXPIREAT key timestamp `key` is expired on `timestamp`
  • 21.
  • 22.
    Sample CodeSample Code fromredis import Redis from uuid import uuid4 class User: def generate_apikey(self): redis = Redis(host='localhost', port=6389) if redis.exists(self.token): return self.token new_apikey = 'hbt-' + str(uuid4()) ttl = 10 * 60 * 60 # 10 minutes redis.setex(new_apikey, self.name, ttl) self.apikey = new_apikey return self.apikey https://github.com/web-apps-tech/hubotmaker.git https://hubot.web-apps.tech/
  • 23.
    Real Time RankingRealTime Ranking sorted set zadd key score member keyにscore点を持ったmemberを追加する add a `member` that has `score` to `key` zincrby key increment member increment score of `member` of `key` zrange key start stop get `key`s members from `start` to `stop`
  • 24.
    Sample CodeSample Code fromredis import Redis redis = Redis() while True: print('input member:score> ', end='') ipt = input() if ipt == 'show': # command 'show' ranking = redis.zrange('ranking', 0, 5, withscores=True)[::-1] for i, m in enumerate(ranking): values = { 'rank': i+1, 'member': m[0].decode(), 'point': m[1] } print('{rank}: {member} ({point}pt)'.format(**values)) continue member, score = args.split(':') redis.zadd('ranking', member, int(score)) print('good bye') https://github.com/nasa9084/samples.git
  • 25.
    try to useredistry to use redis
  • 26.
  • 27.
    official docker containerofficialdocker container $ docker run redis
  • 28.
    in conclusionin conclusion in-memoryKVS having persistency very varied data structure String, List, Set, Hash, SortedSet you can try to use redis with `try redis`