Redis
- NoSQL数据库之一
Not Only SQL ,意即“不仅仅是SQL”,泛指非关系型的数据库。NoSQL用于超大规模数
据的存储。(例如谷歌或Facebook每天为他们的用户收集万亿比特的数据)。这些类型
的数据存储不需要固定的模式,无需多余操作就可以横向扩展。
- 基于内存也可持久化日志型
- key-value存储的数据库
- 缓存系统,热点数据:高频渎、低频写
- 计数器
- 消息队列系统
- 排行榜
- 社交网络
- 实时系统
- 基于本机内存的缓存
- 服务端的redis
- 持久化:单台的redis服务器罢工导致所有的缓存丢失,虽然可以把redis服务器重新上线,但是内存的数据丢失会造成缓存雪崩,此时api服务器和数据库的压力会很大。redis持久化是指redis把内存的数据写到硬盘种,在redis重新启动的时候加载这些数据,从而降低影响。
- 哨兵(Sentinel)和复制(Replication):redis服务器突然罢工,如何切换到备份的服务器,如何保证备份的服务器是完整备份。此时就用到了哨兵和复制了。哨兵可管理多个redis服务器,它提供监控,提醒以及自动的故障转移功能;复制是让一个redis服务器可以备份多个备份的服务器。redis是利用这两个功能来保证redis的高可用的。此外,哨兵功能则是对redis的发布和订阅功能的一个利用。
- 集群:通过添加服务器的数量,提供相同的服务,从而让服务器达到一个稳定、高效的状态。
5.什么是缓存穿透?怎么解决?
- 缓存穿透是缓存和数据库种都没有的数据,而用户不断发起请求,大量的并发请求到达数据库,而数据库受不住这么高的并发,从而导致数据库崩溃。
- 将空数据存入缓存:对查询结果为空的情况也进行缓存,缓存时间设置短一点,或者该key对应的数据insert了之后清理缓存。
- 布隆过滤器:将所有的可能存在数据存到一个bitMap种,不存在的数据就会进行拦截。
6.什么是缓存击穿?怎么解决?
- 缓存击穿是指热点key在某个时间点过期的时候,而恰好在这个时间点对这个key有大量的并发请求过来,从而大量的请求到达数据库。
异步更新缓存
- 自动跟新:redis是支持查询某个key剩余有效时间,所以这里我们只需要设定一个时间差,比如3分钟,请求的时候查询的有效时间如果小于3分钟,那么刷新这个key的有效时间,刷新这个操作可以使用异步实现(提高性能)。(不推荐:如果再快失效的3分钟内没有请求,那么缓存中的key将不会被刷新,还是会存在缓存击穿的问题)
- 定时刷新:
第一种:定时任务。查询快要过期的key,更新内容,并刷新有效时间,这种比较消耗服务器性能,也不是特别推荐。
第二种:延迟队列
如果大家了解它的话可能一下就知道我说的是什么意思了,将数据存入缓存的那一刻同时发送一个延迟队列(安指定时间消费),时间小于缓存中key的过期时间,到了指定时间,消费者刷新key的有效时间再发送一个延迟队列,以此循环,这种方式还是不错的,但是实现方式相对于第一种来说就要复杂一点了,他需要依靠消息中间件来完成,如果消息中间件某个时间宕机,那就gg了,虽然这种方式虽然比较推荐,但是成本偏高,因为为了防止消息中间件宕机,我们有可能需要对消息中间件做集群处理。
- 程序加锁:使用锁,单机用synchronized,lock等,分布式用分布式锁。使用分布式锁,保证对于每个Key同时只有一个线程去查询后端的服务,某个线程在查询后端服务的同时,其他线程没有获得分布式锁的权限,需要进行等待。不过在高并发场景下,这种解决方案对于分布式锁的访问压力比较大。
7.什么是缓存雪崩?怎么解决?
- 缓存种的数据大批量到期,而查询数据量巨大,引起数据库的压力,导致数据库宕机
- 缓存大量失效的时候,引发大量查询数据库。
- 用锁/分布式锁或者队列串行访问:在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个 key 只允许一个线程查询数据和写缓存,其他线程等待。
- 缓存失效时间均匀分布:缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生
- 设置热点数据永远不过期:将一些常用的数据设置成为永久有效
8.缓存击穿和缓存穿透区别
- 缓存击穿和缓存穿透有点像但是性质又不相同,都是缓存中没有数据,请求命中数据库,缓存穿透指的是数据库中不存在的数据,缓存击穿则是指缓存失效的问题。
9.缓存雪崩和缓存击穿区别
- 和缓存击穿不同的是, 缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库。
- 读: 读redis->没有,读mysql->把mysql数据写回redis,有的话直接从redis中取;
- 写: 写mysql->成功,再写redis;(并发高:异步话,先写入redis的缓存,就直接返回;定期或特定动作将数据保存到mysql,可以做到多次更新,一次保存;)
11.1.简介
数据存放于:
内存:高效、断电(关机)内存数据会丢失
硬盘:读写速度慢于内存,断电数据不会丢失
11.2.RDB
8月 23 20:26 bin
8月 31 12:09 dump.rdb
8月 23 20:30 redis.conf
RDB:是redis的默认持久化机制。RDB相当于照快照,保存的是一种状态。几十G数据----》几KB快照**
快照是默认的持久化方式。这种方式就是将内存中数据以快照的方式写入到二进制文件中,默认的文件名为dump.rdb。
优点:
快照保存数据极快、还原数据极快,适用于灾难备份
缺点:
小内存机器不适合使用,RDB机制符合要求就会快照
快照条件:
1、服务器正常关闭时 ./bin/redis-cli shutdown
2、key满足一定条件,会进行快照
vim redis.conf 搜索save
:/save
save 900 1 //每900秒(15分钟)至少1个key发生变化,产生快照
save 300 10 //每300秒(5分钟)至少10个key发生变化,产生快照
save 60 10000 //每60秒(1分钟)至少10000个key发生变化,产生快照
11.3.AOF
由于快照方式是在一定间隔时间做一次的,所以如果redis意外down掉的话,就会丢失最后一次快照后的所有修改。如果应用要求不能丢失任何修改的话,可以采用aof持久化方式
Append-only file:aof 比快照方式有更好的持久性,是由于在使用aof持久化方式时,redis会将每一个收到的写命令都通过write 函数追加到文件中(默认是appendonly.aof)。当Redis重启时会通过重新执行文件中保存的写命令来在内存中重建整个数据库的内容。
有三种方式如下(默认是:每秒fsync 一次)
- appendonly yes //启用aof持久化方式
- #appendfsync always //收到写命令就立即写入磁盘,慢慢,但是保证完全的持久化
- appendfsync everysec //每秒钟写入磁盘一次,在性能和持久化方面做了很好的折中
- #appendfsync no //完全依赖os,性能最好,持久化没保证
产生的问题:
aof的方式也同时带来了另一个问题。持久化文件会变的越来越大。例如我们调用 incr test 命令100次,文件中必须保存全部的100条命令,其实有99条都是多余的。