1 概述
1.1 简介
Redis是完全开源的,遵守BSD协议,是一个高性能的key-value数据库。 Redis与其他key-value缓存产品有以下三个特点:
- redis支持数据的持久化,可以将内存那种的数据保存在磁盘上,重启的时候可以再次加载进行使用。
- Redis不仅仅支持简单的key-value类型的数据,同时还提供list、set、zset、hash等数据结构的存储。
- Redis支持数据的备份,即master-slave模式的数据备份。
1.2 Redis有何优势
- 性能极高,Redis能读的速度是110000次/s,写的速度是81000次/s。
- 丰富的数据类型,Redis支持二进制案例的Strings、Lists、Hashes、Sets和Ordered Sets数据类型操作。
- 原子,Redis的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行,单个操作是原子性的,多个操作也支持事务,即原子性,通过MULTI和EXEC指令包起来。
- 丰富的特性,Redis还支持publish/subscribe,通知,key过期等等特性。
1.3 Redis与其他key-value存储有什么不同?
- Redis有着更为复杂的数据结构并且提供对他们的原子性操作,这是一个不同于其他数据库的进化路径。Redis的数据类型都是基于基本数据结构的同时对程序员透明,无需进行额外的抽象。
- Redis运行在内存中但是可以持久化到磁盘,所以在对不同数据集进行高速读写时需要权衡内存,因为数据量不能大于硬件内存。在内存数据库方面的另一个优点是,相比在磁盘上相同的复杂的数据结构,在内存中操作起来非常简单,这样Redis可以做很多内存复杂性很强的事情。同时,在磁盘格式方面他们是紧凑的以追加的方式产生的,因为他们并不需要进行随机访问。
2 安装及启动
百度一堆
3 常用命令
建议英文不好的朋友补一下英文,直接看 Redis官网 Redis官方文档
查命令直接到这里:Redis官网命令
4 Reids五种数据结构
4.1 String
4.1.1 常用操作
set key value
get key
4.1.2 应用场景
4.1.2.1 单值缓存
set key value
get key
4.1.2.2 对象缓存
比如下面这张表:
| id | name | balance |
|---|---|---|
| 1 | 张三 | 99 |
| 2 | 李四 | 999 |
| 3 | 王五 | 4999 |
- 存:set user:1 value(该条记录的json格式数据),取get user:1
- 存:mset user:1:name 张三 user:1:balance 99,取mget user:1:name user:1:balance,此场景适用于经常要对某些字段进行修改。
4.1.2.3 分布式锁(入门级别)
setnx product:10001 true 返回1代表获取锁成功
setnx product:10001 true 返回0代表获取锁失败
...执行业务操作
del product:10001 执行完业务释放锁
set product:10001 true ex 10 nx 防止程序意外终止导致死锁
4.1.2.4 计数器
针对文章每次打开就计数一次
incr article:readcount:{文章id}
get article:readcount:{文章id}
4.1.2.5 分布式系统全局序列号
incrby orderId 1000 //redis批量生成序列号提升性能
4.2 hash
4.2.1 常用操作:
hset key field value 存储一个哈希表key的键值
hsetnx key field value 存储一个不存在的哈希表key的键值
hmset key field value [field value ...] 在一个哈希表key中存储多个键值对
hget key field 获取哈希表key对应的field值
hmget key field [field ...] 批量获取哈希表key中多个field的值
hdel key field [field ...] 删除哈希表key中的field键值
hlen key 返回哈希表key中field的数量
hgetall key 返回哈希表key中所有的键值
hincrby key field increment 为哈希表key中field健的值加上增量increment
4.2.2 应用场景
4.2.2.1 对象缓存
hmset user {userId}:name zhangsan {userId}:balance 1000
hmset user 1:name zhangsan 1:balance 1000
hmget user 1:name 1:balance
4.2.2.2 电商购物车
- 以用户id为key
- 商品id为field
- 商品数量为value
购物车操作:
添加商品:hset cart:101 10001
增加数量:hincrby cart:101 10001
商品总数:hlen cart:101
删除商品:hdel cart:101 10001
获取购物车所有商品:hgetall cart:101
4.2.3 hash与String数据结构相比优劣势:
- 优点:
- 同类数据归类整合存储,方便数据管理
- 相比string操作消耗内存与cpu更小
- 相比string存储更节省空间
- 缺点:
- 过期功能不能使用在field上,只能用在key上
- Redis集群架构下不适合大规模使用
4.3 list
4.3.1 常用操作:
lpush key value [value...] 将一个或多个值value插入到key列表的表头(最左边)
rpush key value [value...] 将一个或多个值value插入到key列表的表尾(最右边)
lpop key 移除并返回key列表的头元素
rpop key 移除并返回key列表的尾元素
lrange key start stop 返回列表key中指定区间的元素,区间以偏移量start和stop指定
blpop key [key...] timeout 从key列表表头弹出一个元素,若列表中没有元素,等待timeout秒,如果timeout=0则一直阻塞等待
brpop key [key...] timeout 从key列表表尾弹出一个元素,若列表中没有元素,等待timeout秒,如果timeout=0则一直阻塞等待
4.3.2 常用数据结构:
- Stack(栈) = lpush + lpop = FILO(先进后出)
- Queue(队列) = lpush + rpop = FIFO(先进先出)
- Blocking MQ(阻塞队列) = lpush + brpop
4.3.3 应用场景:
4.3.3.1 微博/微信消息流
比如张三关注了“混子曰”公众号 和 “Java架构日记”公众号,
- 混子曰公众号只要一发消息,ID为100
lpush msg:{张三ID} 100
- Java架构日记也发了一条消息,ID为200
lpush msg:{张三ID} 200
- 张三查看公众号消息
lrange msg:{张三ID} 0 2
4.4 set
4.4.1 常用操作
sadd key member [member...] 往集合key中存入元素,元素存在则忽略,若key不存在则新建
srem key member [member...] 从集合key中删除元素
smembers key 获取集合key中所有元素
scard key 获取集合key的元素个数
sismember key member 判断member元素是否存在于集合key中
srandmember key [count] 从集合key中随机选出count个元素,元素不从key中删除
spop key [count] 从集合key中随机选出count个元素,元素从key中删除
4.4.2 运算操作
sinter key [key...] 交集运算
sinterstore destination key [key...] 将交集结果存入新集合destination中
sunion key [key...] 并集运算
sunionstore destination key [key...] 将并集结果存入新集合destination中
sdiff key [key...] 差集运算
sdiffstore destination key [key...] 将差集结果存入新集合destination中
4.4.3 应用场景
4.4.3.1 微信抽奖小程序
- 点击“参与抽奖”加入集合
sadd key {userId}
- 查看参与抽奖所有用户
smembers key
- 抽取count名中奖者
srandmember key [count] / spop key [count]
4.4.3.2 微博微信点赞、收藏、标签
- 点赞
sadd like:{消息ID} {用户ID}
- 取消点赞
srem like:{消息ID} {用户ID}
- 检查用户是否点过赞
sismember like:{消息ID} {用户ID}
- 获取点赞的用户列表
smembers like:{消息ID}
- 获取点赞用户数
scard like:{消息ID}
4.4.3.3 集合操作实现微博/微信关注模型
取交集
sinter set1 sert2 set3
取并集
sunion set1 set2 set3
取差集(以第一个集合为基础,减去后面集合的并集,结果是第一个集合的剩下的元素)
sdiff set1 set2 set3
4.4.3.4 集合操作实现电商商品筛选
比如买手机,筛选页有品牌、操作系统、CPU品牌等等
sadd brand:huawei p40
sadd brand:xiaomi mi10
sadd brand:apple iphone12
sadd os:osx iphone12
sadd os:android p40 mi10
sadd cpu:brand:inter p40 mi10
sadd ram:8G p40 mi10 iphone12
...
想找到Android系统CPU是inter内存是8G的手机都有哪些
sinter os:android cpu:brand:inter ram:5G
4.5 ZSet
4.5.1 常用操作
zadd key score member [[score member]...] 往有序集合key中加入带分值元素
zrem key member [member...] 从有序集合key中删除元素
zscore key member 返回有序集合key中元素的member分值
zincrby key increment member 为有序集合key中元素member的分值加上increment
zcard key 返回有序集合key中元素个数
zrange key start stop [withscores] 正序获取有序集合key从start下标到stop下标的元素
zrevrange key start stop [withscores] 倒序获取有序集合key从start下标到stop下标的元素
4.5.2 集合操作
zunionstore destkey numkeys key [key ...] 并集计算
zinterstore destkey numkeys key [key ...] 交集计算
4.5.3 应用场景
4.5.3.1 新闻排行榜
- 点击新闻
zincrby hotNews:20201201 1 newID:1
- 展示当日排行前十
zrevrange hotNews:20201201 0 9 withscores
- 三日查看榜单计算
zunionstore hotNews:20201201-20201203 3 hotNews:20201201 hotNews:20201202 hotNews:20201203
- 展示三日排行前十
zinterstore hotNews:20201201-20201203 0 9 withscores
4.6 scan:渐进式遍历键
scan cursor [MATCH pattern] [COUNT count] scan参数提供了三个参数,第一个是cursor整数值(hash桶的索引值),第二个是key的正则模式,第三个是一次遍历的key的数量(参考值,底层遍历的数量不一定),并不是符合条件的结果数量。第一次遍历时,cursor值为0,然后将返回结果中第一个整数值作为下一次遍历的cursor。一直遍历到返回的cursor值为0时结束。 注意:但是scan并非完美无瑕,如果再scan的过程中如果有键的变化(增加、删除、修改),那么遍历效果可能会碰到如下问题:新增的键可能没有遍历到,遍历出了重复的键等情况,也就是说scan并不能保证完整的遍历出来所有的键,这些是我们在开发时需要考虑的。