Redis [1] 简介、数据结构、应用场景
简介:Nosql介绍和Reidis介绍
什么是Redis
属于NoSQL的⼀种 ( Not Only SQL )
是不同于传统的关系数据库的数据库管理系统的统称其两者最重要的区别是NoSQL不使⽤SQL作为查询
语⾔。
NoSQL数据存储可以不需要固定的表格模式键 - 值对存储,列存储,⽂档存储,图形数据库
NoSql:redis、memcached、mongodb、Hbase
什么是缓存
程序经常要调⽤的对象存在内存中,⽅便其使⽤时可以快速调⽤,
不必去数据库或者其他持久化设备中查询
主要 就是提⾼性能 DNS缓存、前端缓存、代理服务器、缓存Nginx、应⽤程序缓存、数据库缓存
面:为什么要用缓存
用缓存,主要有图两个优点:高性能、高并发。
高性能
指的是多个用户同时访问是,程序能够尽快的返回用户需要的数据,如果每次去查数据库,势必会增加服务器和数据库的压力,而用了缓存之后,后来的请求都可以尽快的得到返回结果
高并发
mysql 单机支撑到 2000QPS
也开始容易报警了
Redis能读的速度是11w次/s,写的速度是8w次/s
缓存是走内存的,内存天然就支撑高并发。
面:缓存会带来哪些问题?
主要有三方面吧
缓存与数据库存储的数据不一致
缓存穿透、缓存雪崩、缓存击穿
缓存并发竞争
具体分析:
如何保证缓存与数据库的双写一致性?:https://doocs.github.io/advanced-java/#/docs/high-concurrency/redis-consistence
了解什么是 Redis 的雪崩、穿透和击穿?Redis 崩溃之后会怎么样?系统该如何应对这种情况?如何处理 Redis 的穿透?:https://doocs.github.io/advanced-java/#/docs/high-concurrency/redis-caching-avalanche-and-caching-penetration
Redis 的并发竞争问题是什么?如何解决这个问题?了解 Redis 事务的 CAS 方案吗?
https://doocs.github.io/advanced-java/#/docs/high-concurrency/redis-cas
热点key的解决方案之一
避免带宽或者传输影响,本地缓存热点key数据,对于每次读请求,将首先检查key是否存在于本地缓存中,如果存在则直接返回,如果不存在再去访问分布式缓存的机器
-
缓存中的某些Key对应的value存储在集群中一台机器,使得所有流量涌向同一机器,成为系统的瓶颈,无法通过增加机器容量来解决
-
热卖商品、热点新闻、热点评论、大V明星结婚
-
高性能:Redis能读的速度是110000次/s,写的速度是81000次/s
-
内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。 它支持多 种类型的数据结构,如 字符串(strings)、散列(hashes)、 列表(lists)、 集合(sets)、 有序集合(sorted sets)等
-
特性:aof/rdb、高性能原因、key设计、热点key、淘汰算法
strings:验证码、计数器
hashes:购物车、用户信息
lists:榜单、最新评论页
sets:去重、共同好友
sorted sets :实时榜单、优先队列
数据结构及其应用场景
String结构
介绍
存储字符串类型的key-value
它是一种动态字符串,是可以修改的字符串,采用预先分配冗余空间来减少内存的平凡分配。
分配的实际空间是要高于实际字符串长度的。
扩容规则
小于1mb,每次加倍
大于1mb,每次只加1mb
应用场景
验证码
计数器、发号器
订单重复提交令牌
热点商品卡片(序列化json对象存储)
分布式锁
注意
值的长度不能超过512 MB
key命名规范,不要过长,冒号分割,业务名:表名:ID
List结构
介绍
字符串列表,按照插入顺序排序
双向链表,插入删除时间复杂度O(1)快,查找为O(n)慢
底层数据结构
quicklist
列表元素较少的情况下,会使用一块连续的内存存储,ziplist,即压缩列表。
当元素较多时,会改为quicklist。
因为链表不仅需要数据域,还需要指针域,连续存储可以不使用指针域来存储指针信息。从而减少内存空间的使用。
应用场景
简单队列
最新评论列表
只缓存第一页
非实时排行榜:定时计算榜单,如手机日销榜单
每日定时计算,然后存入缓存中,方便取结果
空间换时间
注意
通常添加一个元素到列表的头部(左边)或者尾部(右边)
存储的都是string字符串类型
支持分页操作,高并发项目中,第一页数据都是来源list,第二页和更多信息则是通过数据库加载
一个列表最多可以包含 2^32 - 1 个元素 (4294967295, 每个列表不超过40亿个元素)
Hash结构
介绍
是一个string类型的field和value的映射表,hash特别适合用于存储对象
与java 的map区别
java的map在字典很大的时候,rehash是个耗时的操作,需要一次性rehash
redis为了追求高性能,不能堵塞服务,采用渐进式hash
渐进式hash
rehash的同时保留两个hash结果。
查询时会同时查询两个hash结构,在后续的定时任务和hash操作指令中,逐渐将旧的hash内容一点点迁移到新的hash结构中。搬迁完成后,旧的hash会被删除,内存被回收。
应用场景
购物车
hash结构,cart:userId 对应 一个hashmap
key 为 productId, value 为json 字符串,内容是购物规格
用户个人信息
商品详情
注意
每个 hash 可以存储 2^32 - 1 键值对(40多亿)
Set结构
介绍
将一个或多个成员元素加入到集合中,已经存在于集合的成员元素将被忽略
可以做交集、差集、并集
数据结构
value值为null
应用场景
去重
社交应用关注、粉丝、共同好友
共同好友,好友做交集
差集可以用来做推荐
统计网站的PV、UV、IP
大数据里面的用户画像标签集合
注意
集合是通过哈希表实现的
zset结构
介绍
用于将一个或多个成员元素及其分数值加入到有序集当中
如果某个成员已经是有序集的成员,那么更新这个成员的分数值,分数值可以是整数值或双精度浮点数。
有序集合可以看做是在Set集合的的基础上为集合中的每个元素维护了一个顺序值: score,它允许集合中的元素可以按照score进行排序
应用场景
实时排行榜:商品热销榜、体育类应用热门球队、积分榜
优先级任务、队列
朋友圈 文章点赞-取消,逻辑:用户只能点赞或取消,统计一篇文章被点赞了多少次,可以直接取里面有多少个成员
注意
底层使用到了Ziplist压缩列表和“跳跃表”两种存储结构
如果重复添加相同的数据,score值将被反复覆盖,保留最后一次修改的结果
通用命令
exists
判断key是否存在
del
删除key
type
判断key类型
ttl
查看key存活时间
String结构
介绍
存储字符串类型的key-value
应用场景
验证码
计数器、发号器
订单重复提交令牌
热点商品卡片(序列化json对象存储)
分布式锁
注意
值的长度不能超过512 MB
key命名规范,不要过长,冒号分割,业务名:表名:ID
常用命令
set/get
设置和获取 key-value
mget/mset
· 批量设置或获取多个key的值
· MGET key [key ...]
· MSET key value [key value ...]
incr
· incr对key对应的值进行加1操作,并返回新的值;
· incr key
incrby
· 将key对应的数字加increment。如果key不存在,操作之前,key就会被置为0
· incrby key increment
setex
· 设置key对应字符串value,并且设置key在给定的seconds时间之后超时过期,原子操作
· SETEX key seconds value
setnx
· 将key设置值为value,如果key不存在等同SET命令。 当key存在时什么也不做, 是set if not exists的简写。
· SETNX key value
getset
· 设置key的值,并返回key旧的值
· GETSET KEY_NAME VALUE
List结构
介绍
字符串列表,按照插入顺序排序
双向链表,插入删除时间复杂度O(1)快,查找为O(n)慢
应用场景
简单队列
最新评论列表
只缓存第一页
非实时排行榜:定时计算榜单,如手机日销榜单
每日定时计算,然后存入缓存中,方便取结果
空间换时间
注意
通常添加一个元素到列表的头部(左边)或者尾部(右边)
存储的都是string字符串类型
支持分页操作,高并发项目中,第一页数据都是来源list,第二页和更多信息则是通过数据库加载
一个列表最多可以包含 232 - 1 个元素 (4294967295, 每个列表不超过40亿个元素)
常用命令
lpush
· 将一个或多个值插入到列表头部
· LPUSH key value1 [value2]
rpop
· 移除并获取列表最后一个元素
· RPOP key
llen
· 获取列表长度
· LLEN key
lindex
· 通过索引获取列表中的元素
· LINDEX key index
lrange
· 获取key对应的list的指定下标范围的元素, 其中 0 表示列表的第一个元素, 1 表示列表的第二个元素, -1表示获取所有元素( lrange key 0 -1);
· LRANGE key start stop
rpush
· 在key对应的list的尾部添加一个元素
· RPUSH key value1 [value2]
lpop
· 从key对应的list的尾部删除一个元素,并返回该元素
· LPOP key
brpop
· 移出并获取列表的最后一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止
· BRPOP LIST1 LIST2 .. LISTN TIMEOUT
lrem
· 移除元素,可以指定移除个数
· LREM KEY COUNT VALUE
Hash结构
介绍
是一个string类型的field和value的映射表,hash特别适合用于存储对象
应用场景
购物车
hash结构,cart:userId 对应 一个hashmap
key 为 productId, value 为json 字符串,内容是购物规格
用户个人信息
商品详情
注意
每个 hash 可以存储 2^32 - 1 键值对(40多亿)
常用命令
hset
· 设置 key 指定的哈希集中指定字段的值
· HSET key field value
hget
· 返回 key 指定的哈希集中该字段所关联的值
· HGET key field
hgetall
· 返回 key 指定的哈希集中所有的字段和值
· HGETALL key
hdel
· 从 key 指定的哈希集中移除指定的域
· HDEL key field [field ...]
hexists
· 返回hash里面field是否存在
· HEXISTS key field
hincrby
· 增加 key 指定的哈希集中指定字段的数值, 如果是-1 则是递减
· HINCRBY key field increment
hmset
· 设置 key 指定的哈希集中指定字段的值
· HMSET key field value [field value ...]
hmget
· 返回 key 指定的哈希集中指定字段的值
· HMGET key field [field ...]
Set结构
介绍
将一个或多个成员元素加入到集合中,已经存在于集合的成员元素将被忽略
可以做交集、差集、并集
应用场景
去重
社交应用关注、粉丝、共同好友
共同好友,好友做交集
差集可以用来做推荐
统计网站的PV、UV、IP
大数据里面的用户画像标签集合
注意
集合是通过哈希表实现的
常用命令
sadd
· 添加一个或多个指定的member元素到集合的 key中.指定的一个或者多个元素member 如果已经在集合key中存在则忽略
· SADD key member [member ...]
scard
· 返回集合存储的key的基数 (集合元素的数量).
· SCARD key
sdiff
· 返回的集合元素是第一个key的集合与后面所有key的集合的差集
· SDIFF key [key ...]
sinter
· 返回指定所有的集合的成员的交集.
· SINTER key [key ...]
sismember
· 返回成员 member 是否是存储的集合 key的成员.
· SISMEMBER key member
srem
· 在key集合中移除指定的元素. 如果指定的元素不是key集合中的元素则忽略
· SREM key member [member ...]
sunion
· 返回给定的多个集合的并集中的所有成员.
· SUNION key [key ...]
smembers
· 返回key集合所有的元素.
· SMEMBERS key
Sorted Set结构
介绍
用于将一个或多个成员元素及其分数值加入到有序集当中
如果某个成员已经是有序集的成员,那么更新这个成员的分数值,分数值可以是整数值或双精度浮点数。
有序集合可以看做是在Set集合的的基础上为集合中的每个元素维护了一个顺序值: score,它允许集合中的元素可以按照score进行排序
应用场景
实时排行榜:商品热销榜、体育类应用热门球队、积分榜
优先级任务、队列
朋友圈 文章点赞-取消,逻辑:用户只能点赞或取消,统计一篇文章被点赞了多少次,可以直接取里面有多少个成员
注意
底层使用到了Ziplist压缩列表和“跳跃表”两种存储结构
如果重复添加相同的数据,score值将被反复覆盖,保留最后一次修改的结果
常用命令
zadd
· 向有序集合添加一个或多个成员,或者更新已存在成员的分数
· ZADD key score1 member1 [score2 member2]
zcard
· 获取有序集合的成员数
· ZCARD key
zcount
· 计算在有序集合中指定区间分数的成员数
· ZCOUNT key min max
zincrby
· ZINCRBY key increment member
· 有序集合中对指定成员的分数加上增量 increment
zrange
· 通过索引区间返回有序集合指定区间内的成员, 成员的位置按分数值递增(从小到大)来排序
· ZRANGE key start stop [WITHSCORES]
zrevrange
· 通过索引区间返回有序集合指定区间内的成员, 成员的位置按分数值递增(从大到小)来排序
· ZREVRANGE key start stop [WITHSCORES]
zrevrank
· 返回有序集合中指定成员的排名,有序集成员按分数值递减(从大到小)排序
· ZREVRANK key member
zrank
· 返回有序集key中成员member的排名。其中有序集成员按score值递增(从小到大)顺序排列
· ZRANK key member
zrem
· 移除有序集合中的一个或多个成员
· ZREM key member [member ...]
zscore
· 返回有序集中,成员的分数值
· ZSCORE key member