1.Redis概述
- redis是一个内存数据库,以key-value形式存放数据,属于非关系型数据库。
1.1 特点
- redis将数据存储在内存中,读写效率非常高(写入:8w/s 读取:11w/s)
- 包含五种数据类型:string,list,map,set,sortset(注:这里说的数据类型均指的是value的数据类型,key的数据类型固定是string类型)
- String: 和java中string是一样的, 表示就是字符串, redis中没有char
应用场景: 缓存
- String: 和java中string是一样的, 表示就是字符串, redis中没有char
- list: 和java中linkedList对应, list看做是一个双端队列
应用场景: 任务队列 - map: 和java中hashMap类似
应用场景: 缓存(使用较少) - set: 和java中set集合类似
特点: 无序, 去重
应用场景: 去重操作 - sortedset: 有序的set集合 java中sortedset
特点: 有序, 去重
应用场景: 排行榜 - redis可以很方便将数据移植到另一台装有redis数据库的服务器中
- redis操作都是原子性的, 用来保证redis数据的完整性的
1.2 Others
- Redis是单线程的,但是依然很快
- Redis的全量存储和增量存储
- Redis的非阻塞I/O多路复用机制
2.Redis的持久化方案
redis提供了两种持久化的方案: RDB & AOF
- RDB: 以快照机制进行数据的保存, 类似拍照片的形式, 将redis的当前一个状态进行一下保存
- 优点: 快照文件非常的小,适合于灾难恢复
- 缺点: 容易丢失数据,因为快照保存是有时间节点, 占用内存比较大
- AOF: 类似于日志机制, 会将用户输入的操作redis的命令全部的保存下来,放置到本地上
- 优点: 数据保存的比较完整,只会出现极小数据丢失
- 缺点: 日志文件比较大, 不适合灾难恢复
设置RDB: redis默认是开启了RDB
save 900 1 // 15min 如果有一个数据被操作了, 就会执行一下快照
save 300 10 // 5min 如果有10个数据被操作了, 就会执行一下快照
save 60 10000 // 1min 如果有1w个数据被操作了, 就会执行一下快照
以上这三种机制, 满足了哪个,就会马上执行哪个机制
设置AOF:redis默认是关闭的
如何开启 AOF机制
appendonly no // 默认是no,不开启AOF, 设置yes 打开AOF机制
设置aof的保存机制
appendfsync everysec // 每秒保存一次
取值: always everysec no
- always : 总是, 只要有用户进行操作redis数据库, 就会马上的保存下来
- 优点: 基本上不会出现数据丢失的问题
- 缺点: 大大的降低redis的性能
- everysec : 每秒, 每秒钟执行一个保存操作
- 优点: 不会太多的影响Redis的性能
- 缺点: 丢失一秒的数据
注意: 如果没有开启aof, 那么其保存机制也是无效的
一般情况下:开发中redis使用何种持久化机制
- 大型的公司: RDB , 因为有钱
- 中小型的公司: AOF+RDB 或者 AOF
一般放置到redis中的数据, 都是一些不是很重要,但是用户或者其他的服务会经常的使用这些数据。
3. Redis内存淘汰策略
内存淘汰策略:
- noeviction:当内存不足以容纳新写入数据时,新写入操作会报错。
- allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的Key。推荐使用。
- allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个Key。
- volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的Key。这种情况一般是把Redis既当缓存,又做持久化存储的时候才用。不推荐。
- volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个Key。依然不推荐。
- volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的 Key优先移除。不推荐。
4. 缓存雪崩和缓存击穿
4.1 缓存雪崩
- 所谓的缓存雪崩即原本在redis中的缓存数据在同一时间大面积的失效,这个时候又来了一波请求,结果所有的请求都直接访问到数据库中,从而给数据库造成极大的负荷,导致数据库连接异常。
- 解决方法:
- 使用互斥锁,但是该方案会导致数据的吞吐量明显下降
- 给缓存的失效时间加上一个随机值,避免集体同时失效
- 双缓存。我们有两个缓存,缓存A和缓存B。缓存A的失效时间为20分钟,缓存B不设失效时间。自己做缓存预热操作;然后细分以下几个小点:从缓存A读数据库,有则直接返回;A没有数据,直接从B读数据,直接返回,并且异步启动一个更新线程,更新线程同时更新缓存A和缓存B
4.2 缓存击穿
- 用户访问到了redis缓存中不存在的数据,导致其所有的查询都直接去数据库中去了
- 解决方法:
- 利用互斥锁,缓存失效的时候,先去获得锁,得到锁了才能请求数据库。没得到锁,则休眠一段时间重试
- 采用异步更新策略,无论Key是否取到值,都直接返回。Value值中维护一个缓存失效时间,缓存如果过期,异步起一个线程去读数据库,更新缓存。需要做缓存预热(项目启动前,先加载缓存)操作。
- 提供一个能迅速判断请求是否有效的拦截机制,比如,利用布隆过滤器,内部维护一系列合法有效的Key。迅速判断出,请求所携带的Key是否合法有效。如果不合法,则直接返回。