一、什么是redis?
-
redis是c语言编写的、开源的、高性能的、非关系型(nosql)的键值对数据库
-
redis可以存储键和多种不同类型的值之间的映射,键的类型只能为字符串
-
redis支持五种主要的数据类型:字符串(string)、列表(list)、集合(set)、散列表(hash)、有序集合(zset)
二、redis的优缺点
优点:
-
读写性能优异, Redis能读的速度是110000次/s,写的速度是81000次/s。
-
支持数据持久化,支持AOF和RDB两种持久化方式。
-
支持事务,Redis的所有操作都是原子性的,同时Redis还支持对几个操作合并后的原子性执行。
-
数据结构丰富,除了支持string类型的value外还支持hash、set、zset、list等数据结构。
-
支持主从复制,主机会自动将数据同步到从机,可以进行读写分离。
缺点:
-
数据库容量受到物理内存的限制,不能用作海量数据的高性能读写,因此Redis适合的场景主要局限在较小数据量的高性能操作和运算上。
-
Redis 不具备自动容错和恢复功能,主机从机的宕机都会导致前端部分读写请求失败,需要等待机器重启或者手动切换前端的IP才能恢复。
-
主机宕机,宕机前有部分数据未能及时同步到从机,切换IP后还会引入数据不一致的问题,降低了系统的可用性。
-
Redis 较难支持在线扩容,在集群容量达到上限时在线扩容会变得很复杂。为避免这一问题,运维人员在系统上线时必须确保有足够的空间,这对资源造成了很大的浪费。
三、redis为什么这么快?
-
完全基于内存,数据存储在内存中,绝大部分请求都是内存操作,因此非常快速。
-
数据结构简单,redis中的数据结构是专门设计的,对数据操作简单。
-
采用单线程,不用考虑多线程中上下文切换、线程安全、死锁等问题,避免不必要的性能消耗。
-
使用多路I/O复用模型,非阻塞I/O。
-
redis自己构建了vm模型,节省了系统内部函数调用的时间。
四、redis五种数据结构
数据类型 | 可以存储的值 | 操作 | 应用场景 |
---|---|---|---|
STRING | 字符串、整数或者浮点数 | 对整个字符串或者字符串的其中一部分执行操作 对整数和浮点数执行自增或者自减操作 | 做简单的键值对缓存 |
LIST | 列表 | 从两端压入或者弹出元素 对单个或者多个元素进行修剪, 只保留一个范围内的元素 | 存储一些列表型的数据结构,类似粉丝列表、文章的评论列表之类的数据 |
SET | 无序集合 | 添加、获取、移除单个元素 检查一个元素是否存在于集合中 计算交集、并集、差集 从集合里面随机获取元素 | 交集、并集、差集的操作,比如交集,可以把两个人的粉丝列表整一个交集 |
HASH | 包含键值对的无序散列表 | 添加、获取、移除单个键值对 获取所有键值对 检查某个键是否存在 | 结构化的数据,比如一个对象 |
ZSET | 有序集合 | 添加、获取、删除元素 根据分值范围或者成员来获取元素 计算一个键的排名 | 去重但可以排序,如获取排名前几名的用户 |
五、redis五种数据类型应用场景
(1)字符串——string
string——适合最简单的k-v存储:
1、短信验证码
2、配置信息
3、自增自减运算,实现计数器功能(访问量)
(2)列表——list
list——list是有序的,适合存储一些有序且数据相对固定的数据:
1、省市区表
2、字典表
3、list是有序的,适合根据写入的时间来排序,如:最新的***,消息队列等
(3)散列表——hash
hash——一般key为ID或者唯一标示,value对应的就是详情:
1、商品详情,个人信息详情,新闻详情
2、存取实体,修改某一字段简单,不需要取出实体全部
(4)集合(set)
set——可以简单的理解为ID-List的模式:
1、数据不重复,可以求交集并集差集,例如求共同好友
(5)有序集合(zset)
Sorted Set——是set的增强版本,增加了一个score参数,自动会根据score的值进行排序:
1、自带分数,可以用作排序功能
六、redis持久化方式
RDB(Redis DataBase):指在指定的时间间隔内将内存中的数据集快照写入磁盘,redis单独创建一个子线程进行持久化,主进程不进行任何io操作,确保性能
优点:节省磁盘空间,恢复速度快
缺点:虽然rdb使用了写时拷贝技术,但是数据大时还是比较消耗性能;会丢失最后最后一次持久化期间主进程修改的数据
AOF(Append Only File):以日志的形式记录每一个写操作
优点:丢失数据的概率更低;可读的日志文件,通过修改AOF文件,可以处理误操作
缺点:占用更多的磁盘空间,恢复速度慢,每次读写都同步,有一定的压力,存在个别bug,造成不能恢复
七、redis过期键删除策略
策略 | 解释 | 优点 | 缺点 |
---|---|---|---|
定时过期 | 到过期时间立即清除键 | 可以立即清除过期键,对内存友好 | 占用大量CPU资源处理过期数据,影响响应时间和吞吐量 |
惰性过期 | 访问key时判断key是否过期,过期则清除 | 最大化节省CPU资源 | 大量过期的key可能没有再次被访问,占用大量内存 |
定期过期 | 每隔一定时间,扫描一定数据的key,清除其中过期的key | 节省CPU资源,节省内存 |
八、redis内存淘汰策略
策略 | 键属性 | 解释 |
---|---|---|
noeviction | 全局键 | 内存不足时,新写入操作会报错 |
allkeys-lru | 全局键 | 内存不足时,在键空间中,移除最近最少使用的key |
allkeys-random | 全局键 | 内存不足时,在键空间中,随机移除某个key |
volatile-lru | 设置过期时间的键 | 内存不足时,在设置了过期时间的键空间中,移除最近最少使用的key |
volatile-random | 设置过期时间的键 | 内存不足时,在设置了过期时间的键空间中,随机移除某个key |
volatile-ttl | 设置过期时间的键 | 内存不足时,在设置了过期时间的键空间中,有更早过期时间的key优先移除 |
九、redis事务
事务管理(ACID)概述:
1、原子性(Atomicity)
原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
2、一致性(Consistency)
事务前后数据的完整性必须保持一致。
3、隔离性(Isolation)
多个事务并发执行时,一个事务的执行不应影响其他事务的执行。
4、持久性(Durability)
持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响。
Redis事务相关命令:
multi:事务开始
exec:执行事务命令
discard:取消事务
watch:监测key
unwatch:取消监测
redis事务只支持事务的一致性和隔离性,不支持其他特性,但redis的单条命令支持原子性。
十、redis缓存问题
1 缓存穿透
缓存穿透:
缓存与数据库中都没有数据,导致所有请求都落在数据库上,造成数据库短时间内承受大量请求而崩掉
解决方案:
1、接口层增加校验,过滤无效的请求,如用户鉴权校验,id做基础校验,id<=0的直接拦截
2、从缓存和数据都找不到的数据,可以将key-value设置为key-null,设置过期时间,防止反复请求数据库
3、采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,不存在的数据会被这个bitmap过滤掉,避免对底层数据库的请求压力
2 缓存击穿
缓存击穿:
缓存中数据过期,缓存没有数据,但数据库有,同时并发量高,访问缓存的同时又去访问数据库,引起数据库压力瞬间增大,造成过大压力
解决方案:
1、设置热点数据永不过期
2、加互斥锁,限制并发
3 缓存降级
缓存降级:
当访问量剧增、服务出现问题(如响应时间慢或不响应)或非核心服务影响到核心流程的性能时,仍然需要保证服务还是可用的,即使是有损服务。系统可以根据一些关键数据进行自动降级,也可以配置开关实现人工降级。
服务降级的目的,是为了防止Redis服务故障,导致数据库跟着一起发生雪崩问题。因此,对于不重要的缓存数据,可以采取服务降级策略,例如一个比较常见的做法就是,Redis出现问题,不去数据库查询,而是直接返回默认值给用户。
4 缓存雪崩
缓存雪崩:
缓存同一时间大面积的失效,导致后面的请求都会落到数据库上,造成数据库短时间内承受大量请求而崩掉。
解决方案:
1、缓存数据设置随机的过期时间,避免同一时间失效
2、并发量不是很多时,采用加锁计数或合理数量的队列避免缓存中key同时失效
3、给每一个缓存数据增加相应的缓存标记,记录缓存的是否失效,如果缓存标记失效,则更新数据缓存
5 缓存预热
缓存预热:
系统上线后,将相关的缓存数据直接加载到缓存系统。这样就可以避免在用户请求的时候,先查询数据库,然后再将数据缓存的问题!用户直接查询事先被预热的缓存数据!
解决方案:
1、写个刷新缓存的页面,上线后手动操作一下
2、在项目启动的时候自动加载
3、可以做定时任务,定时刷新缓存
6 缓存击穿与缓存雪崩
缓存击穿是并发查询同一条数据;
缓存雪崩是不同的数据同时过期了。