REDIS

一、什么是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为什么这么快?

  1. 完全基于内存,数据存储在内存中,绝大部分请求都是内存操作,因此非常快速。

  2. 数据结构简单,redis中的数据结构是专门设计的,对数据操作简单。

  3. 采用单线程,不用考虑多线程中上下文切换、线程安全、死锁等问题,避免不必要的性能消耗。

  4. 使用多路I/O复用模型,非阻塞I/O。

  5. 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 缓存击穿与缓存雪崩

缓存击穿是并发查询同一条数据;
缓存雪崩是不同的数据同时过期了。