Hexo

点滴积累 豁达处之

0%

02 redis数据类型及存储结构

Redis支持五中数据类型:String(字符串),Hash(哈希),List(列表),Set(集合)及zset(sortedset:有序集合)。

Redis内部使用一个redisObject对象来表示所有的key和value。redisObject主要的信息包括数据类型(type)、编码方式(encoding)、数据指针(ptr)、虚拟内存(vm)等。type代表一个value对象具体是何种数据类型,encoding是不同数据类型在redis内部式。

redis数据结构

1 字符串

String是Redis最基本的数据类型,结构为一个key对应一个value。

String类型是二进制安全的,意味着可以包含任何数据,比如jpg图片或者序列化的对象。

String类型的最大能存储512M。

1.1 常用命令

set get

set——设置key对应的值为String类型的value

get——获取key对应的值

比如我们想设置往Redis中存放一个用户名,用String类型存储:

1
2
127.0.0.1:6379> SET name chenqingsong
OK

“OK”是Redis返回的响应,代表设置成功。

取出这个name的值:

1
2
127.0.0.1:6379> GET name
"chenqingsong"

想修改name的值为“clf”,重新SET一遍,覆盖掉原来的值:

1
2
3
4
127.0.0.1:6379> SET name clf
OK
127.0.0.1:6379> GET name
"clf"
mget

mget——批量获取多个key的值,如果可以不存在则返回nil

1
2
3
4
5
6
7
8
192.168.2.129:6379> mget name name1
1) "zhangsan"
2) "wangwu"
192.168.2.129:6379> mget name name1 name2
1) "zhangsan"
2) "wangwu"
3) (nil)
192.168.2.129:6379>
incr && incrby

incr && incrby——incr对key对应的值进行加加操作,并返回新的值;incrby加指定值

1
2
3
4
5
6
7
8
9
10
11
12
192.168.2.129:6379> get age
"20"
192.168.2.129:6379> incr age
(integer) 21
192.168.2.129:6379> set age1 "20"
OK
192.168.2.129:6379> get age1
"20"
192.168.2.129:6379> incr age1
(integer) 21
192.168.2.129:6379> incrby age 3
(integer) 24

从上面的结果可以看出,我们对int型的age和string型的age1都能进行incr操作时,

实际上type=string代表value存储的是一个普通字符串,那么对应的encoding可以是raw或者是int,如果是int则代表实际redis内部是按数值型类存储和表示这个字符串的,当然前提是这个字符串本身可以用数值表示,比如”20”这样的字符串,当遇到incr、decr等操作时会转成数值型进行计算,此时redisObject的encoding字段为int。如果你试图对name进行incr操作则报错。

1
2
192.168.2.129:6379> incr name
(error) ERR value is not an integer or out of range
decr && decrby

decr && decrby——decr对key对应的值进行减减操作,并返回新的值;decrby减指定值

1
2
3
4
127.0.0.1:6379> DEL name
(integer) 1 --该数字代表影响的记录总数
127.0.0.1:6379> GET name
(nil) --nil代表为空,不存在该对象

1.2 命令汇总

命令格式 说明
SET key value 设置指定 key 的值
GET key 获取指定 key 的值
SETNX key value Set if Not Exist)只有在 key 不存在时设置 key 的值
SETRANGE key offset value 用 value 参数覆写给定 key 所储存的字符串值,从偏移量 offset 开始
GETRANGE key start end 返回 key 中字符串值的子字符
GETSET key value 将给定 key 的值设为 value ,并返回 key 的旧值
MSET key value [key value …] Multi Set)同时设置一个或多个 key-value 对
MGET key1 [key2..] 获取所有(一个或多个)给定 key 的值
APPEND key value 如果 key 已经存在并且是一个字符串, APPEND 命令将 value 追加到 key 原来的值的末尾
SETEX key seconds value Set Expire)将值 value 关联到 key ,并将 key 的过期时间设为 seconds (以秒为单位)
PSETEX key milliseconds value Precise Set Expire)这个命令和 SETEX 命令相似,但它以毫秒为单位设置 key 的生存时间,而不是像 SETEX 命令那样,以秒为单位
STRLEN key 返回 key 所储存的字符串值的长度
INCR key 将 key 中储存的数字值增一,前提是value是一个数字
INCRBY key increment 将 key 所储存的值加上给定的增量值,前提是value是一个数字
INCRBYFLOAT key increment 将 key 所储存的值加上给定的浮点增量值,前提是value是一个数字
DECR key 将 key 中储存的数字值减一,前提是value是一个数字
DECRBY key decrement key 所储存的值减去给定的减量值,前提是value是一个数字

2 哈希

Redis的哈希是field和value之间的映射,即键值对的集合,所以特别适合用于存储对象。

Redis 中每个 hash 最多可以存储 232 - 1 键值对(40多亿)。

2.1 常用命令

hset hget

hset——设置key对应的HashMap中的field的value

hget——获取key对应的HashMap中的field的value

1
2
3
4
5
6
7
8
9
192.168.2.129:6379> hset myhash name zhangsan
(integer) 1
192.168.2.129:6379> hset myhash age 20
(integer) 1
192.168.2.129:6379> hget myhash name
"zhangsan"
192.168.2.129:6379> hget myhash age
"20"
192.168.2.129:6379>
hgetall

hgetall——获取key对应的HashMap中的所有field的value

1
2
3
4
5
6
192.168.2.129:6379> hgetall myhash
1) "name"
2) "zhangsan"
3) "age"
4) "20"
192.168.2.129:6379>

2.2 命令汇总

命令格式 说明
HMSET key field1 value1 [field2 value2… ] Hash Multi Set)同时将多个 field-value 对设置到哈希表 key 中
HMGET key field1 [field2…] 获取所有给定字段的值
HSET key field value 将哈希表 key 中的字段 field 的值设为 value
HGET key field 获取存储在哈希表中指定字段的值
HGETALL key 获取在哈希表中指定 key 的所有字段和值
HDEL key field2 [field2] 删除一个或多个哈希表字段
HSETNX key field value 只有在字段 field 不存在时,设置哈希表字段的值
HKEYS key 获取所有哈希表中的字段
HVALS key 获取哈希表中所有值
HEXISTS key field 查看哈希表 key 中,指定的字段是否存在
HLEN key 获取哈希表中字段的数量
HINCRBY key field increment 为哈希表 key 中的指定字段的整数值加上增量
HINCRBYFLOAT key field increment 为哈希表 key 中的指定字段的浮点数值加上增量

3 列表

Redis的List类型其实就是每一个元素都是String类型的双向链表。我们可以从链表的头部和尾部添加或者删除元素。这样的List既可以作为栈,也可以作为队列使用。

redis列表

3.1 常用命令

lpush lrange lpop

lpush——在key对应的list的头部添加一个元素。

lrange——获取key对应的list的指定下标范围的元素,-1表示获取所有元素。

lpop——从key对应的list的尾部删除一个元素,并返回该元素。

1
2
3
4
5
6
7
8
9
10
11
12
192.168.2.129:6379> lpush newlist news1 news2 news3
(integer) 3
192.168.2.129:6379> lrange newlist 0 -1
1) "news3"
2) "news2"
3) "news1"
192.168.2.129:6379> lpop newlist
"news3"
192.168.2.129:6379> lrange newlist 0 -1
1) "news2"
2) "news1"
192.168.2.129:6379>

redis lpushandlpop

rpush rpop

rpush——在key对应的list的尾部添加一个元素。

rpop——从key对应的list的尾部删除一个元素,并返回该元素。

1
2
3
4
5
6
7
8
9
192.168.2.129:6379> rpush newlist2 news1 news2 news3
(integer) 3
192.168.2.129:6379> lrange newlist2 0 -1
1) "news1"
2) "news2"
3) "news3"
192.168.2.129:6379> rpop newlist2
"news3"
192.168.2.129:6379>

Redis列表虽然名为列表,其实从特性上来讲更像是栈,以最近放进去的元素为头,以最早放进去的元素为尾,所以,Redis列表的下标呈倒序排列。上例中依次放进去的五个元素:Asia、Africa、America、Oceania、Antarctica,下标分别为4、3、2、1、0。这与Java中List的概念完全不一样,需要特别注意。

与栈类似,当执行POP操作时,Redis列表弹出的是最新放进去的元素,类似于栈顶元素。

Redis列表还支持一种阻塞式操作,比如BLPOP(Blockd List Pop之缩写),移出并获取列表的第一个元素,如果列表没有元素(或列表不存在)会阻塞列表直到等待超时或发现可弹出元素为止。

例如,我们对一个不存在的列表“myList”执行BLPOP命令:

BLPOPmyList 20 – 弹出myList列表的第一个元素,如果没有,阻塞20秒

该客户端会进入阻塞状态,如果20秒之内该列表存入了元素,则弹出:

1
2
3
4
27.0.0.1:6379> BLPOP myList 20 --若无元素则进入阻塞状态,限时20
1) "myList"
2) "hello"
(6.20s)

如果超时后仍然没有等到元素,则结束阻塞,返回nil:

1
2
3
127.0.0.1:6379> BLPOP myList 20
(nil)
(20.07s)

3.2 命令汇总

命令格式 说明
LPUSH key value1 [value2…] 将一个或多个值插入到列表头部
LPOP key 移出并获取列表的第一个元素
LPUSHX key value List Push if exist)将一个或多个值插入到已存在的列表头部
LINDEX key index 通过索引获取列表中的元素
LRANGE key start stop 获取列表指定范围内的元素
LSET key index value 通过索引设置列表元素的值
LTRIM key start stop 只保留指定区间内的元素,不在指定区间之内的元素都将被删除
RPOP key Rear Pop)移除并获取列表最后一个元素
RPUSH key value1 [value2…] 将一个或多个值插入到列表尾部
RPUSHX key value 将一个或多个值插入到已存在的列表尾部
LREM key count value 从列表中删除字段值为value的元素,删除count的绝对值个value后结束,count > 0 从表头删除;count < 0 从表尾删除;count=0 全部删除
RPOPLPUSH source destination 移除列表的最后一个元素,并将该元素添加到另一个列表并返回
BLPOP key1 [key2… ] timeout 移出并获取列表的第一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止,如果timeout为0则一直等待下去
BRPOP key1 [key2… ] timeout 移出并获取列表的最后一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止,如果timeout为0则一直等待下去
LINSERT key BEFORE | AFTERpivot value 在key 列表中寻找pivot,并在pivot值之前|之后插入value
LLEN key 获取列表长度

4 集合

Redis集合是String类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据。

Redis集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。

集合中最大的成员数为 232- 1 ,即每个集合最多可存储40多亿个成员。

集合的一大特点就是不能有重复元素,如果插入重复元素,Redis会忽略该操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
127.0.0.1:6379> SADD direction east west south north
(integer) 4
127.0.0.1:6379> SMEMBERS direction
1) "west"
2) "east"
3) "north"
4) "south"

127.0.0.1:6379> SADD direction east
(integer) 0  --east元素已经存在,该操作无效
127.0.0.1:6379> SMEMBERS direction
1) "west"
2) "east"
3) "north"
4) "south"

Redis集合还有两大特点,一是支持随机获取元素,二是支持集合间的取差集、交集与并集操作。

4.1 常用命令

sadd smembers spop

sadd——在key对应的set中添加一个元素。

smembers——获取key对应的set的所有元素。

spop——随机返回并删除key对应的set中的一个元素。

1
2
3
4
5
6
7
8
9
192.168.2.129:6379> sadd myset news1 news2 news3
(integer) 3
192.168.2.129:6379> smembers myset
1) "news3"
2) "news2"
3) "news1"
192.168.2.129:6379> spop myset
"news3"
192.168.2.129:6379>
sdiff

sdiff——求给定key对应的set与第一个key对应的set的差集

1
2
3
4
5
6
7
8
9
10
11
12
13
14
192.168.2.129:6379> smembers myset
1) "news3"
2) "news2"
3) "news1"
192.168.2.129:6379> sadd myset2 news3 news4 news5
(integer) 3
192.168.2.129:6379> smembers myset2
1) "news4"
2) "news3"
3) "news5"
192.168.2.129:6379> sdiff myset myset2
1) "news1"
2) "news2"
192.168.2.129:6379>
suion

suion——求给定key对应的set并集

1
2
3
4
5
6
7
192.168.2.129:6379> sunion myset myset2
1) "news3"
2) "news1"
3) "news2"
4) "news4"
5) "news5"
192.168.2.129:6379>
sinter

sinter——求给定key对应的set交集

1
2
3
192.168.2.129:6379> sinter myset myset2
1) "news3"
192.168.2.129:6379>

4.2 命令汇总

命令格式 说明
SADD key member1 [member2…] 向集合添加一个或多个成员
SREM key member1 [member2…] 移除集合中一个或多个成员
SPOP key 移除并返回集合中的一个随机元素
SMEMBERS key 返回集合中的所有成员
SRANDMEMBER key [count] 返回集合中count个随机元素,如count为空,则只返回一个
SCARD key Set Cardinality)返回集合中的元素总数
SISMEMBER key member 判membe元素是否是集key 的成员
SMOVE source destination member 将member元素从source集合移动到destination集合
SDIFF key1 [key2…] 返回给定所有集合的差集,即以key1为基准,返回key1有且[key2…]没有的元素
SDIFFSTORE destination key1 [key2…] 返回给定所有集合的差集并存储在destination中
SINTER key1 [key2…] 返回给定所有集合的交集
SINTERSTORE destination key1 [key2…] 返回给定所有集合的交集并存储在destination中
SUNION key1 [key2…] 返回所有给定集合的并集
SUNIONSTORE destination key1 [key2…] 所有给定集合的并集存储在destination集合中

5 有序列表 SortSet

SortSet顾名思义,是一个排好序的Set,它在Set的基础上增加了一个顺序属性score,这个属性在添加修改元素时可以指定,每次指定后,SortSet会自动重新按新的值排序。

需要注意的是,Redis有序集合是默认升序的,score越低排名越靠前,即score越低的元素下标越小。

sorted set的内部使用HashMap和跳跃表(SkipList)来保证数据的存储和有序,HashMap里放的是成员到score的映射,而跳跃表里存放的是所有的成员,排序依据是HashMap里存的score。

5.1 常用命令

zadd zrange

zadd ——在key对应的zset中添加一个元素

zrange——获取key对应的zset中指定范围的元素,-1表示获取所有元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
192.168.2.129:6379> zadd myzset 1 "one" 2 "two" 3 "three"
(integer) 3
192.168.2.129:6379> zrange myzset 0 -1
1) "one"
2) "two"
3) "three"
192.168.2.129:6379> zrange myzset 0 -1 withscores
1) "one"
2) "1"
3) "two"
4) "2"
5) "three"
6) "3"
192.168.2.129:6379>
zrem

zrem——删除key对应的zset中的一个元素

1
2
3
4
5
6
7
8
192.168.2.129:6379> zrem myzset one
(integer) 1
192.168.2.129:6379> zrange myzset 0 -1 withscores
1) "two"
2) "2"
3) "three"
4) "3"
192.168.2.129:6379>

5.2 命令汇总

命令格式 说明
ZADD key score1 member1 [score2 member2 …] 添加一个或多个成员到有序集合,或者如果它已经存在更新其分数
ZRANGE key start stop [WITHSCORES] 把集合排序后,返回名次在[start,stop]之间的元素。 WITHSCORES是把score也打印出来
ZREVRANGE key start stop [WITHSCORES] 倒序排列(分数越大排名越靠前),返回名次在[start,stop]之间的元素
ZRANGEBYSCORE key min max [WITHSCORES][LIMIT offset n] 集合(升序)排序后取score在[min, max]内的元素,并跳过offset个,取出n个
ZREM key member [member …] 从有序集合中删除一个或多个成员
ZRANK key member 确定member在集合中的升序名次
ZREVRANK key member 确定member在集合中的降序名次
ZSCORE key member 获取member的分数
ZCARD key 获取有序集合中成员的数量
ZCOUNT key min max 计算分数在min与max之间的元素总数
ZINCRBY key increment member 给member的分数增加increment
ZREMRANGEBYRANK key start stop 移除名次在start与stop之间的元素
ZREMRANGEBYSCORE key min max 移除分数在min与max之间的元素