@mritd
2016-01-14T13:42:43.000000Z
字数 8825
阅读 1722
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 的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 恢复到挂掉前的状态
字符串(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 相关方法如下
hset(key, field, value) 向名称为key的hash中添加元素field<—>value
hget(key, field) 返回名称为key的hash中field对应的value
hmget(key, field1,...,field N) 返回名称为key的hash中field i对应的value
hmset(key, field1, value1,...,field N, value N) 向名称为key的hash中添加元素field i<—>value i
hincrby(key, field, integer) 将名称为key的hash中field的value增加integer
hexists(key, field) 名称为key的hash中是否存在键为field的域
hdel(key, field) 删除名称为key的hash中键为field的域
hlen(key) 返回名称为key的hash中元素个数
hkeys(key) 返回名称为key的hash中所有键
hvals(key) 返回名称为key的hash中所有键对应的value
hgetall(key) 返回名称为key的hash中所有的键(field)及其对应的value
示例操作如下
redis> HMSET user:1000 username antirez password P1pp0 age 34
OK
redis> HGETALL user:1000
1) "username"
2) "antirez"
3) "password"
4) "P1pp0"
5) "age"
6) "34"
redis> HSET user:1000 password 12345
(integer) 0
redis> HGETALL user:1000
1) "username"
2) "antirez"
3) "password"
4) "12345"
5) "age"
6) "34"
redis>
由于命令太多,所以不一一列举,具体参考 Redis命令参考,文档已进行离线缓存 Redis命令手册下载
将字符串值
value
关联到key
(设置值)。
如果 key 已经持有其他值,SET
就覆写旧值,无视类型。
对于某个原本带有生存时间(TTL)的键来说,当SET
命令成功在这个键上执行时,这个键原有的 TTL 将被清除。
可选参数
EX second
;设置键的过期时间为 second 秒。 SET key value EX second 效果等同于 SETEX key second value 。 PX millisecond
;设置键的过期时间为 millisecond 毫秒。 SET key value PX millisecond 效果等同于 PSETEX key millisecond value 。可接受的语法
SET KEY VALUE [OPTION] [OPTION_VALUE]
代码示例
SET a 10 # 设置 key a value 10
SET a 10 EX 10 # 同上,但有效期为10秒,过期后再 get key 则返回nil
SET a 10 PX 10000 # 同上,有效期为10000毫秒
SET a 10 NX # 仅当 a 不存在时才进行设置,否则返回错误
SET a 10 XX # 仅当 a 存在时进行设置
返回
key
所关联的字符串值。(获取值)
如果key
不存在那么返回特殊值nil
。
假如key
储存的值不是字符串类型,返回一个错误,因为GET
只能用于处理字符串值。
可接受的语法
GET KEY
代码示例
SET a 10 # 先设置一个值
GET a # 获取 a 的值,此时 a 必须为String,否则返回错误
GET b # 尝试获取一个不存在的值时 返回nil
同时设置一个或多个
key-value
对。
如果某个给定key
已经存在,那么MSET
会用新值覆盖原来的旧值,如果这不是你所希望的效果,请考虑使用MSETNX
命令:它只会在所有给定key
都不存在的情况下进行设置操作。
MSET
是一个原子性(atomic)操作,所有给定key
都会在同一时间内被设置,某些给定key
被更新而另一些给定key
没有改变的情况,不可能发生。
可接受的语法
MSET KEY1 VALUE1 KEY2 VALUE2 ...
代码示例
MSET a 10 b 11 c 12 # 同时设置 a、b、c的值,要么全部成功要么全部失败
返回所有(一个或多个)给定
key
的值。
如果给定的key
里面,有某个key
不存在,那么这个key
返回特殊值nil
。因此,该命令永不失败。
可接受的语法
MGET KEY1 KEY2 KEY3 ...
代码示例
localhost:6379> MSET a 10 b 11 c 12
OK
localhost:6379> MGET a b c d # d 不存在 则返回 nil
1) "10"
2) "11"
3) "12"
4) (nil)
localhost:6379>
用
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 操作,无须再重新内存。
可接受的语法
SETRANGE KEY STR_VALUE
代码示例
localhost:6379> SET a "123456789"
OK
localhost:6379> SETRANGE a 5 "XX"
(integer) 9
localhost:6379> GET a
"12345XX89"
localhost:6379> SETRANGE a 5 "XXXXXXXXXXXXXX" # 超过原有长度自动拼接
(integer) 19
localhost:6379> GET a
"12345XXXXXXXXXXXXXX"
localhost:6379> SETRANGE a 7 "XXXX" # 不够的话自动用 \x00 占位
(integer) 11
localhost:6379> GET a
"123\x00\x00\x00\x00XXXX"
返回
key
中字符串值的子字符串,字符串的截取范围由start
和end
两个偏移量决定(包括 start 和 end 在内)。负数偏移量表示从字符串最后开始计数, -1 表示最后一个字符, -2 表示倒数第二个,以此类推。GETRANGE
通过保证子字符串的值域(range)不超过实际字符串的值域来处理超出范围的值域请求。在 <= 2.0 的版本里,GETRANGE 被叫作 SUBSTR。
可接受的语法
GETRANGE KEY START_INDEX END_INDEX
代码示例
localhost:6379> SET a "test GETRANGE"
OK
localhost:6379> GETRANGE a 0 3 # 获取0~3位置字符
"test"
localhost:6379> GETRANGE a 0 100 # 超过长度则表示获取全部
"test GETRANGE"
localhost:6379> GETRANGE a -3 -1 # 获取只能从左到右获取
"NGE"
localhost:6379> GETRANGE a -1 -3 # 回绕操作将返回空串
""
localhost:6379> GETRANGE a 0 -1 # 正确的获取全部字符串
"test GETRANGE"
localhost:6379>
如果
key
已经存在并且是一个字符串,APPEND
命令将value
追加到key
原来的值的末尾。如果key
不存在,APPEND
就简单地将给定 key 设为value
,就像执行SET key value
一样。
可接受的语法
APPEND KEY STRING_VALUE
代码示例
localhost:6379> EXISTS b # b 不存在
(integer) 0
localhost:6379> APPEND b "test not exists" # 此时进行 APPEND 操作等同于 SET
(integer) 15
localhost:6379> GET b
"test not exists"
localhost:6379> APPEND b "XXXXXXX" # 拼接字符串
(integer) 22
localhost:6379> GET b
"test not existsXXXXXXX"
localhost:6379>
List类型是按照插入顺序排序的字符串链表。和普通链表一样,可以在其头部和尾部添加新的元素。插入时,如果该键不存在,将为该键创建一个新的链表。与此相反,如果链表中所有的元素均被移除,那么该键也将会被从数据库中删除。List中可以包含的最大元素数量是4294967295。
从元素插入和删除的效率来看,如果我们是在链表的两头插入或删除元素,这将会是非常高效的操作,即使链表中已经存储了百万条记录,该操作也可以在常量时间内完成。如果元素插入或删除操作是作用于链表中间,那将会是非常低效的。
将一个或多个值放入
List
中,RPUSH
新加入的元素将放在List
链表尾部(右),LPUSH
同理放在左边,如果对应的List
的key
不存在,将自动创建一个List
,并将值放入List
中;当key
存在,且不是List
类型时,将返回错误。
可接受的语法
RPUSH/LPUSH KEY VALUE1 VALUE2 VALUE3 # 同时放入多个值
RPUSH/LPUSH KEY VALUE # 每次只放入一个值
代码示例
localhost:6379> RPUSH list1 1 2 3 4
(integer) 4
localhost:6379> LRANGE list1 0 -1 # 获取List所有值
1) "1"
2) "2"
3) "3"
4) "4"
localhost:6379>
返回指定
List
的长度,如果给定的KEY
不存在则返回0,如果给定的KEY
不是List
类型将返回错误。
可接受的语法
LLEN KEY
代码示例
localhost:6379> LLEN list1
(integer) 4
localhost:6379> LLEN L
(integer) 0
localhost:6379>
返回指定返回的
List
的值,如果开始值大于List
的长度,那么将返回空列表,如果结束值大于List
长度,那么将示结束值为List
最大长度。
可接受的语法
LRANGE KEY START END
代码示例
localhost:6379> LRANGE list1 0 3
1) "1"
2) "2"
3) "3"
4) "4"
localhost:6379> LRANGE list1 10 11
(empty list or set)
localhost:6379> LRANGE list1 0 1000
1) "1"
2) "2"
3) "3"
4) "4"
截取列表指定位置的元素,当Start值大于
List
长度时,将返回空列表;当End值大于List
长度时,示End值为List
长度。
可接受的语法
LTRIM KEY START END
代码示例
localhost:6379> RPUSH list 1 2 3 4 5 6 7 8 9 10
(integer) 10
localhost:6379> LTRIM list 1 9
OK
localhost:6379> LRANGE list 0 -1
1) "2"
2) "3"
3) "4"
4) "5"
5) "6"
6) "7"
7) "8"
8) "9"
9) "10"
localhost:6379> LTRIM list 5 100
OK
localhost:6379> LRANGE list 0 -1
1) "7"
2) "8"
3) "9"
4) "10"
localhost:6379> LTRIM list 50 100
OK
localhost:6379> LRANGE list 0 -1
(empty list or set)
localhost:6379>
获取指定位置的值,超出位置(不在
List
范围内)返回nil。
可接受的语法
LINDEX KEY INDEX
代码示例
localhost:6379> RPUSH list 1 2 3 4 5 6 7 8 9
(integer) 9
localhost:6379> LINDEX list 3
"4"
localhost:6379> LINDEX list 100
(nil)
localhost:6379>
移除列表中与指定值相等的元素,
在最新版本 3.0.6测试,无论下面的 count等于多少,都会移除所有目标值,只是搜索方向问题,尚不清楚原因
可接受的语法
LREM KEY COUNT VALUE
代码示例
localhost:6379> RPUSH list 0 0 xxx 0 xxx xxx 0 0 0 xxx 0
(integer) 11
localhost:6379> LRANGE list 0 -1
1) "0"
2) "0"
3) "xxx"
4) "0"
5) "xxx"
6) "xxx"
7) "0"
8) "0"
9) "0"
10) "xxx"
11) "0"
localhost:6379> LREM list 5 xxx
(integer) 4
localhost:6379> LRANGE list 0 -1
1) "0"
2) "0"
3) "0"
4) "0"
5) "0"
6) "0"
7) "0"
localhost:6379> del list
(integer) 1
localhost:6379> RPUSH list 0 0 xxx 0 xxx xxx 0 0 0 xxx 0
(integer) 11
localhost:6379> LRANGE list 0 -1
1) "0"
2) "0"
3) "xxx"
4) "0"
5) "xxx"
6) "xxx"
7) "0"
8) "0"
9) "0"
10) "xxx"
11) "0"
localhost:6379> LREM list 6 "xxx"
(integer) 4
localhost:6379> LRANGE list 0 -1
1) "0"
2) "0"
3) "0"
4) "0"
5) "0"
6) "0"
7) "0"
localhost:6379> del list
(integer) 1
localhost:6379> RPUSH list 0 0 xxx 0 xxx xxx 0 0 0 xxx 0
(integer) 11
localhost:6379> LREM list -6 "xxx"
(integer) 4
localhost:6379> LRANGE list 0 -1
1) "0"
2) "0"
3) "0"
4) "0"
5) "0"
6) "0"
7) "0"
localhost:6379> del list
(integer) 1
localhost:6379> RPUSH list 0 0 xxx 0 xxx xxx 0 0 0 xxx 0
(integer) 11
localhost:6379> LREM list 0 "xxx"
(integer) 4
localhost:6379> del list
(integer) 1
localhost:6379> RPUSH list 0 0 xxx 0 xxx xxx 0 0 0 xxx 0
(integer) 11
localhost:6379>
向指定位置设置值,列表
KEY
不存在将返回错误,坐标不对返回对应错误信息。
可接受的语法
LSET KEY INDEX VALUE
代码示例
localhost:6379> RPUSH list 1 1 1 1 1
(integer) 5
localhost:6379> LSET list 2 xxxx
OK
localhost:6379> LRANGE list 0 -1
1) "1"
2) "1"
3) "xxxx"
4) "1"
5) "1"
localhost:6379>