读《The Little Redis Book》

引言

Karl Seguin的一本小册子,很短,边读边实作,发现这把瑞士小军刀挺特别,哈哈。

这里 获取小册子的最新版。

整本小册子主要介绍了五种数据结构String, Hash, List, Set, SortedSet 以其基本用法,一些更为高级的主题如Big O Notation, Transaction和一些重要的命令如expirt, sort,最后提到了有关配置configuration,验证authentication,备份backups,Redis集群cluster等等内容。

我们先安装,然后来看看五个主要的数据结构具体都是怎么玩的。

【以下均以Mac OSX上的操作为例】

安装

官方下载地址:https://redis.io/download

官方给到的安装命令:

1
2
3
4
wget http://download.redis.io/releases/redis-4.0.9.tar.gz
tar xzf redis-4.0.9.tar.gz
cd redis-4.0.9
make

如果你的Mac OSX裝了homebrew的话,直接:

1
brew install redis

装好后,根目录下执行 redis-server, 就跑起来了。

开另一个窗口,执行redis-cli , 进入redis的console, 可以通过info命令来查看更多服务器相关信息。

好了,准备工作完成,来看看这五种数据结构。

Strings

基本用法:

1
2
3
4
5
6
7
8
set users:leto "{name: leto, planet: dune, likes: [spice]}"
get users:leto
strlen users:leto
getrange users:leto 1 9
append users:leto hello
get users:leto
incr stats:page:about
incrby rating:video:12333 5

简单说一下:

set <key> <value> : 存储key-value

get <key> : 获取key

strlen <key>: 获取value的长度

getrange <key> <start> <end> : 获取指定起始与终止位置的value子串

append <key> <new_value> : 给key对应的value追加new_value

incr <key>: value自动加1,没有设置value时,value默认是0

incrbr <key> <num>: 给value加上num

Redis的所有命令可以查阅这里:https://redis.io/commands

此外,可以使用flushdb 清空所有数据。

Hashes

类似Strings的set,get, Hash中使用hset, hget, hmset, hmget.

基本用法:

1
2
3
4
5
6
7
8
hset users:goku powerlevel 900
hget users:goku powerlevel
hmset users:goku race cool age 20
hmget users:goku race powerlevel
hgetall users:goku
hkeys users:goku
hdel users:goku age
del users:goku

看输出其实就知道这些命令都是干嘛的,这里还是简单说一下:

【这里的field,指的就是hash中的key,为了便于区分,用field来代替。】

mset <key> <field1> <value1> <field2> <value2>...: set多个field-value,value默认是string类型

mget <key> <field1> <field2>...: get多个field对应的value

hgetall <key> : 获取所有的field-value

hkeys <key> : 获取所有的fields

hdel <key> <field>: 删除某个field

del <key> : 删除所有的fileds

第四章提到了keys Anti-Pattern, 给到的例子就是用Hashes来CRUD每个账户的bug信息。

Lists

基本用法:

1
2
3
4
5
rpush newusers goku
rpush newusers tom
ltrim newusers 0 10
lrange newusers 0 3
lrange newusers 2 10

简单说一下这些命令:

rpush <list> <item> : push一个item到list, 例子中是在newusers的list中push了一个user goku

ltrim <list> <begin> <end> : trim成指定的长度,例子中是到0~10

lrange <list> <begin> <end> : 获取指定长度的list,上面的例子中,newusers这个list中有goku, tom,对应的index是0,1,所以lrange newuser 0 3输出了goku, tom, 而lrange newuser 2 10则为空。

书中提到了sets的一些场景,可用于存储logs或者跟踪用户浏览网站的足迹。

Sets

sets用来存储唯一值,同时提供一系列以集合为基础的运算,比如并集,交集。

一些基本用法:

1
2
3
4
5
6
7
sadd friends:leto paul tom jessica
sadd friends:duncan paul jessica alia
sismember friends:leto jessica
sismember friends:leto alia
sinter friends:leto friends:duncan
sinterstore friends:leto_duncan friends:leto friends:duncan
smembers friends:leto_duncan

简单说一下这些命令:

sadd <set> <member1> <member2> .... : 给集合添加members

sismember <set> <member> : 判断member是不是set中的元素, 1代表是,0代表不是。

sinter <set1> <set2>: 求两个集合的交集

sinterstore <set1> <set2> <new_set>:将两个集合的交集存储在一个新的集合new_set中

smembers <set> : 查看set的members

Sorted Sets

Sorted Sets可以看成是带有score的sets。

基本用法:

1
2
3
4
5
zadd friends:leto 100 paul 90 tom 98 jessica 80 chani
zcount friends:leto 90 100
zrevrank friends:leto chani
zrank friends:leto chani
zrangebyscore friends:leto -inf +inf

简单说一下这些命令:

zadd <set> <score1> <member1> <score2> <member2>.... : 给set的members添加上score

zcount <set> <score_start> <score_end> : set中score在score_start ~ score_end之间的member个数

zrevrank <set> <member> : 降序排序后member的位置

zrank <set> <member> :升序排序后member的位置【Redis的默认排序是升序】

zrangebyscore <set> -inf +inf : 输出sorted set

sorted set的一个比较常用的场景是用来追踪以时间为纬度的事件。好吧,我没用过,这里就不举例子了。

其他一些好玩的命令

  • Expire

    用来设置key的过期时间。

    看个例子:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    set pages:about 30
    get pages:about
    expire pages:about 20 # 设置过期为20秒后
    ttl pages:about # 查看还剩多少秒过期
    persist pages:about # 取消过期设置
    get pages:about
    expire pages:about 5
    get pages:about # 此时pages:about过期,值变成了nil
    setex pages:detail 30 'More details' # set key= pages:about ,值为More details, 30秒后过期

  • Publication and subscriptions

    可以订阅channel,取消channel,publish message,很cool!

    玩一下。

    在一个window上跑redis-cli, 执行subscribe warnings, 另开一个window跑redis-cli, 执行:publish warnings "hi,Redis~"

    你会看到第一个window中的warnings channel接受到了信息“hi,Redis~”。

  • Monitor

    好用的debugging 工具,可以清晰看到你的所有历史操作。

    直接上图感受下:

  • Sort

    sort可以用来给list,set, sorted set进行排序。

    可以用limit来限定哪些records需要排序,用by指定排序依据。

    看个例子感受下:

Something else

  • pipelining

    Normally when a client sends a request to Redis it waits for the reply before sending the next request. With pipelining you can send a number of requests without waiting for their responses. This reduces the networking overhead and can result in significant performance gains.

    正常情况下,当客户端发送请求给到redis时,它需要得到回复后才可能发送下一条请求。但是通过pipelining, 你可以在不需要等待回复的情况下,向Redis发送大量的请求。这减少了网络开支,显著提升了性能。

    没用过,先记着。

  • Transaction

    每个Redis的命令都是原子性的,当使用多个命令时,Redis同样支持transaction。

    Redis is actually single-threaded, which is how every command is guaranteed to be atomic. While one command is executing, no other command will run.

    Redis如何保证translation? 即原子性,一致性,隔离性,持久性?

    • The commands will be executed in order
    • The commands will be executed as a single atomic operation (without another client’s command being executed halfway through)
    • That either all or none of the commands in the transaction will be executed

The end

读技术类书籍果然不比一般书籍,得跟着实作才有感觉,真想向天再借500年……