redis是remote dictionary server(远程字典服务器)的缩写,它以字典结构存储数据,并允许其他应用通过tcp协议读写字典中的内容,目前为止redis支持的键值数据类型如下:
>>字符串类型
>>散列类型
>>列表类型
>> 集合类型
>> 有序集合类型
redis数据库中的所有数据都存储在内存中。由于内存的读写速度远快于硬盘,因此redis在性能上对比其他基于硬盘存储的数据库有非常明显的优势,在一台普通的笔记本电脑上,redis可以在一秒内读写超过十万个键值。
redis虽然是作为数据库开发的,但由于其提供了丰富的功能,越来越多的人将其用作缓存、队列系统等。
redis可以为每个键设置生存时间(time to live,ttl),生存时间到期后键会自动被删除。这一功能配合出色的性能让redis可以作为缓存系统来使用,而且由于redis支持持久化和丰富的数据类型,使其成为了另一个非常流行的缓存系统memcached的有力竞争者。性能上redis是单线程模型,而memcached支持多线程,所以在多核服务器上后者的性能更高一些。然而redis的性能已经足够优异,在绝大部分场合下其性能都不会成为瓶颈。
redis还可以限定数据占用的最大内存空间,在数据达到空间限制后可以按照一定的规则自动淘汰不需要的键。除此之外,redis的列表类型键可以用来实现队列,并且支持阻塞式读取,可以很容易地实现一个高性能的优先级队列。同时在更高层面上,redis还支持“发布/订阅”的消息模式。
可直接调用redis-server启动对应的服务。正确停止redis的方式是向redis发送shutdown命令: redis-cli shutdown,当redis收到shutdown命令后,会先断开所有客户端连接,然后根据配置执行持久化,最终完成退出。redis-cli是redis自带的基于命令行的redis客户端。
redis通过-h和-p参数自定义地址和端口号。redis提供了ping命令来测试客户端与redis的连接是否正常,如果连接正常会收到回复pong。
命令的返回值有5种类型,对于每种类型redis-cli的展现结果都不同:
1、状态回复,状态回复(status reply)是最简单的一种回复,状态回复直接显示状态信息。
2、错误回复,当出现命令不存在或命令格式有错误时,redis会返回错误回复。错误回复以error开头,并在后面跟上错误信息。
3、整数回复,以integer开头,并在后面跟上整数数据。
4、字符串回复是最常见的一种回复类型,当请求一个字符串类型键的键值或一个其他类型键中的某个元素时就会得到一个字符串回复。字符串回复以双引号包裹。当请求的键值不存在时会得到一个空结果,显示为nil。
5、多行字符串回复,当请求一个非字符串类型键的元素列表时就会收到多个元素列表时就会收到多行字符串回复。多行字符串回复中的每行字符串都以一个序号开头。
每个数据库对外都是以一个从0开始的递增数字命名,redis默认支持16个数据库,可以通过配置参数databases来修改这一数字。客户端与redis建立连接后会自动选择0号数据库,不过可以随时使用select命令更换数据库。但redis不支持自定义数据库的名字,每个数据库都以编号命名,开发者必须自己记录那些数据库存储了哪些数据。redis不支持为每个数据库设置不同的访问密码。一个客户端可以访问全部数据库,要么链一个数据库也没有权限访问。多个数据库之间并不是完全隔离的,flushall命令可以清空一个redis实例中所有数据库中的数据,因此这些数据库更像是一种命名空间,而不适宜存储不同应用程序的数据。不同应用应该使用不同的redis实例存储数据。redis很轻量,一个redis实例占用的内存只有1m,因此多个redis实例不会占用很多内存。
基础命令:
1、获取符合规则的键名列表: keys pattern(通配符的格式) ?匹配一个字符, * 匹配任意个字符, [] 匹配括号间的任一字符,可以使用“-”符合表示一个范围,\x匹配字符x,用于转义符号。
redis不区分命令大小写。
2、判断一个键是否存在: exists key, 若键存在则返回整数类型1,否则返回0。
3、删除键 del key [key ...], 可以删除一个或多个键,返回值是删除的键的个数。但del命令的参数不支持通配符。但尅通过管道和xargs命令实现删除所有符合规则的键。redis-cli keys “user:*”| xargs redis-cli del。也可以redis-cli del ‘redis-cli keys “user:*’
4、获取键值的数据类型: type key, 用来获得键值的数据类型,返回值可能是string(字符串类型)、hash(散列类型)、list(列表类型)、set(集合类型)、zset(有序集合类型)。
字符串
字符串类型是redis中最基本的数据类型,能存储任何形式的字符串,包括二进制数据。可用来存储用户的邮件、json化的对象、图片等。一个字符串类型键允许存储的数据的最大容量是512mb。字符串类型是其他4种数据类的基础。其他数据类型和字符串类型的差别从某种程度来说只是组织字符串的形式不同。
1、赋值与获取: set key value, get key
set和get是redis中最简单的两个命令。当键不存在时会返回空结果。
2、递增数字, incr key, 当存储的字符串是整数形式时,redis提供了一个实用的命令incr,其作用是让当前键值递增,并返回递增后的值。当操作的键不存在时会默认键值为0。所以第一次递增后的结果是1。当键值不是整数时会提示错误(error) err value is not an integer or out of range
所有redis命令都是原子操作,无论多少客户端同时连接,都不会出现竞争问题。redis的键命名规则如下:“对象类型:对象id:对象属性”来命名一个键。对于多个单词则推荐使用"."分割。
自增id,在redis中通过一种模式实现,对于每一类对象使用名为对象类型count的键来存储当前类型对象的数量。没增加一个新对象时都使用incr命令递增该键的值。由于使用incr命令建立的初始键值是1,可很容易得知incr命令的返回值既是加入该对象后的当前类型的对象总数,又是该新增对象的id。
每个字符串类型键只能存储一个字符串,而往往信息包含很多元素,因此为了存储这些元素,需要使用序列化函数将它们转换成一个字符串。
增加指定的整数:incr key increment, increment参数指定一次增加的数值。incrby命令与incr命令基本作用一样。
减少指定的整数:decr key, decrby key decrement。decrement是指定的整数。
增加指定的浮点数: incrbyfloat key increment, 可以递增一个双精度浮点数。
向尾部最佳值: append key value, append作用是向键值的末尾追加value,若干键不存在则将该键的值设置为value,即相当于set key value, 返回值是追加后字符串的总长度。append命令的第二个参数加双引号,原因是该参数包括空格。
127.0.0.1:6379> set key hello
ok
127.0.0.1:6379> keys *
1) "bar"
2) "num"
3) "foo"
4) "key"
127.0.0.1:6379> append key " world!"
(integer) 12
127.0.0.1:6379> get key
"hello world!"
127.0.0.1:6379> strlen key
(integer) 12
获取字符串长度: strlen key, 返回键值的长度,如果键不存在则返回0,字符串类型可以存储二进制数据,可以存储任何编码的字符串。
127.0.0.1:6379> set bar 您好
ok
127.0.0.1:6379> strlen bar
(integer) 6
同时获取设置多个键值:mget key [key ...]
mset key value [key value ...]
127.0.0.1:6379> mset key1 v1 key2 v2 key3 v3
ok
127.0.0.1:6379> mget key1 key2
1) "v1"
2) "v2"
127.0.0.1:6379> mget key1 key3
1) "v1"
2) "v3"
127.0.0.1:6379>
位操作
getbit key offset, 可以获得一个字符串类型键指定位置的二进制位的值(0或1),索引从0开始。如果需要获取的二进制的索引超出了键值的二进制的实际长度则默认为时0.
setbit key offset value, 可以设置字符串类型键指定位置的二进制的值,返回值是该位置的旧值。如果设置的位置超过了键值的二进制位的长度,setbit命令会自动将中间的二进制位设置为0。设置一个不存在的键的指定二进制位的值会自动将其前面的位赋值为0.
bitcount key [start] [end], 可以获得字符串类型键中值是1的二进制位个数。
bitop operatuon destkey key [key ...], 可以对多个字符串类型键进行位运算,将结果存储在destkey参数指定的键中。bitop命令支持的运算操作有and、or、xor和not。
散列
redis是采用字典结构以键值对的形式存储数据,而散列类型的键值也是一种字典结构。其存储了字段和字段值的映射。但字段值只能是字符串,不支持其他数据类型。即散列类型不能嵌套其他的数据类型,一个散列类型键可以包含至多232-1个字段。redis的其他数据类型同样不支持数据类型嵌套。集合类型的每个元素都只能是字符串。
散列类型适合存储:使用对象类别和id构成键名,使用字段标识对象的属性,而字段值则存储属性值。
基本的命令:
赋值和获取值
hset key field value
hset key field
hmset key field value [field value ...]
hmget key field [field]
hgetall key
hset命令你去分插入和更新,意味着膝盖数据时不用事先判断字段是否存在来决定是要执行插入还是更新。当执行的是插入操作时hset命令返回1,当执行的是更新操作时hset会返回0。当键本身不存在时,hset会自动创建它。
在redis中每个键都属于一个明确的数据类型,如通过hset命令建立的键是散列类型。通过set命令建立的键是字符串类型。使用一种数据类型的命令操作另一种数据类型的键会提示错误。
需要同时设置多个字段的值时可以使用hmset命令。hmget命令可以同时获取多个字段的值。
如果想获取键中所有字段和字段值却不知道键中有哪些字段时应该使用hgetall命令。返回的结果是字段和字段值组成的列表。
判断某个字段是否存在: hexists key field
当字段不存在时赋值: hsetnx key filed value
增加和减小某个字段:hincrby key filed num,没有hincr相关的命令。
删除某个字段: hdel key filed [field], 可以删除一个或多个字段,返回值是被删除的字段个数。
获取字段名或字段值:
hkeys key, 获取键中所有字段的名字
hvals key,获取键中所有字段值
hlen key, 获取字段数量
列表
列表类型可以存储一个有序的字符列表,常用的了操作是向列表的两端添加元素或者获得列表的一个片段。列表类型内部是使用双向链表实现的。向列表两端添加元素的复杂度为0(1)。
lpush key value [value ...]
rpush key value [value ...]
lpush命令用来向列表左边增加元素,返回值表示增加元素后列表的长度。lpush命令只会同时增加多个元素。lpush会先从列表左边加入。
rpush命令用来向列表右边增加元素。
lpop key
rpop key
lpop命令可以从列表左边弹出一个元素。执行两步操作:第一步将列表左边的元素从列表中移除,第二部是返回被移除的元素值。rpop命令可以从列表右边弹出一个元素。
以上的4个命令可以使用列表类型来模拟栈和队列的操作。如果想把列表当做栈,则搭配使用lpush和lpop或者rpush和rpop。如果相当列表,则搭配使用lpush和rpop或rpush和lpop。
llen key: 获取列表中元素的个数。当键不存在时llen会返回0。时间复杂度为0(1),使用时会直接读取现成的值。
lrange key start stop 是列表类型最常用的命令之一,能够获得列表中的某一片段。lrange命令将返回索引从start到stop之间的所有元素,redis的列表起始索引为0。
lrange命令也支持负索引,表示从右边开始计算序数,如"-1"表示最右边第一个元
素,"-2"表示最右边第二个元素。另外一些特殊情况如下。
(1)如果start的索引位置比stop的索引位置靠后,则会返回空列表。
(2)如果stop大于实际的索引范围,则会返回到列表最右边的元素。
删除列表中指定的值:lrem key count value
lrem命令会删除列表中前count个值为value的元素,返回值是实际删除的元素个数。根据count值的不同,lrem命令的执行方式会略有差异:
> 当count>0时lrem命令会从列表左边开始删除前count个值为value的元素
> 当count<0时lrem 命令会从列表右边开始删除前|count|个值为value的元素;
> 当count=0是lrem命令会删除所有值为value的元素。
获得指定索引的元素值: lindex key index,如果要将列表类型当做数组用时lindex命令是必不可少的,lindex命令用来返回指定索引的元素,索引从0开始。
设置指定索引的元素值: lset key index value是另一个通过索引操作列表的命令,会将索引为index的元素赋值为value。
只保留列表指定片段:ltrim key start end,lrtim命令可以删除指定索引范围之外的所有元素,指定列表范围的方法和lrange命令相同。
想列表中插入元素: linsert key before | after pivot value, 在列表中从左到右查找值为pivot的元素,然后根据第二个参数是before还是after来决定将value插入到该元素的前面还是后面。返回值是插入后列表的元素个数。
将元素从一个列表转到另一个列表r: poplpush source dest, 先执行rpop命令再执行lpush命令。
127.0.0.1:6379> hvals paper
1) "vlan"
2) "gp"
127.0.0.1:6379> hlen paper
(integer) 2
127.0.0.1:6379>
127.0.0.1:6379>
127.0.0.1:6379> lpush numbers 1
(integer) 1
127.0.0.1:6379> lpush numbers 2
(integer) 2
127.0.0.1:6379> lpush numbers 3
(integer) 3
127.0.0.1:6379> lpush numbers 1
(integer) 4
127.0.0.1:6379> rpush numbers 2
(integer) 5
127.0.0.1:6379> lpush number 2 3
(integer) 2
127.0.0.1:6379> lpush number 2 3
(integer) 4
127.0.0.1:6379> lpush number 2 3
(integer) 6
127.0.0.1:6379> lpush number 2 3
(integer) 8
127.0.0.1:6379> lpop number
"3"
127.0.0.1:6379> lpop number
"2"
127.0.0.1:6379> llen number
(integer) 6
127.0.0.1:6379> llen numbers
(integer) 5
127.0.0.1:6379> lindex numbers 1
"3"
127.0.0.1:6379> lset numbers 1 10
ok
127.0.0.1:6379> lindex numbers 1
"10"
127.0.0.1:6379> lrange number 2 3
1) "3"
2) "2"
127.0.0.1:6379> lrem numbers 0 3
(integer) 0
127.0.0.1:6379> lrem numbers 0 2
(integer) 2
127.0.0.1:6379> llen numbers
(integer) 3
127.0.0.1:6379> lrange numbers 0 2
1) "1"
2) "10"
3) "1"
127.0.0.1:6379> lrange numbers 0 3
1) "1"
2) "10"
3) "1"
127.0.0.1:6379> lrange numbers 1 2
1) "10"
2) "1"
127.0.0.1:6379>
集合
集合中每个元素是不同的,没有顺序,集合类型的常用操作是向集合中加入或删除元素、判断某个元素释放存在等。集合类型在redis内部是使用值为空的散列表实现的,操作的时间复杂度是0(1)。多个集合类型键之间还可以进行并集、交集和差集运算。
添加元素: sadd key member [member...], 看用来向集合中增加一个或多个元素,若键不存在则会自动创建。若已经存在则忽略该元素。返回值是成功加入的元素数量。
删除元素: srem key member [member ...], 返回删除成功的个数。
获得集合中的所有元素: smembers key,返回集合中的所有元素。
判断元素是否在集合中: sismember key member,判断一个元素是否在集合中是一个时间复杂度为0(1)的操作,无论集合中有多少个元素,sismember命令始终可以极快地返回结果。当值存在时sismember命令返回1,当值不存在或键不存在时返回0。
127.0.0.1:6379> sadd letter a b c d
(integer) 4
127.0.0.1:6379> sadd letter a b c
(integer) 0
127.0.0.1:6379> sadd letter a b
(integer) 0
127.0.0.1:6379> srem letter a b
(integer) 2
127.0.0.1:6379>
127.0.0.1:6379> srem letter a b
(integer) 0
127.0.0.1:6379> smembers letter
1) "c"
2) "d"
127.0.0.1:6379> sismember letter a
(integer) 0
127.0.0.1:6379> sismember letter b
(integer) 0
127.0.0.1:6379> sismember letter d
(integer) 1
127.0.0.1:6379>
集合间运算
sdiff key [key ...], 用来对多个结合执行差集运算,集合a与集合b的差集表示为a-b,代表所有属于a且不属于b的元素构成的集合。当存在多个集合时,按照从左到右的顺序执行差集操作。
127.0.0.1:6379> sadd seta 1 2 3 4
(integer) 4
127.0.0.1:6379> sadd setb 2 3 5
(integer) 3
127.0.0.1:6379> sdiff seta setb
1) "1"
2) "4"
127.0.0.1:6379> sdiff setb seta
1) "5"
127.0.0.1:6379> sadd setc 1 2 3 5 5
(integer) 4
127.0.0.1:6379> sdiff setb seta setc
(empty list or set)
127.0.0.1:6379> sdiff seta setb setc
1) "4"
127.0.0.1:6379>
sinter key [key ...], 对多个集合执行交集运算,代表所有属于a且属于b的元素构成的集合。
127.0.0.1:6379> sinter seta setb
1) "2"
2) "3"
127.0.0.1:6379> sinter seta setb setc
1) "2"
2) "3"
127.0.0.1:6379>
sunion key [key ...],对多个集合执行并集运算,代表所有属于a或属于b的元素构成的集合。
127.0.0.1:6379>
127.0.0.1:6379> sunion seta setb
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
127.0.0.1:6379> sunion seta setb setc
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
127.0.0.1:6379>
获取集合中的元素个数: scard key
127.0.0.1:6379> smembers seta
1) "1"
2) "2"
3) "3"
4) "4"
127.0.0.1:6379> scard seta
(integer) 4
127.0.0.1:6379>
前面可以进行元素,但是有时候需要将结果保存到一个新的集合中,特别是在需要多不集合运算的场景中非常有用,在redis中提供了这些命令:
sdiffstore destination key [key ...]
sinterstore destination key [key ...]
sunionstore destination key [key ...]
127.0.0.1:6379> sunionstore setd seta setb
(integer) 5
127.0.0.1:6379> smembers setd
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
127.0.0.1:6379>
127.0.0.1:6379> sinterstore sete seta setb
(integer) 2
127.0.0.1:6379> smembers sete
1) "2"
2) "3"
127.0.0.1:6379> sdiffstore setf seta setb
(integer) 2
127.0.0.1:6379> smembers setf
1) "1"
2) "4"
127.0.0.1:6379>
随机获取集合中的元素: srandmember key [count],其中的count是可选参数,当count为正数时,选择count个不重复的元素,若count大于集合元素的个数,则只是返回集合中的全部元素.当count为负数时,选择出来的|count|个元素可能相同,当|count|大于集合元素个数时,也会输出|count|个元素。
127.0.0.1:6379> srandmember seta
"1"
127.0.0.1:6379> srandmember seta
"2"
127.0.0.1:6379> srandmember seta
"1"
127.0.0.1:6379> srandmember seta
"3"
127.0.0.1:6379> srandmember seta
"3"
127.0.0.1:6379> srandmember seta
"2"
127.0.0.1:6379> srandmember seta 10 <<---取出实际的元素个数
1) "1"
2) "2"
3) "3"
4) "4"
127.0.0.1:6379> srandmember seta -10 <<---取出10个元素,但这些元素可能相同
1) "2"
2) "4"
3) "1"
4) "2"
5) "4"
6) "3"
7) "1"
8) "4"
9) "3"
10) "2"
127.0.0.1:6379>
从集合中弹出一个元素:spop key, 会从集合中随机选择一个元素弹出。这是因为集合是无序导致的。
有序集合
在集合类型的基础上有序集合类型为集合中的每个元素都关联一个分数,使得可以插入、删除和判断元素是否存在等集合类型支持的操作,还能够获得分数最好或最低前n个元素,获得指定分数范围内的元素等与分数有关的操作。虽然每个元素是不同的,但是分数却可以相同。
有序集合和列表在某些方面相似:
都是有序的,都可以获得某一范围的元素,但两者的应用场景不同。列表是通过链表实现的,获取两端的数据速度极快。而有序集合使用散列表和跳跃表实现的,中间部分的数据速度也很快。列表不能简单的调整某个元素的位置,但有序集合可以。有序集合比列表更费内存。
增加元素: zadd key score member [score member ...], 用来向有序集合中加入一个元素和该元素的份数没如果该元素已经存在则会用新的份数替代原有的份数,zadd的返回值是新加入到集合中的元素个数,不包括之前已经存在的元素。因此zadd也可以用于更改元素的分数。分数可以是整数,还支持双精度浮点数。其中 inf和-inf分别表示正无穷和负无穷。
127.0.0.1:6379> zadd scoreboard 89 tom 67 peter 100 david
(integer) 3
127.0.0.1:6379> zadd scoreboard 76 peter
(integer) 0
127.0.0.1:6379>
127.0.0.1:6379> zadd testboard 17e 307 a
(integer) 1
127.0.0.1:6379> zadd testboard 1.5 b
(integer) 1
127.0.0.1:6379> zadd testboard inf c
(integer) 1
127.0.0.1:6379> zadd testboard -inf d
(integer) 1
127.0.0.1:6379>
获取元素的分数:zscore key member
获得排名在某个范围的元素列表:
zrange key start stop [withscores], 会按照元素分数从小到大的顺序返回索引从start到stop之间的所有元素,包含两端的元素。索引都是从0开始,负数代表从后面向前查找。如果需要获得元素的分数可以在尾部加上withscores。
127.0.0.1:6379> zrange scoreboard 0 2
1) "peter"
2) "tom"
3) "david"
127.0.0.1:6379> zrange scoreboard 1 -1
1) "tom"
2) "david"
127.0.0.1:6379> zrange scoreboard 1 -1
1) "tom"
2) "david"
127.0.0.1:6379> zrange scoreboard 0 -1 withscores
1) "peter"
2) "76"
3) "tom"
4) "89"
5) "david"
6) "100"
127.0.0.1:6379>
zrevrange key start stop [withscores],与zrange唯一不同在于zrevrange命令是按照元素分数从大到小的顺序给出结果的。
获得指定分数范围的元素:zrangebyscore key min max [withscores] [limit offset count],该命令按照元素分数从小到大的顺序返回分数在min和max之间的元素。如果希望分数范围不包含端点值,可以在分数前加"("符号。命令中limit offset count是在获得的元素列表的基础上向后偏移offset个元素,并只获取前count个元素。
127.0.0.1:6379>
127.0.0.1:6379> zadd scoreboard 56 jerry 92 wendy 67 yvonne
(integer) 3
127.0.0.1:6379> zrange scoreboard 0 -1 withscores
1) "jerry"
2) "56"
3) "yvonne"
4) "67"
5) "peter"
6) "76"
7) "tom"
8) "89"
9) "wendy"
10) "92"
11) "david"
12) "100"
127.0.0.1:6379> zrangebyscore scoreboard 60 inf withscores limit 1 3
1) "peter"
2) "76"
3) "tom"
4) "89"
5) "wendy"
6) "92"
127.0.0.1:6379>
zrevrangebyscore命令是按照元素分数从大往小的顺序给出结果的。而她的min和max参数的顺序和zrangebyscore命令是相反的。
增加某个元素的分数: zincrby key increment member,可以增加一个元素的分数,返回值是更改后的分数。
获得集合中元素的数量: zcard key
获得指定分数范围内的元素个数: zcount key min max
删除一个或多个元素: zrem key member [member ...]
按照排名范围删除元素: zremrangebyrank key start stop
获得元素的排名: zrank /zrevrank key member,zrank命令按照元素分数从小到大的顺序获得指定的元素的排名(从0开始,即分数最小的元素排名为0),zrevrank 命令则相反。
计算有序集合的并集:zinterstore destination numkeys key [key …] [weights weight [weight …]] [agregate sum|min|max]
zinterstore命令用来计算多个有序集合的交集并将结果存储在destination键中(同样以有序集合类型存储),返回值为destination键中的元素个数。destination键中元素的分数是由aggregate参数决定的。当aggregate是sum时(也就是默认值),destination键中元素的分数是每个参与计算的集合中该元素分数的和。当aggregate是min时,destination键中元素的分数是每个参与计算的集合中该元素分数的最小值。
127.0.0.1:6379> zadd set1 1 a 2 b
(integer) 2
127.0.0.1:6379> zadd set2 10 a 20 b
(integer) 2
127.0.0.1:6379> zinterstore result 2 set1 set2
127.0.0.1:6379> zrange result 0 -1 withscores
1) "a"
2) "11"
3) "b"
4) "22"
127.0.0.1:6379> zinterstore result 2 set1 set2 aggregate min
(integer) 2
127.0.0.1:6379> zrange result 0 -1 withscores
1) "a"
2) "1"
3) "b"
4) "2"
127.0.0.1:6379> zinterstore result 2 set1 set2 aggregate max
(integer) 2
127.0.0.1:6379> zrange result 0 -1 withscores
1) "a"
2) "10"
3) "b"
4) "20"
127.0.0.1:6379>