Redis学习笔记
一、简介
redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(有序集合)和hashs(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。
redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。Redis 是一个高性能的key-value数据库。 redis的出现,很大程度补偿了memcached这类key/value存储的不足,在部 分场合可以对关系数据库起到很好的补充作用。它提供了Python,Ruby,Erlang,PHP客户端,使用很方便。
二、Redis功能
Redis 的Sharding
Redis 支持客户端的Sharding 功能,通过一致性hash 算法实现,当前Redis 不支持故障冗余,在集群中不能在线增加或删除Redis。
Redis 的master/slave 复制
一个master 支持多个slave;Slave 可以接受其他slave 的连接来替代他连接master;复制在master 是非阻塞的,而在slave 是阻塞的;复制被利用来提供可扩展性,在slave 端只提供查询功能及数据的冗余。
Redis 的Virtual Memory 功能(VM)
vm 是Redis2.0 新增的一个非常稳定和可靠的功能,vm 的引入是为了提高Redis 的性能,也就是把很少使用的value 保存到disk,而key 保存在内存中。实际上就是如果你有10w 的keys 在内存中,而只有仅仅10%左右的key 经常使用,那么Redis 可以通过开启VM 尝试将不经常使用的Value 转换到disk 上保存。
Redis 的附加档案(AOF)功能
Redis 通过配置的策略将数据集保存到aof 中,当Redis 挂掉后能够通过aof 恢复到挂掉前的状态
三、Redis 数据类型
字符串(Strings)
字符串是一种最基本的Redis值类型。Redis字符串是二进制安全的,这意味着一个Redis字符串能包含任意类型的数据,例如: 一张JPEG格式的图片或者一个序列化的Ruby对象。一个字符串类型的值最多能存储512M字节的内容。与Memcached一样,一个key对应一个value,其上支持的操作与Memcached的操作类似;但它的功能更丰富。
列表(Lists)
Redis列表是简单的字符串列表,按照插入顺序排序。 你可以添加一个元素到列表的头部(左边)或者尾部(右边)。Lists是一个链表结构,主要功能是push、pop、获取一个范围的所有值等等。操作中key理解为链表的名字。LPUSH命令插入一个新元素到列表头部,而RPUSH命令 插入一个新元素到列表的尾部。当对一个空key执行其中某个命令时,将会创建一个新表。 类似的,如果一个操作要清空列表,那么key会从对应的key空间删除。这是个非常便利的语义,因为如果使用一个不存在的key作为参数,所有的列表命令都会像在对一个空表操作一样。
集合(Sets)
Redis集合是一个无序的字符串合集。你可以以 O(1) 的时间复杂度完成 添加、删除以及测试元素是否存在 的操作。Redis集合有着 不允许相同成员存在 的优秀特性。向集合中多次添加同一元素,在集合中最终只会存在一个此元素。实际上这就意味着,在添加元素前,你并不需要事先进行检验此元素是否已经存在的操作。Redis的集合支持集合运算,可以进行 合集、交集、差集运算。一个集合最多可以包含232-1个元素(4294967295,每个集合超过40亿个元素)。
有序集合(Sorted sets)
Redis有序集合和Redis集合类似,是不包含 相同字符串的合集;他在set的基础上 增加了一个顺序属性,这一属性 在添加修改元素的时候可以指定,每次指定后自动重新按新的值调整顺序。可以理解了有两列的mysql表,一列存value,一列存顺序。操作中key理解为 Sorted sets 的名字。
哈希(Hashes)
Redis hash是一个string类型的field和value的映射表.一个key可对应多个field,一个field对应一个value。将一个对象存储为hash类型,较于每个字段都存储成string类型更能节省内存。新建一个hash对象时开始是用zipmap(又称为small hash)来存储的。这个zipmap其实并不是hash table,但是zipmap相比正常的hash实现可以节省不少hash本身需要的一些元数据存储开销。尽管zipmap的添加,删除,查找都是O(n),但是由于一般对象的field数量都不太多。所以使用zipmap也是很快的,也就是说添加删除平均还是O(1)。如果field或者value的大小超出一定限制后,Redis会在内部自动将zipmap替换成正常的hash实现。
Hashes相关
Hashes 相关方法如下
1 |
|
示例操作如下
1 |
|
四、Redis 数据类型的常用操作
由于命令太多,所以不一一列举,具体参考 Redis命令参考,文档已进行离线缓存 Redis命令手册下载
字符串
SET
将字符串值
value
关联到key
(设置值)。
如果 key 已经持有其他值,SET
就覆写旧值,无视类型。
对于某个原本带有生存时间(TTL)的键来说,当SET
命令成功在这个键上执行时,这个键原有的 TTL 将被清除。
可选参数
- EX
格式为EX second
;设置键的过期时间为 second 秒。 SET key value EX second 效果等同于 SETEX key second value 。 - PX
格式为PX millisecond
;设置键的过期时间为 millisecond 毫秒。 SET key value PX millisecond 效果等同于 PSETEX key millisecond value 。 - NX
只在键不存在时,才对键进行设置操作。 SET key value NX 效果等同于 SETNX key value 。 - XX
只在键已经存在时,才对键进行设置操作。
可接受的语法
1 |
|
代码示例
1 |
|
GET
返回
key
所关联的字符串值。(获取值)
如果key
不存在那么返回特殊值nil
。
假如key
储存的值不是字符串类型,返回一个错误,因为GET
只能用于处理字符串值。
可接受的语法
1 |
|
代码示例
1 |
|
MSET
同时设置一个或多个
key-value
对。
如果某个给定key
已经存在,那么MSET
会用新值覆盖原来的旧值,如果这不是你所希望的效果,请考虑使用MSETNX
命令:它只会在所有给定key
都不存在的情况下进行设置操作。MSET
是一个原子性(atomic)操作,所有给定key
都会在同一时间内被设置,某些给定key
被更新而另一些给定key
没有改变的情况,不可能发生。
可接受的语法
1 |
|
代码示例
1 |
|
MGET
返回所有(一个或多个)给定
key
的值。
如果给定的key
里面,**有某个key
不存在,那么这个key
返回特殊值nil
**。因此,该命令永不失败。
可接受的语法
1 |
|
代码示例
1 |
|
SETRANGE
用
value
参数覆写(overwrite)给定key
所储存的字符串值,从偏移量offset
开始。不存在的key
当作空白字符串处理。可以理解为对指定位置字符串覆盖SETRANGE
命令会确保字符串足够长以便将value
设置在指定的偏移量上,如果给定key
原来储存的字符串长度比偏移量小(比如字符串只有5个字符长,但你设置的offset
是10),那么原字符和偏移量之间的空白将用零字节(zerobytes,"\x00")
来填充。
注意你能使用的最大偏移量是 2^29-1(536870911) ,因为 Redis 字符串的大小被限制在 512 兆(megabytes)以内。如果你需要使用比这更大的空间,你可以使用多个 key 。当生成一个很长的字符串时,Redis 需要分配内存空间,该操作有时候可能会造成服务器阻塞(block)。在2010年的Macbook Pro上,设置偏移量为 536870911(512MB 内存分配),耗费约 300 毫秒,设置偏移量为 134217728(128MB 内存分配),耗费约 80 毫秒,设置偏移量 33554432(32MB 内存分配),耗费约 30 毫秒,设置偏移量为 8388608(8MB 内存分配),耗费约 8 毫秒。注意若首次内存分配成功之后,再对同一个 key 调用 SETRANGE 操作,无须再重新内存。
可接受的语法
1 |
|
代码示例
1 |
|
GETRANGE
返回
key
中字符串值的子字符串,字符串的截取范围由start
和end
两个偏移量决定(包括 start 和 end 在内)。负数偏移量表示从字符串最后开始计数, -1 表示最后一个字符, -2 表示倒数第二个,以此类推。GETRANGE
通过保证子字符串的值域(range)不超过实际字符串的值域来处理超出范围的值域请求。在 <= 2.0 的版本里,GETRANGE 被叫作 SUBSTR。
可接受的语法
1 |
|
代码示例
1 |
|
APPEND
如果
key
已经存在并且是一个字符串,APPEND
命令将value
追加到key
原来的值的末尾。如果key
不存在,APPEND
就简单地将给定 key 设为value
,就像执行SET key value
一样。
可接受的语法
1 |
|
代码示例
1 |
|
List类型
List类型是按照插入顺序排序的字符串链表。和普通链表一样,可以在其头部和尾部添加新的元素。插入时,如果该键不存在,将为该键创建一个新的链表。与此相反,如果链表中所有的元素均被移除,那么该键也将会被从数据库中删除。List中可以包含的最大元素数量是4294967295。
从元素插入和删除的效率来看,如果我们是在链表的两头插入或删除元素,这将会是非常高效的操作,即使链表中已经存储了百万条记录,该操作也可以在常量时间内完成。如果元素插入或删除操作是作用于链表中间,那将会是非常低效的。
RPUSH/LPUSH
将一个或多个值放入
List
中,RPUSH
新加入的元素将放在List
链表尾部(右),LPUSH
同理放在左边,如果对应的List
的key
不存在,将自动创建一个List
,并将值放入List
中;当key
存在,且不是List
类型时,将返回错误。
可接受的语法
1 |
|
代码示例
1 |
|
LLEN
返回指定
List
的长度,如果给定的KEY
不存在则返回0,如果给定的KEY
不是List
类型将返回错误。
可接受的语法
1 |
|
代码示例
1 |
|
LRANGE
返回指定返回的
List
的值,如果开始值大于List
的长度,那么将返回空列表,如果结束值大于List
长度,那么将示结束值为List
最大长度。
可接受的语法
1 |
|
代码示例
1 |
|
LTRIM
截取列表指定位置的元素,当Start值大于
List
长度时,将返回空列表;当End值大于List
长度时,示End值为List
长度。
可接受的语法
1 |
|
代码示例
1 |
|
LINDEX
获取指定位置的值,超出位置(不在
List
范围内)返回nil。
可接受的语法
1 |
|
代码示例
1 |
|
LREM
移除列表中与指定值相等的元素,
在最新版本 3.0.6测试,无论下面的 count等于多少,都会移除所有目标值,只是搜索方向问题,尚不清楚原因
- count > 0 : 从表头开始向表尾搜索,移除与 value 相等的元素,数量为 count 。
- count < 0 : 从表尾开始向表头搜索,移除与 value 相等的元素,数量为 count 的绝对值。
- count = 0 : 移除表中所有与 value 相等的值。
可接受的语法
1 |
|
代码示例
1 |
|
LSET
向指定位置设置值,列表
KEY
不存在将返回错误,坐标不对返回对应错误信息。
可接受的语法
1 |
|
代码示例
1 |
|
RPOPLPUSH/LPOPRPUSH
简单地说用于倒腾两个链表,RPOPLPUSH 将 A 链表最右侧一个元素删除并返回,同时将其放入到 B 链表最左侧,LPOPRPUSH 同理;测试最新版本 3.0.6 已经移除。
可接受的语法
1 |
|
SET类型
SET
是一个无序的字符串合集,可以以O(1) 的时间复杂度完成 添加,删除以及测试元素是否存在的操作;SET
中不允许相同成员存在,向集合中多次添加同一元素,在集合中最终只会存在一个此元素。它支持一些服务端的命令进行集合运算。 我们可以在很短的时间内完成合并(union
),求交(intersection
), 找出不同元素的操作。
SADD
将一个或多个
member(value)
元素加入到集合key
当中,已经存在于集合的member
元素将被忽略。假如key
不存在,则创建一个只包含member
元素作成员的集合。当key
不是集合类型时,返回一个错误。在Redis2.4版本以前, SADD 只接受单个 member 值。
可接受的语法
1 |
|
代码示例
1 |
|
SREM
移除集合
key
中的一个或多个member
元素,不存在的member
元素会被忽略。当key
不是集合类型,返回一个错误。在 Redis 2.4 版本以前, SREM 只接受单个 member 值。
可接受的语法
1 |
|
代码示例
1 |
|
SPOP
移除并返回集合中的一个随机元素。如果只想获取一个随机元素,但不想该元素从集合中被移除的话,可以使用
SRANDMEMBER
命令。被移除的随机元素当key
不存在或key
是空集时,返回nil
。
可接受的语法
1 |
|
代码示例
1 |
|
SMOVE
将
member
元素从source
集合移动到destination
集合;**SMOVE
是原子性操作。**
如果source
集合不存在或不包含指定的member
元素,则SMOVE
命令不执行任何操作,仅返回 0 。否则,member
元素从source
集合中被移除,并添加到destination
集合中去。当destination
集合已经包含member
元素时,SMOVE
命令只是简单地将source
集合中的member
元素删除。当source
或destination
不是集合类型时,返回一个错误。
可接受的语法
1 |
|
代码示例
1 |
|
SCARD
返回指定结合的元素数量
可接受的语法
1 |
|
代码示例
1 |
|
SISMEMBER
判断指定元素是否存在与集合中;如果
member
元素是集合的成员,返回 1 。如果member
元素不是集合的成员,或key
不存在,返回 0 。
可接受的语法
1 |
|
代码示例
1 |
|
SINTER
返回多个集合的交集,不存在的KEY将视为空集,与空集进行取交集操作将返回空集。
可接受的语法
1 |
|
代码示例
1 |
|
SINTERSTORE
基本同上,但是
SINTERSTORE
可以将取出的交集保存到指定集合中。
可接受的语法
1 |
|
代码示例
1 |
|
SUNION
取指定集合的并集
可接受的语法
1 |
|
代码示例
1 |
|
SUNIONSTORE
同
SINTERSTORE
;不做阐述
SDIFF
取指定集合的差集,同
SINTER
、SUNION
可接受的语法
1 |
|
代码示例
1 |
|
对于集合的 合集、差集、并集操作,中文API的解释是
返回一个集合的全部成员
,我的理解是,以第一个集合为准,返回的总是这个结合依次与后续集合运算的结果,并忽略后面集合的元素;具体还是不算太理解……以后研究
ZSET
和Set类型极为相似,它们都是字符串的集合,都不允许重复的成员出现在一个Set中。它们之间的主要差别是zset中的每一个成员都会有一个分数(score)与之关联,Redis正是通过分数来为集合中的成员进行从小到大的排序。然而需要额外指出的是,尽管zset中的成员必须是唯一的,但是分数(score)却是可以重复的。
在zset中添加、删除或更新一个成员都是非常快速的操作,其时间复杂度为集合中成员数量的对数。由于zset中的成员在集合中的位置是有序的,因此,即便是访问位于集合中部的成员也仍然是非常高效的。事实上,Redis所具有的这一特征在很多其它类型的数据库中是很难实现的,换句话说,在该点上要想达到和Redis同样的高效,在其它数据库中进行建模是非常困难的。
ZADD
将一个或多个
member
元素及其score
值加入到有序集 key 当中。如果某个member
已经是有序集的成员,那么更新这个member
的score
值,并通过重新插入这个member
元素,来保证该member
在正确的位置上,同时返回0。score
值可以是整数值或双精度浮点数。如果key
不存在,则创建一个空的有序集并执行ZADD
操作。当key
存在但不是有序集类型时,返回一个错误。
可接受的语法
1 |
|
代码示例
1 |
|
ZCARD
返回集合的长度
可接受的语法
1 |
|
代码示例
1 |
|
ZCOUNT
返回指定
SCORE
之间的元素数量
可接受的语法
1 |
|
代码示例
1 |
|
ZSCORE
查看指定成员的
SCORE
可接受的语法
1 |
|
代码示例
1 |
|
ZINCRBY
对集合中指定
VALUE
的SROCE
加上指定值;当集合KEY
不存在时,相当于ZADD
。
可接受的语法
1 |
|
代码示例
1 |
|
ZRANGE
返回集合内指定区间的元素,其中成员的位置按 score 值递增(从小到大)来排序。具有相同
score
值的成员按字典序(lexicographical order
)来排列。如果需要成员按score
值递减(从大到小)来排列,请使用ZREVRANGE
命令。
可接受的语法
1 |
|
代码示例
1 |
|
ZREVRANGE
同
ZRANGE
只不过SCORE
从大到小排列,略过
ZRANGEBYSCORE
基本同
ZRANGE
一样,但是返回分数在min
和max
之间的所有成员满足表达式min <= score <= max
的成员,其中返回的成员是按照其分数从低到高的顺序返回,如果成员具有相同的分数,则按成员的字典顺序返回。
(
表示小于,默认 包含min
和max
;极限min
和max
可以用-inf
和+inf
表示
可接受的语法
1 |
|
代码示例
1 |
|
ZRANK
返回指定成员位置
可接受的语法
1 |
|
代码示例
1 |
|
ZREM
删除指定元素
可接受的语法
1 |
|
代码示例
1 |
|
ZSCORE
获取指定元素的 分数,如果该成员存在,以字符串的形式返回其分数,否则返回nil。
可接受的语法
1 |
|
代码示例
1 |
|
ZREVRANGEBYSCORE
除了排序方式是基于从高到低的分数排序之外,其它功能和参数含义均与
ZRANGEBYSCORE
相同。
ZREMRANGEBYRANK
删除索引位置位于
start
和stop
之间的成员,start
和stop
都是0-based
,即0
表示分数最低的成员,-1
表示最后一个成员,即分数最高的成员。
ZREMRANGEBYSCORE
删除分数在
min
和max
之间的所有成员,即满足表达式min <= score <= max
的所有成员。
Hashes类型
可以将
Redis
中的Hashes
类型看成具有String Key
和String Value
的map
容器。所以该类型非常适合于存储值对象的信息。如Username
、Password
和Age
等。如果Hash
中包含很少的字段,那么该类型的数据也将仅占用很少的磁盘空间。每一个Hash
可以存储4294967295
个键值对。
HSET
将哈希表 key 中的域 field 的值设为 value 。如果 key 不存在,一个新的哈希表被创建并进行 HSET 操作。如果域 field 已经存在于哈希表中,旧值将被覆盖。
可接受的语法
1 |
|
代码示例
1 |
|
HSETNX
将哈希表 key 中的域 field 的值设置为 value ,当且仅当域 field 不存在。若域 field 已经存在,该操作无效。如果 key 不存在,一个新哈希表被创建并执行 HSETNX 命令。
可接受的语法
1 |
|
代码示例
1 |
|
HGET
返回 key 中指定 field 的 value
可接受的语法
1 |
|
代码示例
1 |
|
HGETALL
获取指定 key 中全部 field 和 value
可接受的语法
1 |
|
代码示例
1 |
|
HEXISTS
判断指定的 key 中的 field 是否存在,1表示存在,0表示 参数中的Field或Key不存在。
可接受的语法
1 |
|
代码示例
1 |
|
HLEN
获取指定 key 中的 field 数量,当 key 不存在时,返回 0 。
可接受的语法
1 |
|
代码示例
1 |
|
HKEYS
返回指定 key 中的 所有 field,当 key 不存在时,返回一个空表。
可接受的语法
1 |
|
代码示例
1 |
|
HVALS
返回指定 key 中所有 field 的 value,当 key 不存在时,返回一个空表。
可接受的语法
1 |
|
代码示例
1 |
|
HDEL
删除指定 key 中的一个或多个 field,返回被成功移除的域的数量,不包括被忽略的域。在Redis2.4以下的版本里, HDEL 每次只能删除单个域,如果你需要在一个原子时间内删除多个域,请将命令包含在 MULTI / EXEC 块内。
可接受的语法
1 |
|
代码示例
1 |
|
HMSET
设置指定 key 的多个 field 对应的 value;此命令会覆盖哈希表中已存在的域。如果 key 不存在,一个空哈希表被创建并执行 HMSET 操作。
可接受的语法
1 |
|
代码示例
1 |
|
HMGET
获取指定 key 中的 多个 field 的 value
可接受的语法
1 |
|
代码示例
1 |
|