目录
redis高性能,高吞吐量,基于内存,单线程,多路复用io模型非关系型数据库
redis高性能,高吞吐量,基于内存,单线程,多路复用io模型非关系型数据库
1.redis 常用数据结构
单key大小512m
string 字符串
hash 哈希
set 集合
zset 有序集合
list 列表
不常用的三种
位图:用作打卡统计
基础统计:用作页面访问pv uv
地理位置:附近的人
2.redis主从复制原理
当slave节点连接到master后,会像master发送一条指令
master收到指令后,会进行bgsave生成快照,后续操作记录在缓冲区
快照完成后会发送给slave,slave清空磁盘旧数据,并将快照加载到内存,对外提供服务
master再将缓冲区数据发送给slave
后续保持增量同步
***那为什么还需要增量同步呢?求职者:数据同步,slave是定时会发起的,假如每次同步,都把主的所有数据都进行同步,那么性能会很慢,大部分时候,slave可能只跟master相差一部分数据。那么只需要同步这部分数据。slave发起同步的时候,还会带有上次同步的偏移量,然后跟master的最新的偏移量比较,如果相差的数据在master的积压缓存(一个专门存储master最新数据并且会覆盖的内存区间)能查询到的话,那么只需要把相差的数据同步给slave。这就叫做增量同步。指令同步:master输入的指令会异步同步给slave
3.redis持久化机制
1.rdb:快照形式 主动bgsave或被动
2.aof:记录日志 每秒 每次 从不
4.aof重写
缩减文件大小,整理key
触发重写,执行bgrewriteaof命令
主进程fock出一个子进程
子进程创建一个新的aof文件,父进程继续执行读写操作,写操作会写入aof缓冲区和aof重写缓冲区
子进程根据内存快照,按照命令合并规则写入到新的aof文件
新的aof备份完成后,将aof重写缓冲区数据写到新文件中
替换旧的aof 完成aof重写
5.缓存雪崩、缓存穿透、缓存击穿
缓存穿透
缓存或数据库都没有数据
大量请求直接打到数据库
1:最常用的就是布隆过滤器,能快速的得出该数据是否在数据库里,不存在直接返回空
2把查询的空值,直接插入缓存,并设置较小的过期时间
3限流ip 每秒最多访问次数
4接口检验
缓存雪崩,缓存大面积失效,设置不同过期时间
缓存击穿:热数据过期,设置不过期或者续期;查询数据库加同步锁;
6.redis 存储1000w数据 会有什么问题?
1.机器故障:集群
2.过期问题
3.数据结构优化
4.不能影响其他应用
7.安全的分布式锁怎么实现
1)setnx:redis提供的分布式锁
存在问题:线程还没释放锁系统宕机了,造成死锁
2)setnx +setex:给锁设置过期时间,到期自动删除。
存在问题:因为加锁和过期时间设置非原子,存在设置超时时间失败情况,导致死锁
3)set(key,value,nx,px):将setnx+setex变成原子操作
存在问题:加锁和释放锁不是同一个线程的问题。假如线程1业务还没执行完,锁过期释放,线程2获取锁执行,线程1执行完业务删除锁删除的就是线程2的,然后其他线程又可获取锁执行,线程2执行完释放锁删除的是别人的,如此往复,导致并发安全问题。
4.方法1:在value中存入uuid(线程唯一标识),删除锁时判断该标识,同时删除锁需保证原子性,否则还是有删除别人锁问题,可通过lua或者redis事务释放锁
方法2:利用redis提供的第三方类库,Redisson也可解决任务超时,锁自动释放问题。其通过开启另一个服务,后台进程定时检查持有锁的线程是否继续持有锁了,是将锁的生命周期重置到指定时间,即防止线程释放锁之前过期,所以将锁声明周期通过重置延长。
Redission也可解决不可重入问题(AQS,计数)
问题:但上述方案能保证单机系统下的并发访问安全,实际为了保证redis高可用,redis一般会集群部署。单机解决方案会出现锁丢失问题。如线程set值后成功获取锁但主节点还没来得及同步就宕机了,从节点选举成为主节点,没有锁信息,此时其他线程就可以加锁成功,导致并发问题。
Redisson
不仅实现了基于Redis实现加锁,解锁,还提供了防死锁,锁续期5)redis集群解决方案,使用redlock解决: 看门狗机制默认加锁时间30s,每隔10s进行续期
顺序向5个节点请求加锁(5个节点相互独立,没任何关系)
根据超时时间来判断是否要跳过该节点
如果大于等于3节点加锁成功,并且使用时间小于锁有效期,则加锁成功,否则获取锁失败,解锁
*任何一种方案都不是说完美的,都有可能极低概率的出现问题。可以结合业务做幂等性数据处理判断
8.redis为什么这么快
1.基于内存
我们都知道内存读写是比在磁盘快很多的,Redis 基于内存存储实现的数据库,相对于数据存在磁盘的 MySQL 数据库,省去磁盘 I/O的消耗。2.合理的数据结构
sds简单动态的字符串、字典hash O(1)、跳表
3.合理的数据编码
针对不同的数据结构采用合理的数据编码
4.合理的线程模型
单线程避免上下文切换
io多路复用模型:可以让单个线程高效✁处理多个连接请求