Redis学习
Redis是开源的,高性能的key-value数据库。支持持久化,将内存数据保存至磁盘。支持数据备份,master-slave模式。
1. 数据结构
redis数据结构包括String Hash List Set ZSet
-
String字符串
语法SET key value; GET key -
Hash哈希
HMSET key field1 value1 [field2 value2 ]同时插入多个值域数据到指定key下
HSET key field value插入一条数据到指定key
HMGET key field1 [field2]获取指定字段对应的值
HGETALL key 获取指定key所有字段和值 -
List 字符串列表
LPUSH key value1 [value2]插入多个字符串
LINDEX key index根据索引获取字符串 -
Set无序集合,不能出现重复的数据。
SADD key member1 [member2]
SREM key member1 [member2] -
Zset有序集合和集合一样也是 string 类型元素的集合,且不允许重复的成员
ZADD key score1 member1 [score2 member2]
ZREM key member [member …]
应用场景:
String:缓存,限流,计数器,分布式锁,分布式Session
Hash:储存用户信息,用户主页访问量,组合查询
List:微博关注人时间轴列表,简单队列
Set:赞,踩,标签,好友关系
Zset:排行榜
2. 高可用
redis高可用方案
```f
- 2.1读写分离,主从复制
避免单独redis服务器宕机数据丢失,需要多台备份服务器,形成一主多从模式。
![在这里插入图片描述](https://img-blog.csdnimg.cn/a1dc3ac3625f484a9be81499c09a612c.png)
主服务器负责写操作,并且同步给从服务器,从服务器负责读取数据。主从直见数据同步可分为三个阶段如下图:
![在这里插入图片描述](https://img-blog.csdnimg.cn/f1472374e556414884db1877176647dd.png)
- 2.2 sentinal哨兵
主从复制,当redis主服务器突发宕机,需要手动切换一台从服务器为主服务器,需要人工操作,同时在进行切换的操作过程中,客户端无法对原主服务器进行写入操作。sentinal可以解决手动切换的问题,系统自动判断操作处理。当主服务器宕机sentinal检测到会切换另一个从服务器当主服务器继续进行写操作。
- 2.3 集群
redis集群是3.0版本之后引进的
- 所有的redis节点彼此互联(ping-pong机制),内部使用二进制协议优化传输速度和带宽。
节点的fail是通过集群中超过半数的节点检测失效时才生效。
客户端与redis节点直连,不需要中间代理层,客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可。
#### 3. 缓存雪崩 击穿 穿透
- 雪崩
- ![在这里插入图片描述](https://img-blog.csdnimg.cn/e0aca994087340eebae52eaeed3e8518.png)
描述:大量的热点数据过期时间相同,导致数据在同一时刻集体失效。造成瞬时数据库请求量大、压力骤增,引起雪崩,导致数据库存在被打挂的风险。
解决方案:1.将热点数据的过期时间打散。给热点数据设置过期时间时加个随机值。
2.加互斥锁。当热点key过期后,大量的请求涌入时,只有第一个请求能获取锁并阻塞,此时该请求查询数据库,并将查询结果写入redis后释放锁。后续的请求直接走缓存。
3.设置缓存不过期或者后台有线程一直给热点数据续期。
- 击穿
![在这里插入图片描述](https://img-blog.csdnimg.cn/c92598a33cdb410dbc2954f7352b7448.png)
描述:某个热点 key,在缓存过期的一瞬间,同时有大量的请求打进来,由于此时缓存过期了,所以请求最终都会走到数据库,造成瞬时数据库请求量大、压力骤增,导致数据库存在被打挂的风险。
方案:1.加互斥锁。当热点key过期后,大量的请求涌入时,只有第一个请求能获取锁并阻塞,此时该请求查询数据库,并将查询结果写入redis后释放锁。后续的请求直接走缓存。
2.设置缓存不过期或者后台有线程一直给热点数据续期。
- 穿透
![在这里插入图片描述](https://img-blog.csdnimg.cn/099a0ca1a43741629c99f13f96ce4127.png)
描述:访问数据库和缓存都不存在的数据,同一时间多个用户请求不存在的数据就会大量访问数据库层,缓存根本起不到任何作用,就像被穿透了一样,数据库可能面临宕机风险。
解决方案 : 1.添加参数校验
我刚入职的时候,我的老大就跟我说过,作为一名后端开发工程师,不要相信前端传来的东西,所以数据一定要在后端进行校验。我们可以在接口层添加校验,不合法的直接返回即可,没必要做后续的操作。
2.缓存空值
上面我们也介绍了,之所以会发生穿透,就是因为缓存中没有存储这些空数据的key。从而导致每次查询都到数据库去了。
那么我们就可以为这些key 设置的值设置为null 丢到缓存里面去。后面再出现查询这个key 的请求的时候,直接返回null ,就不用在到 数据库中去走一圈了。但是别忘了设置过期时间。
3 布隆过滤器
redis的一个高级用法就是使用布隆过滤器(Bloom Filter),BloomFilter 类似于一个hase set 用来判断某个元素(key)是否存在于某个集合中。这个也能很好的防止缓存穿透的发生,他的原理也很简单就是利用高效的数据结构和算法快速判断出你这个Key是否在数据库中存在,不存在你return就好了,存在你就去查了DB刷新KV再return。
### Redis锁
乐观锁:watch + 事务(multi/exec)
悲观锁: jvm锁 sychronized reecentlock **只适合单机服务**
分布式锁 :redis/zookeeper
redis实现分布式锁(key唯一):
1、手动实现分布式锁setnx del redlock
2、 第三方框架redisson分布式锁
zookeeper分布式锁(znode唯一)
1.创建不能重复的临时节点 处理完业务 删除节点(独占排他锁)
2.第三方框架curator
mysql实现分布式锁(添加唯一索引)
1.加锁 insert lock_db values('lock') 同一时间只有一个客户端执行成功 唯一索引
2.释放锁 删除插入的记录
3.重试 递归
### Redis持久化
redis支持数据持久化操作
RDB:
在指定时间进行数据快照保存,以二进制格式写入默认的dump.rdb文件中
rdb有三种触发机制,save、bgSave、在redis.confg配置自动化
save不推荐使用,redis是单线程的,一次save操作会阻塞其他客户端操作redis
bgsave不会阻塞客户端的请求,redis利用fork子进程处理持久化操作,redis主进程继续为客户端提供响应处理。
上面两种save/bgsave都需要在客户端手动操作命令执行,在生产环境下一般都要自动触发建议配置redis.config自动化,指定备份的频率
RDB的优势:文件以二进制存储较小,恢复数据比AOF要快,可以恢复到指定的时间版本
RDB的不足:如果业务上需要尽量避免在服务器故障时丢失数据,那么 RDB 并不适合,因为rdb备份至少也需要5分钟保存一次数据,那么可能会丢失最近几分钟数据。
AOF:
aof存储的是客户端操作的有序指令,且只保存对内存修改的指令记录
优势:AOF 持久化的默认策略为每秒钟 fsync 一次,在这种配置下,Redis 仍然可以保持良好的性能,并且就算发生故障停机,也最多也只会丢失掉一秒钟内的数据;
不足:对于相同的数据集来说,AOF 文件的体积通常要大于 RDB 文件的体积。
根据所使用的 fsync 策略,AOF 的速度可能会慢于 RDB