中间件:
Redis:
高性能k-v数据库,在内存运行,也可以持久化到磁盘,单线程单进程KV数据库。
支持的数据结构和底层实现:
类型 | 用法 | 实现 |
String | set key value | 最大512M |
Hash(k-v集合) | hmset name key1 val1 key2 val2 | 适合存储对象 |
List(有序列表,按插入顺序排序) | lpush/rpush name value | |
SET(无序集合) | sadd name value | |
zset(有序集合) | zadd name score value每个元素都会关联一个分数,按分数排序 |
REDIS主从实现原理:
主节点负责写,从节点负责读。
从节点发现主节点信息,建立socket链接,主节点将所有数据发送给从节点,完成初次全量同步,如果master有写命令,进行命令传播,保持主从一致性。
slave断开重连会进行同步,判断master id是否跟自己记录的一样,如果不一样就进行完整同步,如果一样就判断主从偏移量是否一致,如果不一致就进行部分重新同步,如果一样就直接结束。
分块分表:
分区是分割数据到多个redis实例的处理过程,因此每个实例保存key的一个子集。
如果只使用一个redis实例时,其中保存了服务器中全部的缓存数据,这样会有很大风险,如果单台redis服务宕机了将会影响到整个服务。解决的方法就是采用分片/分区的技术,将原来一台服务器维护的整个缓存,现在换为由多台服务器共同维护内存空间。
Redis Cluster 使用分片机制,在内部分为16384各slot插槽,分布在所有的master节点上,每个master节点负责一部分slot,数据操作时通过crc16的hash函数来对key进行取模,将结果路由到预先分配过slot相应节点上。
redis怎么实现高并发:
1、Redis是基于内存的,内存的读写速度非常快;
2、Redis是单线程的,省去很多上下文切换线程的时间;
3、Redis使用多路复用,可以处理并发的连接,非阻塞IO内部实现epoll,采用epoll+自己实现的简单的事件框架。epoll中的读、写、关闭、连接都转化为事件,然后利用epoll的多路复用特性,绝不在io上浪费一点时间。
redis持久化机制:
redis一般把数据缓存在内存里,但是会周期性的把更新的数据写入磁盘
两种持久化策略:
RDB:快照形式,直接把内存dump,Redis需要做持久化时,会fork一个子进程,子进程将数据写到临时RDB表里,写完再替换,实现COW;适合冷备,每5分钟生成一次;
AOF:把对服务器修改的命令都放到文件里;每一个写命令都追加到aof文件里,redis重启时会直接根据AOF指定进行恢复,适合热备,1秒1次fsync。
redis缓存雪崩,缓存穿透,缓存击穿,如何解决雪崩问题:
缓存雪崩:redis宕机或者大量key失效,同时又有大量请求打进来,DB撑不住;
1、设置不同的过期时间,防止同时失效
2、搭建高可用redis集群
3、设置多级缓存
缓存击穿:一个key非常热点,扛大量请求,然后再某一个时间点过期,恰好这个时间点对这个key有大量请求过来,这些请求发现缓存过期时会从后台DB加载数据并回到缓存,把DB压垮。
解法:热点数据永不过期(物理不过期,逻辑不过期;当发现要过期了通过后台异步进程进行缓存重建)或者加上互斥锁。
缓存穿透:用户大量请求在缓存和DB中查不到,导致数据不存在也会大量查DB
解法:DB查不到也写在缓存里,或使用布隆过滤器(类似一个hashset,可以快速查找某个KEY是否在数据库存在)。
Redis过期策略:
1、定期删除:100ms随机抽一些设置了过期时间的删除
2、惰性删除:等查询了再看过期没,过期了就删除
Redis的淘汰策略:
设置过期时间:LRU:最近最少使用,TTL:淘汰剩余时间短的;Random:随机淘汰。
所有K-V:Random随机淘汰。
Redis分布式锁的实现:
假设有5个redis节点,这些节点之间既没有主从,也没有集群关系。客户端用相同的key和随机值在5个节点上请求锁,请求锁的超时时间应小于锁自动释放的时间。当在3个(超过半数)redis上请求到锁的时候,才算是真正获取到了锁。如果没有获取到锁,则把部分已锁的redis释放掉。
如何解决redis分布式锁过期时间到了业务没执行完问题:
思路一:任务执行的时候,开辟一个守护线程,在守护线程中每隔一段时间重新设置过期时间。
思路二:通过Redisson中的看门狗来实现,在Redisson实例被关闭前,不断延长锁的有效期,默认30秒。
Redis重新分配哈希值:
系统自动化当前各主节点中拿出一定数量的哈希槽,转义至新的主节点中,以达到哈希槽平衡。
Redis快的原因:
基于内存操作,数据结构简单,避免上下文切换和竞争关系,多路复用和非阻塞IO:使用多路复用来监听多个socket连接客户端。
高可用:
主从复制+哨兵模式(3个)
哨兵集群:集群监控:监控Master/Slave是否正常工作;消息通知:某个Redis故障,报警给管理员;master node挂了自动转移给slave;配置中心:通知client新的master。
通过Sentine哨兵来监控Redis主服务器的状态。当主挂掉时,在从节点中根据一定策略选出新主,并调整其他从slave到新主。
选主的的策略简单来说有三个:
1、slave的priority设置的越低,优先级越高;
2、同等情况下,slave复制的数据越多优先级越高;
3、相同的条件下runid越小越容易被选中。
在Redis集群中,sentinel也会进行多实例部署,sentinel之间通过Raft协议来保证自身的高可用。