Redis相关
1.什么是redis,是用来做什么的?
redis是一个c语言编写的nosql数据库,支持网络,基于内存,可持久化的,key-value类型的数据库.
使用场景
- 缓存
- 计数器 点赞
- 排行榜 zset可以排序
- 数据排重 set不能存储重复数据
- 消息队列 list先进先出,先进后出
- 分布式锁 共享数据
2.redis的基本数据结构
1.String字符串,一个key对应一个value,value可以是字符串,数字或二级制数据常用于缓存用户信息,配置参数,计数器
2.List列表,简单的字符串列表,按照插入顺序排序,可以从列表的两端进行插入和删除操作适用于存储有序的元素集合,如消息队列,任务队列
3.hash哈希,包含键值对的无序散列表,适合存储对象,将对象的字段和值分别作为哈希的FIELD和value常用于存储和管理用户信息和商品信息
4.set集合,无序的字符串集合,集合的元素不唯一,不允许重复用于存储不重复的元素集合如标签和兴趣爱好
5.Sorted Set有序集合,类似与集合,但是每个元素都关联一个分数,通过分数来对元素进行排序常用于排行榜,推荐系统等场景
3.redis的线程模型
redis6.0之前是单线程模型的,在redis服务端只有一个线程进行处理,既要处理客户端的连接还要执行客户端发送的命令
redis6.0之后,采用多线程模型,处理客户端连接请求是一部分模型在处理,还有线程专门来处理客户端发送的命令,执行命令的线程只是一个,是并发安全的
为什么设计为单线程速度也很快?
1.操作都是在内存中的,所以性能是比较高的
2.底层是一个哈希表,可以通过key的哈希值快速定位到存储的位置,hash值可以在O(1)时间内被算出
3.由于单线程模型不存在上下文切换问题,节省了切换的开销
4.redis的持久化
redis是一个内存数据库,数据保存在内存中,但是内存中的数据变化是很快的,也容易发送丢失,所以redis还为我们提供了持久化的机制,分别是RDB(Redis DataBase)和 AOF(Append Only File)。
RDB方式
指在指定的时间间隔内将内存中的数据以快照的形式写入磁盘,存储到RDB 文件中(dump.rdb).
AOF方式
以日志的形式记录每个写操作,将redis执行过的所有指令记录下来(读操作不记录),只许追加文件但不可以改写文件,redis启动之初会读取该文件重新构建数据.
AOF这种方式redis默认是没有启用的,
appendonly no 改为yes启用
appendfsync always 每次修改都会保存,消耗性能
appendfsync everysec 每秒执行一次,可能在这一秒丢失
5.redis事务
redis事务本质是一次操作中多条命令能够作为一个整体执行,执行过程中间不被插入其他命令执行,这时就应该开启事务
multi命令开启事务
发送命令1 只是命令组队并不执行
发送命令2
...
exec 执行这个命令时才会执行事务中的多个命令
该事务不保证命令执行的原子性,多条命令中,如果有某一条命令执行失败,其他命令成功,那它执行成功的命令依然有效,失败的命令未成功.
6.redis的过期策略
惰性删除:key中会维护一个状态,当过期时不会立即删除过期的key,会在下一次使用时发现key过期,此时才会删除过期的key
好处:不需要实时的扫描跟踪,但是会浪费一定的内存空间
定期删除:会定期扫描redis中过期的key,需要消耗一定的资源
好处:不会浪费空间
7.redis和mysql的一致性
1.先更新mysql数据,然后更新redis,在实际开发中,有可能更新redis时出现问题,导致redis数据更新失败,用户还是继续从redis查询数据,查询到的是旧数据
2.先删除redis中的数据,然后再更新mysql数据,虽然可以解决方式1 的问题,但是也可能出现问题,线程1删除了redis数据,正在更新mysql,此时线程2有可能正在查询,仍然查询到的是旧数据
3.延时双删,在更新前先删除redis中的数据,然后更新mysql,更新后等待再次删除redis中的数据
8.redis的缓存问题
数据查询处理流程:前台请求,后台先从缓存中取数据,取到直接返回结果,取不到从数据库中取,数据库取到更新缓存,并返回结果,数据库也没取到,直接返回空结果
穿透:key对应的数据在数据库中并不存在,查询时,redis中也没有此数据,还是要到mysql中去查询,请求都到数剧库从而压垮数据库.比如通过id=-1获取用户信息,不论缓存还是数据库都没有,若黑客利用此漏洞进行攻击可能压垮数据库。
解决方法:
1.在redis设置一对key-null,下次请求时,就可以从缓存中获取-1:null
2.对参数进行校验,不合法参数拦截.例如id=-1,数据库压根就没有这样的值,先进行验证
3.使用布隆过滤器
布隆过滤器:就是一个数组里面默认存储的都是0,主要用来判断某一个元素是否存在,我们可以把数剧向布隆过滤器冗余的进行存放,把一个值用多个哈希函数进行计算,算出多个位置,将对应的位置改为1,判断一个元素是否存在,只需要通过哈希函数算出位置,如果位置上都是1,则元素有可能存在,如果某个位置上的值为0,那么元素一定不存在.
击穿:某个key对应的数据在数据库中存在,在某一个时间节点上key刚好过期了,而且此时有大量的请求同时到达,都去mysql查询,也会击垮mysql.
解决方法:
1.key设置较长的过期时间
2.为查询mysql的方法加锁
雪崩:大量key过期或者redis出现故障,大量请求访问到mysql
解决方法:
1.随机设置key的过期时间,避免大量key集体失效
2.集群部署多台redis主从结构,其中一台怠机了,其他服务还可以用
3.跑定时任务,当key快过期时,更新失效时间