前言
上一篇简单的介绍了Redis和怎么在CentOS中去安装Redis服务。
Redis是什么呢?
- Redis 缓存是基于 key - value 存储的内存缓存
- 提供list、set、zset、hash等数据结构类型
- 支持数据的备份, master-slave模式的数据备份
- 支持数据的持久化,重启的时候可以再次加载使用
Redis和memcached的区别?
- 数据存储,memcached 需要对数据增强进行不断扩容。
- memcached 跨机房 cache 同步问题
- memcached 数据命中率低,大量访问无法穿透DB,mysql 无法支持。
今天主要给大家介绍的是Redis的数据类型
一、Redis数据类型
Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)。
Redis官方操作文档:http://redisdoc.com/
在redis 自带的客户端中输入命令时,可以使用tab自动补齐。
数据结构和内部编码图示:
1.1 String(字符串)
1)概述
String 是 redis 最基本的类型,一个key对应一个value。
2)结构
可以是字符串(json);数字,以及二进制
key | value |
girl | beautiful |
counter | 1 |
bits | 101111101110 |
3)使用场景
- 缓存
- 计数器
- 分布式锁
4)API
命令 | 说明 | 时间复杂度 |
set key value | 设置key和value | O(1) |
mset key value … keyN valueN | 批量设置key-value | O(1) |
get key | 获得key对应的value | O(1) |
mget key … keyN | 批量获取key,原子操作 | O(N) |
getset key newvalue | set key newvalue并返回旧的value | O(1) |
del key | 删除key与value | O(1) |
incr key | key自增1, 如果key不存在,自增后get(key) = 1 | 0(1) |
incrby key k | key自增k, 如果key不存在,自增后get(key) = k | O(1) |
decr key | key自减1, 如果key不存在,自增后get(key) = -1 | O(1) |
decrby key k | key自减k, 如果key不存在,自增后get(key) = -k | 0(1) |
append key value | 将value追加到旧的value | O(1) |
strlen key | 返回字符串的长度(注意中文,utf8下一个中文占用3个字符) | O(1) |
5)性能对比
- n次get操作
- 1次mget操作
1.2 hash(哈希)
1)概述
Redis hash 是一个键值(key=>value)对集合
Redis hash是一个string类型的field和value的映射表,hash特别适合用于存储对象
2)哈希值结构
注意:field不能相同,value可以相同
3)API
命令 | 说明 | 时间复杂度 |
hset key field value | 设置has key 对应的field的value | O(1) |
hmset key field1 value1 field2 value2…fieldN value | 批量设置hash key的一批field value | O(N) |
hget key field | 获取hash key对应field的value | O(1) |
hmget key field1 field2…fieldN | 批量获取hash key的一批field对应的值 | |
hgetall key | 返回hash key对应所有的field和value | O(N) |
hvals key | 返回hash key对应所有的field的value | O(N) |
hkeys key | 返回hash key对应所有的field | O(N) |
hexists key field | 判断hash key 是否有field | O(1) |
hlen key | 获取hash key field的数量 | O(1) |
hincrby key field intCounter | hash key对应的field的value自增intCounter | O(1) |
注意:慎用hgetall(牢记单线程)
4)使用实例
127.0.0.1:6379> hset userone name zhangsan
(integer) 1
127.0.0.1:6379> hset userone age 12
(integer) 1
127.0.0.1:6379> hget userone name
"zhangsan"
127.0.0.1:6379> hgetall userone
1) "name"
2) "zhangsan"
3) "age"
4) "12"
127.0.0.1:6379> HEXISTS userone name
(integer) 1
127.0.0.1:6379> hlen userone
(integer) 2
127.0.0.1:6379> hmset usertwo name lisi age 24 password 110
OK
127.0.0.1:6379> hmget usertwo name age password
1) "lisi"
2) "24"
3) "110"
127.0.0.1:6379> hgetall usertwo
1) "name"
2) "lisi"
3) "age"
4) "24"
5) "password"
6) "110"
127.0.0.1:6379> hvals usertwo
1) "lisi"
2) "24"
3) "110"
127.0.0.1:6379> hkeys usertwo
1) "name"
2) "age"
3) "password"
127.0.0.1:6379> hincrby usertwo age 4
(integer) 28
127.0.0.1:6379> hgetall usertwo
1) "name"
2) "lisi"
3) "age"
4) "28"
5) "password"
6) "110"
1.3 list(列表)
1)概述
Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。
2)列表结构
3)特点
- 有序
- 可重复
- 左右两边插入弹出
4)API
5)示例一
127.0.0.1:6379> rpush listone i love you
(integer) 3
127.0.0.1:6379> lpush listone hello my java
(integer) 6
127.0.0.1:6379> lrange listone 0 -1
1) "java"
2) "my"
3) "hello"
4) "i"
5) "love"
6) "you"
127.0.0.1:6379> linsert listone before love zhangsan
(integer) 7
127.0.0.1:6379> lrange listone 0 -1
1) "java"
2) "my"
3) "hello"
4) "i"
5) "zhangsan"
6) "love"
7) "you"
127.0.0.1:6379> linsert listone after love lisi
(integer) 8
127.0.0.1:6379> lrange listone 0 -1
1) "java"
2) "my"
3) "hello"
4) "i"
5) "zhangsan"
6) "love"
7) "lisi"
8) "you"
127.0.0.1:6379> lpop listone
"java"
127.0.0.1:6379> rpop listone
"you"
127.0.0.1:6379> lrange listone 0 -1
1) "my"
2) "hello"
3) "i"
4) "zhangsan"
5) "love"
6) "lisi"
127.0.0.1:6379> lrem listone 1 my
(integer) 1
127.0.0.1:6379> lrange listone 0 -1
1) "hello"
2) "i"
3) "zhangsan"
4) "love"
5) "lisi"
6)示例二
127.0.0.1:6379> rpush listtwo b b b b b
(integer) 5
127.0.0.1:6379> lrem listtwo -3 b
(integer) 3
127.0.0.1:6379> lrange listtwo 0 -1
1) "b"
2) "b"
127.0.0.1:6379> lindex listtwo 0
"b"
127.0.0.1:6379> lindex listtwo 7
(nil)
127.0.0.1:6379> llen listtwo
(integer) 2
127.0.0.1:6379> lset listtwo 0 java
OK
127.0.0.1:6379> lrange listtwo 0 -1
1) "java"
2) "b"
6)实际应用
• LPUSH + LPOP = Stack
• LPUSH + RPOP = Queue
• LPUSH + LTRIM = Capped Colleciton
• LPUSH + BRPOP = Message Queue
1.4 Set(集合)
1)概述
Redis 的 Set 是 String 类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据。
Redis 中集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。
2)特点
- 无序
- 不可重复
- 集合间操作
3)API
- 集合内的操作
命令 | 说明 | 时间复杂度 |
sadd key element | 向集合key添加element(如果element已经存在,添加失败) | O(1) |
srem key element | 将集合key中的element移除掉 | O(1) |
scard key | 计算集合大小 | O(1) |
sismember key element | 判断element 是否在集合中 | O(1) |
srandmember key count | 从集合中随机挑count个元素 | O(1) |
spop key | 从集合中随机弹出一个元素 | O(1) |
smembers key | 获取集合中所有元素 | O(1) |
- 集合间的操作
命令 | 说明 | 时间复杂度 |
sdiff key1 key2 | 差集 | O(1) |
sinter key1 key2 | 交集 | O(1) |
sunion key1 key2 | 并集 | O(1) |
sidff/sinter/suion + store destkey | 将差集、交集、并集保存在destkey中 | O(1) |
- 说明
srandmember不会破坏集合
smembers 返回的是无序集合,并且要注意量很大的时候会阻塞
4)示例
- 集合内的操作
127.0.0.1:6379> sadd setone java pyhton c c++
(integer) 4
127.0.0.1:6379> smembers setone
1) "c++"
2) "c"
3) "pyhton"
4) "java"
127.0.0.1:6379> srem setone c
(integer) 1
127.0.0.1:6379> smembers setone
1) "c++"
2) "pyhton"
3) "java"
127.0.0.1:6379> scard setone
(integer) 3
127.0.0.1:6379> sismember setone java
(integer) 1
127.0.0.1:6379> srandmember setone 2
1) "c++"
2) "pyhton"
127.0.0.1:6379> spop setone
"pyhton"
127.0.0.1:6379> smembers setone
1) "c++"
2) "java"
- 集合间的操作
127.0.0.1:6379> sadd settwo 1 2 3 4 5 6
(integer) 6
127.0.0.1:6379> sadd setthree a b c 3 4 e 2
(integer) 7
127.0.0.1:6379> sdiff settwo setthree
1) "1"
2) "5"
3) "6"
127.0.0.1:6379> sinter settwo setthree
1) "2"
2) "3"
3) "4"
127.0.0.1:6379> sunion settwo setthree
1) "5"
2) "6"
3) "4"
4) "b"
5) "2"
6) "1"
7) "a"
8) "e"
9) "c"
10) "3"
5)实际应用场景
- 抽奖系统,用spop
- 赞过的文章,收藏过的文章等
- 共同关注
6)总结
- SADD = Tagging
- SPOP/SRANDMEMBER = Random item
- SADD + SINTER = Social Graph
1.5 ZSet(有序集合)
1)概述
Redis 有序集合和集合一样也是string类型元素的集合,且不允许重复的成员。
不同的是每个元素都会关联一个double类型的分数。
redis正是通过分数来为集合中的成员进行从小到大的排序。
有序集合的成员是唯一的,但分数(score)却可以重复。
2)API
命令 | 说明 | 时间复杂度 |
zadd key score element | 添加score和element | O(logN) |
zrem key element(可以是多个) | 将集合key中的element移除掉 | O(1) |
zscore key element | 返回元素的分数 | O(1) |
zincrby key increScore element | 增加或减少元素的分数 | O(1) |
zcard key | 返回元素的总个数 | O(1) |
zrank(zrevrank) key member | 返回元素的排名 | O(1) |
zrange(zrevrank) key start end [WITHSCORES] | 返回指定索引范围内的升序元素[分值] | O(logN + m) |
zrangebyscore(zrevrangebyscore) key minScore maxScore | 返回指定分数范围内的升序元素 | O(logN + m) |
zcount key minScore maxScore | 返回有序集合内在指定分数范围内的个数 | O(logN + m) |
zremrangebyrank key start end | 删除指定排名内的升序元素 | O(logN + m) |
zremrangebyscore key minScore maxScore | 删除指定分数内的升序元素 | O(logN + m) |
ZINTERSTORE destination numkeys(表示key的个数) key [key …] | 计算给定的一个或多个有序集的交集并将结果集存储在新的有序集合 key 中 | |
ZUNIONSTORE destination numkeys key [key …] | 计算给定的一个或多个有序集的并集,并存储在新的 key 中 |
3)示例
127.0.0.1:6379> zadd zsetone 10 java
(integer) 1
127.0.0.1:6379> zadd zsetone 20 pyhton
(integer) 1
127.0.0.1:6379> zadd zsetone 30 c
(integer) 1
127.0.0.1:6379> zadd zsetone 40 php
(integer) 1
127.0.0.1:6379> zscore zsetone c
"30"
127.0.0.1:6379> zcard zsetone
(integer) 4
127.0.0.1:6379> zrangebyscore zsetone 10 30
1) "java"
2) "pyhton"
3) "c"
4)实际应用场景
各种榜单(score:timestamp, saleCount, followCount)