-
为什么使用redis:因为传统的数据库,并不能使用所有的场景,例如秒杀,app首页等瞬时流量高峰,很容易把数据库打崩,所以引用了缓存。目前市面上redis的风评很好,并且很好的支持了spring等框架,所以选择redis。
-
redis 的数据结构:
-
String 底层字符数组
-
Hash
-
List 双向列表,插入块删块,查询慢
-
Set 集合 底层是insert 数组所有元素是整数并且个数小于512 或者 hashtable 底层字典
-
SortedSet(zset) 有序集合 ziplist 或者skiplist
-
-
redis 实现分布式锁
-
使用setnx key value PX time 实现 只有当key不存在时才会创建key,如果key存在则不执行操作
-
使用del key释放锁
-
-
如何取出固定开头的k所有key
-
使用keys命令
-
由于redis是单线程的,所以使用keys命令会阻塞一段时间,导致线上服务停顿。
-
也可以使用scan命令,此命令可以不阻塞的提出指定模式的key,但是会有一定的重复数据
-
-
如何使用redis做异步队列
-
使用list 结构 rpush 生成消息在列表尾部添加消息 lpop key 取出列表数据每次取一个从最开始放进去的开始取(队列),也可以使用 blpop如果列表没有消息则阻塞到,有数据到来
-
使用Pub/Sub 可以实现一次发送多次消费,确点是数据不会持久化,当消费者下线后,生产的消息会丢失。
-
-
如何使用redis实现延时队列
-
使用sortedset 拿时间戳作为score,消息内容作为key来调用zadd生成消息,消费者用zrangebyscore指令获取N次之前的数据轮询进行处理。
-
-
redis数据持久化
-
RDB镜像全量持久化:RDB持久化分为手动触发和自动触发
-
手动触发 save 命令,会阻塞当前Redis服务器,知道持久化完成,对于数据量大的不建议使用
-
自动触发 bgsave 执行bgsave 命令。redis主进程判断当前是否存在在执行的子进程,如果存在这直接返回。如果没有则主进程fork操作创建子进程,在fork过程中会阻塞主进程,当子进程创建完毕后,主进程则不再阻塞,可以响应其他命令。子进程创建RDB文件,根据父进程内存创造临时快照文件,完成后替换原有的文件。并通知父进程表示持久化完成,父进程更新信息。
-
RDB 优点:恢复速度快,适用于数据备份,用于灾难恢复。
-
RDB 缺点:没法做到实时持久化。并且因为bgsave命令每次都会fork线程,频繁执行消耗过高。
-
-
AOF持久化:增量持久化,记录每次写命令,重启时重新执行AOF文件可以恢复数据,解决了数据恢复的实时性问题
-
AOF会把所有的写入命令追加到aof_buf中,因为如果每次都写入磁盘的话,那么性能的磁盘的负载,这样势必会降低性能。aof_buf 同步到磁盘有三种策略
-
1.每次写入都同步磁盘,这样做可以达到数据最高实时性,但是会影响性能,一般不会执行此策略
-
2.每隔一秒同步一次,这样做可能会丢失一秒的数据,单是对性能的影响也很小,一般都会执行此策略达到兼顾数据安全和性能
-
3.不做任何处理,交给操作系统自动去执行,操作系统同步周期不固定,最多可能会有30s的间隔,也就意味着可能会有30s的数据丢失
-
-
AOF文件重写:随着AOF文件的越来越大,需要定期对AOF文件进行重写,达到压缩的目的。具体机制是1.已经过期的key会排出。2.旧文件中无效命令排出。3.将多条写命令合并 如:lpush list a、lpush list b、lpush list c可以转化为:lpush list a b c。AOF重写不仅可以减小文件的大小节省资源,而且换可以在重启时缩短数据加载的时间
-
AOF 重写也分手动触发和自动触发。
-
-
Redis服务重启
-
AOF机制开启并且存在AOF文件时优先加载AOF文件。
-
关闭AOF或者AOF文件不存在时,加载RDB文件
-
加载AOF/RDB文件成功后Redis启动成功
-
-
redis 同步机制:redis的主从结构一般分为一主多从或者级联结构,根据是否全量可以分为全量同步和增量同步
-
全量同步 全量同步一般发生在Slave初始化阶段,这时候Slave需要将master上的所有数据都复制一份。1.从服务器连接主节点,发送SYNC命令;2,主服务器收到SYNC命令后,执行bgsave命令生成RDB快照文件,并使用缓冲区记录此后执行的所有写命令;3.生成完RDB文件后,向从服务器发送快照文件;4.从服务器在接受到快照文件后丢弃所有的旧数据,并且加载主节点发过来的RDB文件;5.主节点发送完RDB文件后开始向从节点发送缓冲区的写命令;6从节点加载完RDB文件后开始接受命令,并且执行主节点发送过来的缓冲区写命令。
-
增量同步 增量同步是指在Slave初始化后开始正常工作时主节点发生的写操作同步到从节点的过程。增量复制的过程主要是主节点每执行一个写命令就会向从节点发送相同的命令,从节点接收命令并且执行。
-
主从同步策略 主从刚连接时,进行全量同步;全量同步后开始正常工作后开始增量同步。不过Slave可以随时向主节点发起全量同步的请求。redis的策略是无论什么时候,首先先进行增量同步如果 不成功在进行全量同步
-
-
redis脑裂 由于网络等原因,导致集群节点失去联系。主从数据不同步;重新平衡选举,产生两个主节点。这样就会导致有两个maser运行,导致数据不一致
-
解决方案:更改配置要求至少有一个slave,数据复制和同步延迟不能超过10s,如果说一旦所有的slave数据复制和同步都超过了10s,那么这时候原先的master就不接受请求了。重新选举新的主节点。等原先的节点回复后在进行同步数据。这样出现脑裂情况最多损失10s的数据。
-
-
redis 为什么这么快?
-
完全基于内存,绝大多数操作都是内存中完成的所以非常快
-
数据结构简单,对数据操作也简单。
-
采用单线程,避免了不必要的线程上下文切换和竞争条件,也不存在多线程之间的竞争导致cup消耗。也不用考虑锁的问题,不存在加锁释放锁,或者出现死锁导致的性能消耗。
-
使用多路i/o复用模型,非阻塞i/o
-
-
缓存雪崩 缓存雪崩是指在同一时间缓存大面积失效,导致请求全部落在数据库上,导致数据库异常,从而导致服务大面积不可用
-
结局方案:1.在批量往redis中存数据时给每个key的失效时间都加上一个随机值,这样就可以保证数据不会在同一时间大面过期。2.如果是集群部署的话,将热点数据均匀的放在不同的redis库中。3.可以将热点数据设置勇不过期,或者长时间不过期,如果数据有更新则更新缓存。
-
-
缓存击穿 缓存击穿是指缓存和数据库都没有的数据,而用用户不断的请求,如果这种请求量特别大的话会导致数据库不可用,从而导致服务瘫痪。
-
1.首先在接口层面校验参数,如果参数不合法直接返回。
-
2.可以将不存在的数据缓存为null,并且缓存失效时间设置短一些,这样可以避免不存在请求一直打到数据库上。
-
网关层可以配置每个ip同一时间内限制访问次数。
-
布隆过滤器:当一个元素被假如集合后,通过k个散列函数将这个元素映射成一个位数组中的k个点,把这些点设置成1,检索时我们只要判断 这些点都是不是1,如果是1的话就证明可能存在(因为存在hash冲突)。如果这些点中有一个不存在就说明这个元素肯定不存在。
-
-
缓存穿透 缓存击穿指的是一个key非常热点,在不停的高并发请求,当这个key失效的一瞬间,在持续的高并发请求就会将请求打到数据库,从 而导致数据库不可用,导致服务瘫痪。
-
设置热点数据永不过期
-
添加本地缓存
-
添加互斥锁,在缓存失效后请求接口处添加互斥锁,其他请求过来拿不到锁则等会在拿一次。
-
-
redis哨兵 哨兵模式是一种特殊的模式,redis提供了哨兵命令,哨兵是一个独立的进程,作为进程他会独立运行。其原理是哨兵通过发送命令,等待redis服务响应,从而监控多个reids实例
-
集群监控:负责监控redis master 和slave 之间是否正常工作
-
消息通知:如果某个redis实例有故障,那么哨兵负责报警通知管理员
-
故障转换:如果master出现故障,则通过哨兵将重新选举master
-
配置中心:如果故障转移发生了,通知client客户端新的master地址
-
-
过期策略
-
定期删除 默认100ms去随机检查一些设置了过期时间的key,检查是否过期,如果过期了就删除
-
惰性删除 查询时在检查是否过期,如果过期了就不返回,并且删除key
-
内存淘汰机制:1.内存限制机制 当达到内存设置值时删除2.lru 尝试回收最少使用的key(分两种一种是直接回收,一种是仅限在过期的集合中回收) 3.回收随机的key(分两种一种是直接回收,一种是仅限在过期的机器和中回收)4.回收在过期集合内的键。
-
-
一致性 hash 算法
-
一致性 hash 算法将整个 hash 值空间组织成一个虚拟的圆环,整个空间按顺时针方向组织,下一步将各个 master 节点(使用服务器的 ip 或主机名)进行 hash。这样就能确定每个节点在其哈希环上的位置。
-
来了一个 key,首先计算 hash 值,并确定此数据在环上的位置,从此位置沿环顺时针“行走”,遇到的第一个 master 节点就是 key 所在位置。
-
在一致性哈希算法中,如果一个节点挂了,受影响的数据仅仅是此节点到环空间前一个节点(沿着逆时针方向行走遇到的第一个节点)之间的数据,其它不受影响。增加一个节点也同理。
-
燃鹅,一致性哈希算法在节点太少时,容易因为节点分布不均匀而造成缓存热点的问题。为了解决这种热点问题,一致性 hash 算法引入了虚拟节点机制,即对每一个节点计算多个 hash,每个计算结果位置都放置一个虚拟节点。这样就实现了数据的均匀分布,负载均衡。
-
redis cluster 的 hash slot 算法
-
redis cluster 有固定的 16384 个 hash slot,对每个 key 计算 CRC16 值,然后对 16384 取模,可以获取 key 对应的 hash slot。
-
redis cluster 中每个 master 都会持有部分 slot,比如有 3 个 master,那么可能每个 master 持有 5000 多个 hash slot。hash slot 让 node 的增加和移除很简单,增加一个 master,就将其他 master 的 hash slot 移动部分过去,减少一个 master,就将它的 hash slot 移动到其他 master 上去。移动 hash slot 的成本是非常低的。客户端的 api,可以对指定的数据,让他们走同一个 hash slot,通过 hash tag 来实现。
-