Redis特性:
- 速度快:数据放在内存(主要原因)、单线程架构、C语言实现
- 持久化:断电或者机器故障时,数据持久化到到硬盘
- 简单稳定:Redis使用单线程模型、不依赖于操作系统中的类库
- 主从复制:实现了多个相同数据的Redis副本
- 高可用和分布式:2.8版本正式提供了高可用实现Redis Sentinel
3.0版本正式提供了分布式实现Redis Cluster - 丰富的功能:5种数据结构、键过期、Lua脚本等
- 基于键值对的数据结构服务器
- 客户端语言多
单线程架构:
Redis使用了单线程的I/O多路复用模型,
非阻塞I/O,使用epoll作为I/O多路复用技术的实现
单线程的好处: 简化数据结构和算法的实现
避免了线程切换和竞态产生的消耗
Redis的数据结构:
字符串(string)、哈希(hash)、列表(list)、集合(set)、有序集合(zset)
String:
字符串类型,其Value可以是字符串(简单字符串、XML或JSon等复杂字符串)、数值(int、float)、甚至是二进制(存图片、视频等),但其值最大不能超过512M。
- 常用命令:
set,get,decr,incr,mset,mget 等
mset可以批量插入键值,并且是原子性的。
mget可以减少网络时间,一次命令除了命令时间还是有网络时间:
n次get时间 = n次网络时间 + n次命令时间
mget时间 = 1次网络时间 + n次命令时间 - 内部编码:
Redis会根据当前值的类型和长度决定使用哪种内部编码实现。
·int: 8个字节的长整型。
·embstr: 小于等于39个字节的字符串。
·raw: 大于39个字节的字符串。
#object encoding key可以获取key的内部编码
127.0.0.1:6379> set key “hello,world”
OK
127.0.0.1:6379> object encoding key
"embstr
- 应用场景:
a).setnx可以作为分布式锁的一种实现方案, Redis官方给出了使用setnx实现分布式锁的方:setnx实现分布式锁
b).缓存:数据存放redis,先查redis,查不到数据时再查数据库,减缓数据库压力。
c).计数:通过incr实现常规计数
d).session共享:分布式服务中共享session信息(如用户登陆信息,实现简单的单点登陆)
Hash:
hash可以理解为嵌套的Map;如Map(key,map1)、map1(field,value)
- 常用命令:
hget,hset,hgetall,hkeys,hvals 等。
hgetall可能会阻塞Redis,可以使用hscan渐进式遍历哈希类型 - 内部编码:
当哈希类型元素个数小于hash-max-ziplist-entries配置(默认512个)、同时所有值都小于hash-max-ziplist-value配置(默认64字节) 时,Redis会使用ziplist作为哈希的内部实现,否则使用hashtable(哈希表);ziplist更加节省内存,效率更好。 - 应用场景:
可以Hash数据结构来存储数据库表信息:
#例如储存用户信息
hmset user name Tom age 22 sex 0
List:
hash列表(list) 类型是用来存储多个有序的字符串,因为有序, 可以通过索引下标获取元素或某个范围内元素列表; 一个列表最多可以存储232-1个元素
-
常用命令:
添加:lpush、rpush、linsert
删除:lpop、rpop、lrem、ltrim
修改:lset
查找:lrang、lindex、llen
阻塞:blpop、brpop -
内部编码:
同Hash,在 3.2 版本以后, redis提供了 quicklist 内部编码, 它结合了 ziplist 和 linkedlist 两者的优势,使用 quicklist 内部编码效率更高。 -
应用场景:
a).消息队列:lpush+brpop命令组合即可实现阻塞队列。一个队列的帖子
如果想要一个消息多个消费者消费,可以了解一下redis的pub/sub功能,但是还是最好使用专业的消息队列MQ
b).列表:Irange获取列表范围,lpush来推送新的消息:
Set:
保存多元素,与列表不一样的是不允许有重复元素, 且集合是无序, 一个集合最多可存 232-1元素, 除了支持增删改查, 还支持集合交集、 并集、 差集;
- 常用命令:
sadd,spop,smembers,sunion 等。
集合操作:sinter(交集)、sunion( 并集)、sdiff(差集)
集合操作的结果保存:sinterstore(将交集保存)、sunionstore(将并集保存)、sdiffstore(将差集保存) - 内部编码:
当集合中的元素都是整数且元素个数小于set-maxintset-entries配置(默认512个)时, Redis会选用intset来作为集合的内部实现, 从而减少内存的使用。否则使用hashtable(哈希表); - 应用场景:
a).抽奖:比如抽3名中奖:
点击抽奖,用户数据加入集合:sadd cj:01 user:id
抽奖:spop cj:01 3或srandmenber cj:01 3
查看抽奖人数:smembers cj:01
b).点赞:比如朋友圈消息ID:01
点赞:sadd ID:01 user:id;取消赞:srem ID:01 user:id
获取点赞列表:smembers ID:id
c).标签:用集合操作社交标签,比如sinter来做共同关注的人,sdiff来做可能认识的人
Zset:
有序集合中的元素可以排序,但不像List使用的下表索引排序,Zset是依据元素的score来排序,如下,tom的分数最高。有序集合中的元素不能重复,但是score可以重复, 就和一个班里的同学学号不能重复, 但是考试成绩可以相同。
- 常用命令:
zadd,zscore ,zrange,zrem,zcard,zrank,zrangebyscore等。
#zrangebyscore key min max [withscores] [limit offset count]
#min和max还支持开区间( 小括号) 和闭区间( 中括号)
#-inf和+inf分别代表无限小和无限大:
127.0.0.1:6379> zrangebyscore user:ranking (200 +inf withscores
“tim”
“220”
“martin”
“250”
“tom”
“251”
- 内部编码:
当有序集合的元素个数小于hash-max-ziplist-entries配置(默认512个)、同时所有值都小于hash-max-ziplist-value配置(默认64字节) 时,Redis会使用ziplist作为有序集合的内部实现,否则使用skiplist(跳跃表);ziplist更加节省内存,效率更好。 - 应用场景:
a).排行榜系统:视频网站的排行(按时间、播放数量等)
#zrank分数从低到高返回排名(排名从0开始计算);zrevrank反之
127.0.0.1:6379> zrank user:ranking tom
(integer) 5
127.0.0.1:6379> zrevrank user:ranking tom
(integer) 0
#前3名:
zrevrange user:ranking 0 3
b).点赞:zadd user:id 4 tom //给tom点4个赞
4. List、Set、Zset异同:
参考:
《Redis开发与运维》