Redis提供了多种数据类型,可以用作缓存、消息队列、事件处理,集合运算、分布式协调等。
Strings(字符串)
string类型是redis最简单也最常用的数据结构。string我觉的这里不应该简单理解为字符串,官方说string类型被存储在一个字节数组里(sequences of bytes)。可以是文本、序列化的对象、二进制数据等。
常用方法:
redis使用set和get命令分别对key进行设置和获取。
127.0.0.1:6379> set name hello
OK
127.0.0.1:6379> get name
"hello"
127.0.0.1:6379> set name redis
OK
127.0.0.1:6379> get name
"redis"
每一个key在redis中都是唯一的,如果多次set一个key则后面设置的value会覆盖前面的。
还可以使用mset和mget进行多个key同时设置和获取
127.0.0.1:6379> mset name redis age 20
OK
127.0.0.1:6379> mget name age
1) "redis"
2) "20"
mset 命令后跟 key value [key value ...]
mget key [key ...]。mget返回一个对应的value数组。
值的删除使用del命令,设置key的有效期使用expire命令
127.0.0.1:6379> del age
(integer) 1
#删除key后再获取返回nil
127.0.0.1:6379> get age
(nil)
#设置name的过期时间为3秒
127.0.0.1:6379> expire name 3
(integer) 1
127.0.0.1:6379> get name
"redis"
#3秒后第二次获取返回nil,已过期被自动删除
127.0.0.1:6379> get name
(nil)
127.0.0.1:6379> EXISTS name
(integer) 0
expire key 设置的时间单位是秒。
EXISTS命令可以判断某个key是否存在。
setnx(set not exists) 设置一个不存在的key
setnx是一个很重要的命令,这个命令设置一个key,如果这个key不存在则返回成功,如果该key已存在则返回失败。这个命令可以用来实现分布式锁。
127.0.0.1:6379> setnx name redis
(integer) 1
127.0.0.1:6379> setnx name redis
(integer) 0
计数
string类型存储的value如果是数字型,还可以用作计数器使用
127.0.0.1:6379> set age 18
OK
127.0.0.1:6379> incr age
(integer) 19
127.0.0.1:6379> incrby age 5
(integer) 24
127.0.0.1:6379> incrby age -3
(integer) 21
127.0.0.1:6379> DECR age
(integer) 20
127.0.0.1:6379> decrby age 2
(integer) 18
incr将value值+1,decr将value值-1.incrby指定具体的数字变化量。这些计数操作都是原子操作。分布式系统中可以用来生成唯一ID。
最后需要提一点redis支持单个string的value最大大小是512M。这个已经足够使用了。
List(列表)
redis的list是按插入顺序排序的字符串元素集合,可以在头部或尾部添加元素,支持在列表两端推入(push)或弹出(pop)元素。可以用来实现栈和队列。list相当于一个链表,其插入和删除较快,但是查找某个元素比较慢。
常用方法
LPUSH : 将元素插入到表头
RPUSH: 将元素插入到表尾
LPOP: 移除并返回表头元素
RPOP: 移除并返回表尾元素
LLEN key: 返回表元素个数
LRANGE key start stop 范围索引区间范围元素。这里的start和stop都是下标索引
127.0.0.1:6379> lpush lang java python
(integer) 2
127.0.0.1:6379> llen lang
(integer) 2
127.0.0.1:6379> rpush lang c
(integer) 3
127.0.0.1:6379> lrange lang 0 -1
1) "python"
2) "java"
3) "c"
127.0.0.1:6379> lrange lang 0 1
1) "python"
2) "java"
127.0.0.1:6379> lpop lang
"python"
127.0.0.1:6379> rpop lang
"c"
上面看到要想获取list所有元素可以使用 lrange key 0 -1。这里的-1代表start开始后所有元素。lrange 只获取列表元素,不会进行删除操作。如果获取范围的同时删除不在范围内的可以使用ltrim 来截取列表。
127.0.0.1:6379> lpush lang java python php c go
(integer) 5
127.0.0.1:6379> ltrim lang 0 2
OK
127.0.0.1:6379> llen lang
(integer) 3
127.0.0.1:6379> lrange lang 0 -1
1) "go"
2) "c"
3) "php"
list是个链表,当然也可以按下标进行获取指定某个元素,可以使用lindex命令,不过一般情况下不用,时间复杂度比较高。
127.0.0.1:6379> lindex lang 2
阻塞
blpop和brpop 如果list种当前没有元素,阻塞等待获取list种元素,可以设置timeout时间。
还有一点需要主要,如果list对应的key经过pop后没有任何元素,则key会被自动删除。
127.0.0.1:6379> lpop lang
"java"
127.0.0.1:6379> lpop lang
(nil)
127.0.0.1:6379> exists lang
(integer) 0
Hash(哈希表)
哈希表(Hash)是一种存储键值对的数据结构,类似于其他编程语言中的字典或者关联数组。每个哈希表可以存储多个键值对,每个键都是唯一的,像java的HashMap。
常用命令
HSET key field value : 设置哈希表 key
中的字段 field
的值为 value
。
HGET key field : 获取哈希表 key
中指定字段 field
的值。
HGETALL key:返回哈希表总所有的键值。
HDEL key field [field ...] :删除哈希表中指定的field键值。
HMSET key field value [field value ...] :一次设置多个键值
HMGET key field [field ...] :一次获取多个键值
使用例子:
127.0.0.1:6379> hset user:1 name redis
(integer) 1
127.0.0.1:6379> hget user:1 name
"redis"
127.0.0.1:6379> hset user:1 age 18
(integer) 1
127.0.0.1:6379> hset user:1 city jinan
(integer) 1
127.0.0.1:6379> hgetall user:1
1) "name"
2) "redis"
3) "age"
4) "18"
5) "city"
6) "jinan"
127.0.0.1:6379> hdel user:1 age city
(integer) 2
127.0.0.1:6379> hgetall user:1
1) "name"
2) "redis"
127.0.0.1:6379> hmset user:1 age 20 city yantai
OK
127.0.0.1:6379> hlen user:1
(integer) 3
127.0.0.1:6379> hmget user:1 name age
1) "redis"
2) "20"
如果一个field的value是一个整数,也可以使用 HINCRBY key field increment进行值的累增。increment是增量。如果field不存在,默认从0作为基数开始计算。
127.0.0.1:6379> hget user:1 amt
(nil)
127.0.0.1:6379> HINCRBY user:1 amt 5
(integer) 5
127.0.0.1:6379> hget user:1 amt
"5"
对于filed是否存在同样有HEXISTS 命令来判断,hsetnx命令当field不存在时设置field。
127.0.0.1:6379> HEXISTS user:1 name
(integer) 1
127.0.0.1:6379> hsetnx user:1 name test
(integer) 0
127.0.0.1:6379> hsetnx user:1 name1 test
(integer) 1
hash适合存储对象或者实体,每个字段对应对象的一个属性。哈希表的读取、更新和删除操作非常高效,时间复杂度都是 O(1),可以动态添加或删除字段,每个哈希表可以包含最多 2^32 - 1 个字段。
Set(集合)
集合(Set)是一种无序且唯一的数据结构,可以包含多个字符串元素,但是每个元素在集合中必须是唯一的,即集合中不允许重复的成员。
常用方法
SADD key member [member ...] : 向集合 key
中添加一个或多个成员。
SMEMBERS key : 获取集合 key
中的所有成员。
SISMEMBER key member : 判断 member
是否是集合 key
的成员。
SREM key member [member ...] : 从集合 key
中移除一个或多个成员。
SCARD key:获取集合中元素个数,card是cardinality 简写。
SPOP key [count]:从集合中随机取出指定数量的元素,被取出的元素会从集合中删除。
SRANDMEMBER key [count]:从集合中随机取出指定数量的元素,取出元素不会从集合中移除。
使用例子:
127.0.0.1:6379> sadd lang c c++ java
(integer) 3
127.0.0.1:6379> smembers lang
1) "c++"
2) "java"
3) "c"
127.0.0.1:6379> SISMEMBER lang java
(integer) 1
127.0.0.1:6379> sismember lang python
(integer) 0
127.0.0.1:6379> scard lang
(integer) 3
127.0.0.1:6379> srem lang c++
(integer) 1
127.0.0.1:6379> sadd python php go
(integer) 2
127.0.0.1:6379> srandmember lang 2
1) "c"
2) "java"
127.0.0.1:6379> sismember lang java
(integer) 1
127.0.0.1:6379> spop lang 2
1) "c"
2) "java"
127.0.0.1:6379> sismember lang java
(integer) 0
集合除了单个集合操作外,还可以进行集合与集合之间操作。这个和数学的集合操作一样,可以求交集,并集和差集。方法如下:
SUNION key [key ...]:并集运算
SINTER key [key ...]:交集运算 (inter是intersection缩写, 交叉,交集)
SDIFF key [key ...]:差集运算
Sorted Set(有序集合)
有序集合和set集合一样每个集合成员是唯一的,不同之处是,有序集合中每成员还拥有一个score值,集合成员可以根据score进行排序。score值是可以重复的,如果两个成员的score值相同,那么两个成员顺序按成员名称字符串顺序排序。
常用方法
成员操作
ZADD key score member [score member ...] : 向有序集合 key
中添加一个或多个成员,同时指定它们的分数。
ZREM key member [member ...]:删除成员
ZCARD key:集合中成员数
ZRANK key member [WITHSCORE]:返回成员的排序值
127.0.0.1:6379> zadd myzset 1 one 2 two
(integer) 2
127.0.0.1:6379> zadd myzset 3 three
(integer) 1
127.0.0.1:6379> zcard myzset
(integer) 3
127.0.0.1:6379> zrem myzset three
(integer) 1
127.0.0.1:6379> zcard myzset
(integer) 2
127.0.0.1:6379> zadd myzset 4 four 5 five 6 six
(integer) 3
127.0.0.1:6379> zrank myzset five
(integer) 3
127.0.0.1:6379>
zrank 返回的是按score从小到大排序,成员的位置,从0开始。如果想按从大到小排序可以使用ZREVRANK命令。
score操作:
ZRANGE key start stop [WITHSCORES] : 按照从小到大的顺序,返回有序集合 key
中指定范围内的成员。WITHSCORES可选参数用来指定是否返回分数。start和stop是排序索引顺序。
ZREVRANGE key start stop [WITHSCORES] : 按照从大到小的顺序,返回有序集合 key
中指定范围内的成员。
ZSCORE key member : 返回有序集合 key
中成员 member
的分数。
ZINCRBY key increment member : 将有序集合 key
中成员 member
的分数增加 increment
。increment 用来指定增加的分数。
127.0.0.1:6379> zrange myzset 0 2
1) "one"
2) "two"
3) "four"
127.0.0.1:6379> ZREVRANGE myzset 0 2 withscores
1) "six"
2) "6"
3) "five"
4) "5"
5) "four"
6) "4"
127.0.0.1:6379> zscore myzset four
"4"
127.0.0.1:6379> ZINCRBY myzset 10 four
"14"
127.0.0.1:6379> zscore myzset four
"14"
zrange这里操作和List一样,如果stop设置为-1表示取从start位置到最后一个成员。
有序集合除了可以按score排序后按数量进行取成员,还可以根据score值来取成员数据。使用zrangebyscore命令
127.0.0.1:6379> zrangebyscore myzset 1 5
1) "one"
2) "two"
3) "five"
从6.2.0版本开始,zrangebyscore命令被标为过时方法,被合并到了zrange命令里,使用BYSCORE
参数。
ZRANGEBYSCORE完整语法如下:
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]
这里看到可以使用limit来分页获取数据。score的最小和最大值可以使用 -inf 和 +inf来表示。inf是infinite无穷的的意思。
默认情况下,ZRANGEBYSCORE按指定的score范围(min,max)赛选出的成员是包含score边界的。也即score等于边界min和max的成员。查询的score范围是闭区间。如果想不包含边界,可以使用(符号
如下
127.0.0.1:6379> zrangebyscore myzset (1 5
1) "two"
2) "five"
上面筛选的区间范围是 1 < score <=5。
如果只想根据就score范围统计数量,不获取成员可以使用 ZCOUNT key min max。 min和max指定score的边界。
以上5种是redis常用的数据类型,除了这些还有bitmap,geo,hyperloglog等等都是在特定场景下非常有用。后面学到再整理。