Redis 不仅仅是一个简单的键值对存储,它实际上是支持多种数据类型的数据结构的服务器。当其他传统的键值存储还在处理string类型的key和value时,redis 已经不仅仅支持简单的key-value存储, 它可以处理许多复杂的数据类型。
- 二进制安全的string
- Lists: 有序的string链表
- Sets: 去重的容器
- Sorted Sets: 与Sets大致相似,但不同的是, 每个Sorted Set里的元素都有一个float类型的score。 Score用来给集合里的元素排序。我们可以从有序的集合中取出一定范围的数据元素。
- Hashes: 每个元素都由不特定的属性和值对与之关联。属性和值都是string类型, 类似于python,ruby 里的Hashes。
- Bitmap: 把string看成位数组,redis 提供自己的方法单独的对每一位操作,统计位值为1的总数等方法。
- HyoerLogLogs: 这是即将加入redis基本数据类型,主要用于处理集合的基数。
Redis Keys
Redis Keys 是二进制安全的,这意味这你可以使用任何二进制字符串作为key。 从简单字符串 “foo”到 复杂的图片字节流都可以用作redis的key,包括空字符串。
Keys的一些注意点:
- 用作key的字符串即不应该太长也不应该太短。举个例子,用一个1024 bytes的字符串作为key,它不仅仅占用了过多的内存空间 而且在查找这个key时也会消耗太多的资源。甚至在算它hash值时也需要很多内存资源。而当字符串太短的时候, 往往不能准确的表达信息, 如 “user:1000:followers” 就比 “u1000flw”好理解,使用一个有实际意义容易理解的key字符串,便于开发维护。字符串key长的时候会消耗资源, 短的时候不能表达准确完整的信息。你需要在两者之间找到平衡点,在兼顾效率的同时,找到一个表达清晰的key字符串。
- key的字符串,应该有个固定的模式,清晰地表达它的实际意义。像”object-type:id”这样的模式是不错的格式。点或者冒号可以用来区分不同的名词, 如 “comment:1234:reply.to” 或者”comment:1234:reply-to”。
- 最大的key字符串大小是512MB。
Redis Strings
字符串是redis中最简单的值类型。它是Memcached的唯一数据类型的,所以对很多redis新手来说并不陌生。
当使用Redis Strings时, 我们其实在做一个stirng到string的映射。
在缓存HTML片段或者页面的时候,Redis String是一个很好的选择。
通过redis-cli, 我们简单使用下Redis String 数据类型。
> set mykey somevalue
OK
> get mykey
"somevalue"
你可以看到我们用 SET 和 GET 命令来存取键值。 注意 SET 会覆盖任何已存在的一样key的值。
所以 SET 就像一个赋值操作。值可以是任意的字符串(包括二进制数据),如你可以存储图片的二进制数据在值里。但是一个值不能超过512MB。
SET有一些其他有意思的参数, 如当key已存在时 不会覆盖原值,或者与之相反,只有在key存在时, 才能更新。
> set mykey newval nx
(nil)
> set mykey newval xx
OK
在使用INCR时会默认把string类型的值转成integer,然后再加一,再放回原来的值域中。还有些其它与之类似的命令如 INCRBY,
DECR 和 DECRBY. 它们都是用来做增加操作,只是在使用时略有差别。
为什么说INCR 是原子性的?
即使多个客户端在同时使用INCR 操作同一个key,也不会产生冲突。
举个例子, 当多个client同时调用INCR在同一个key上时,
client 1 读到 "10",而 client 2 读到 "10"然后都增加到11,值就变成11了。这种多线程脏读的情况是不可能在使用INCR时发生的。最终结果永远都只会是12。读,改,写这些操作都是原子性的不可能并发操作。
Redis String还有些其它命令,像
GETSET 这个命令在赋值的同时会把原来的值作为结果返回。 你可以用它来统计网站上的访问人数,每次增加新的访问次数时, 返回已经累计的访问人数。
对多个键值对同时进行存取操作可以提高效率。MSET 和 MGET就是用来进行这样的操作的命令。
> mset a 10 b 20 c 30
OK
> mget a b c
1) "10"
2) "20"
3) "30"
当使用MGET 时, Redis 返回值得数组。
修改和查询key的值
有些命令不局限于特定数据类型,但是对redis数据操作非常实用。
举个例子, EXISTS 返回0或者1(0表示不存在,1表示存在),还有 DEL 可以用来删除键值对。
> set mykey hello
OK
> exists mykey
(integer) 1
> del mykey
(integer) 1
> exists mykey
(integer) 0
从上图你可以看到 DEL本身会返回0或者1作为结果,来告诉客户端删除操作是否成功。0表示删除失败,因为key不存在。
返回值的类型的的命令TYPE 以上三条命令是在与键值操作命令中最主要的三条命令。
> set mykey x
OK
> type mykey
string
> del mykey
(integer) 1
> type mykey
none
R设置key的过期时间
在讨论其它重要的数据类型之前,我们先看下下面比较重要的功能 Redis expires。简单来说你可以给一个key设置过期时间。当一个key过期时, 他会被自动销毁就像对key调用DEL命令
Redis expires 简要信息:
- 过期时间可以是以秒(seconds)或者毫秒(milliseconds)为单位
- 但是过期时间通常毫秒为单位
- 过期时间通常被保存在硬盘上,并不会因为redis是否在运行而更改过期时间
设置key的过期时间:
> set key some-value
OK
> expire key 5
(integer) 1
> get key (immediately)
"some-value"
> get key (after some time)
(nil)
key被销毁了在两次调用 GET 命令之间。因为过期时间被设为5秒. 在上面的例子中我们用 EXPIRE 来设置过期时间。
也可以用 PERSIST H来移除过期时间,那样key就不会被自动销毁。
我们也可以用 SET命令来设置过期十几年 :
> set key 100 ex 10
OK
> ttl key
(integer) 9
上面的例子,我们设置一个key的值为
100
,过期时间为10秒. 后面的 TTL 可以用来显示key还有多久过期