set/get命令(如果已经存在该key,则替换)
1 | > set key "abc" |
如果健存在,则执行失败;如果健不存在,则执行成功:
1 | > set key newval nx |
设置Integer值,原子性增减
1 | > set count 100 |
mset/mget命令
1 | > mset a 10 b 20 c 30 |
exists命令【返回1表示数据库中存在,返回0表示数据库中不存在】
1 | > set mykey hello |
type命令【返回某个键的值的类型】
1 | > set key x |
expire命令
过期时间可以设置为秒或者毫秒精度。
过期时间分辨率总是 1 毫秒。
过期信息被复制和持久化到磁盘,当 Redis 停止时时间仍然在计算 (也就是说 Redis 保存了过期时间)
1 | > set key "expire" |
lpush / rpush / lrange / lpop / rpop 命令
1 | //rpush 从右边添加一个元素 |
ltrim 命令
1 | > rpush nlist 1 2 3 4 5 |
列表阻塞操作
BRPOP 和 BLPOP 两个命令
它们是当列表为空时 RPOP 和 LPOP 的会阻塞版本:仅当
一个新元素被添加到列表时,或者到达了用户的指定超时时间,才返回给调用者
1 | //先将tasks填入元素 |
集合、有序集合、哈希三条规则:
- 当我们向聚合(aggregate)数据类型添加一个元素,如果目标键不存在,添加元素前将创建一个空的聚合数
据类型。 - 当我们从聚合数据类型删除一个元素,如果值为空,则键也会被销毁。
- 调用一个像 LLEN 的只读命令(返回列表的长度),或者一个写命令从空键删除元素,总是产生和操作一个持
有空聚合类型值的键一样的结果。
规则1:
1 | > del mylist |
不能执行一个错误键类型的操作
1 | > set foo bar |
规则2:1
2
3
4
5
6
7
8
9
10
11
12> lpush mylist 1 2 3
(integer) 3
> exists mylist
(integer) 1
> lpop mylist
"3"
> lpop mylist
"2"
> lpop mylist
"1"
> exists mylist
(integer) 0
当所有元素弹出后,键就不存在了
规则3:
1 | > del mylist |
哈希/散列
1 | > hmset user:1000 username csh birthday 1993 address GZ |
Set操作
SADD 命令【添加元素到集合】
1 | > sadd myset 1 2 3 |
sismember 命令【判断元素是否在set中】
1 | > sismember myset 3 |
假设,我们想标记新闻。如果我们的 ID 为 1000 的新闻,被标签 1,2,5 和 77 标记,我们可以有一个这篇新闻
被关联标记 ID 的集合:
1 | > sadd news:1000:tags 1 2 5 77 |
然而有时候我们也想要一些反向的关系:被某个标签标记的所有文章:1
2
3
4
5
6
7
8> sadd tag:1:news 1000
(integer) 1
> sadd tag:2:news 1000
(integer) 1
> sadd tag:5:news 1000
(integer) 1
> sadd tag:77:news 1000
(integer) 1
smembers 命令【获取指定对象的标签】
1 | > smembers news:1000:tags |
sinter 命令【获取同时被1,2,10,27标记的新闻】1
2> sinter tag:1:news tag:2:news tag:10:news tag:27:news
... results here ...
扑克例子:
抽取一个元素的命令是 SPOP,就方便为很多问题建模。
例如,为了实现一个基于 web 的扑克游戏,你可以将你的一副牌表示为集合。假设我们使用一个字符前缀表示(C)lubs 梅花, (D)iamonds 方块,(H)earts 红心,(S)pades 黑桃。
1 | > sadd deck C1 C2 C3 C4 C5 C6 C7 C8 C9 C10 CJ CQ CK |
现在我们为每位选手提供 5 张牌。SPOP 命令删除一个随机元素,返回给客户端,是这个场景下的最佳操作。
然而,如果我们直接对这副牌调用,下一局我们需要再填充一副牌,这个可能不太理想。所以我们一开始要复制一下 deck 键的集合到 game:1:deck 键。
这是通过使用 SUNIONSTORE 命令完成的,这个命令通常对多个集合执行交集,然后把结果存储在另一个集合中。而对单个集合求交集就是其自身,于是我可以这样拷贝我的这副牌:
1 | > sunionstore game:1:deck deck |
现在我们准备好为第一个选手提供 5 张牌:1
2
3
4
5
6
7
8
9
10> spop game:1:deck
"C6"
> spop game:1:deck
"CQ"
> spop game:1:deck
"D1"
> spop game:1:deck
"CJ"
> spop game:1:deck
"SJ"
只有一对 jack,不太理想……
现在是时候介绍提供集合中元素数量的命令。这个在集合理论中称为集合的基数(cardinality,也称集合的势),所以相应的 Redis 命令称为 SCARD。
1 | > scard game:1:deck |
数学计算式为:52 - 5 = 47。
当你只需要获得随机元素而不需要从集合中删除,SRANDMEMBER 命令则适合你完成任务。它具有返回重复的和非重复的元素的能力。
有序集合(Sorted Sets)
按照如下规则排序:
• 如果 A 和 B 是拥有不同分数的元素,A.score > B.score,则 A > B。
• 如果 A 和 B 是有相同的分数的元素,如果按字典顺序 A 大于 B,则 A > B。A 和 B 不能相同,因为排序集合只能有唯一元素。
zadd命令【添加有序集合元素】
1 | > zadd hackers 1940 "Alan Kay" |
zrange命令【获取有序集合的一个范围】
1 | > zrange hackers 0 -1 |
zrevrange命令【反顺序】
1 | > zrevrange hackers 0 -1 |
zrangebyscore / zremrangebyscore / zrank 命令
1 | //返回分数在负无穷到 1950 之间的所有元素(包括两个极端) |
字典分数
如果集合中有相同的分数,允许按字典顺序获取范围
1 | > zadd hackers 0 "Alan Kay" 0 "Sophie Wilson" 0 "Richard Stallman" 0 |
位图(Bitmaps)
1 | > setbit key 10 1 |
回收策略(Eviction policies)
当 maxmemory 限制到达的时候,Redis 将采取的准确行为是由 maxmemory-policy 配置指令配置的。
以下策略可用:
• noeviction:当到达内存限制时返回错误。当客户端尝试执行命令时会导致更多内存占用(大多数写命令,除
了 DEL 和一些例外)。
• allkeys-lru:回收最近最少使用(LRU)的键,为新数据腾出空间。
• volatile-lru:回收最近最少使用(LRU)的键,但是只回收有设置过期的键,为新数据腾出空间。
• allkeys-random:回收随机的键,为新数据腾出空间。
• volatile-random:回收随机的键,但是只回收有设置过期的键,为新数据腾出空间。
• volatile-ttl:回收有设置过期的键,尝试先回收离 TTL 最短时间的键,为新数据腾出空间。
当没有满足前提条件的话,volatile-lru,volatile-random 和 volatile-ttl 策略就表现得和 noeviction 一样了。
选择正确的回收策略是很重要的,取决于你的应用程序的访问模式,但是,你可以在程序运行时重新配置策略,使用 INFO 输出来监控缓存命中和错过的次数,以调优你的设置。
一般经验规则:
• 如果你期待你的用户请求呈现幂律分布(power-law distribution),也就是,你期待一部分子集元素被访问得远比其他元素多,可以使用 allkeys-lru 策略。在你不确定时这是一个好的选择。
• 如果你是循环周期的访问,所有的键被连续扫描,或者你期待请求正常分布(每个元素以相同的概率被访问),可以使用 allkeys-random 策略。
• 如果你想能给 Redis 提供建议,通过使用你创建缓存对象的时候设置的 TTL 值,确定哪些对象应该被过期,你可以使用 volatile-ttl 策略。
当你想使用单个实例来实现缓存和持久化一些键,allkeys-lru 和 volatile-random 策略会很有用。但是,通常最好是运行两个 Redis 实例来解决这个问题。
另外值得注意的是,为键设置过期时间需要消耗内存,所以使用像 allkeys-lru 这样的策略会更高效,因为在内存压力下没有必要为键的回收设置过期时间。
回收过程 (Eviction process)
理解回收的过程是这么运作的非常的重要:
• 一个客户端运行一个新命令,添加了新数据。
• Redis 检查内存使用情况,如果大于 maxmemory 限制,根据策略来回收键。
• 一个新的命令被执行,如此等等。
我们通过检查,然后回收键以返回到限制以下,来连续不断的穿越内存限制的边界。
如果一个命令导致大量的内存被占用 (像一个很大的集合交集保存到一个新的键),一会功夫内存限制就会被这个明显的内存量所超越。
参考文章:
Redis 3.0 中文版