7.3.1、分区规则
常见的分区规则
节点取余:hash(key) % N
一致性哈希:一致性哈希环
虚拟槽哈希:CRC16[key] & 16383
RedisCluster采用了虚拟槽分区方式,具题的实现细节如下:
1、采用去中心化的思想,它使用虚拟槽solt分区覆盖到所有节点上,取数据一样的流程,节点之间使用轻量协议通信Gossip来减少带宽占用所以性能很高,
2、自动实现负载均衡与高可用,自动实现failover并且支持动态扩展,官方已经玩到可以1000个节点 实现的复杂度低。
3、每个Master也需要配置主从,并且内部也是采用哨兵模式,如果有半数节点发现某个异常节点会共同决定更改异常节点的状态。
4、如果集群中的master没有slave节点,则master挂掉后整个集群就会进入fail状态,因为集群的slot映射不完整。如果集群超过半数以上的master挂掉,集群都会进入fail状态。
5、官方推荐 集群部署至少要3台以上的master节点。
8、Redis 限流
经常乘坐北京西二旗地铁或者在北京西站乘坐的时候经常会遇到一种情况就是如果人很多,地铁的工作人员拿个小牌前面一档让你等会儿再检票,这就是实际生活应对人流量巨大的措施。
在开发高并发系统时,有三把利器用来保护系统:缓存、降级和限流。那么何为限流呢?顾名思义,限流就是限制流量,就像你宽带包了1个G的流量,用完了就没了。通过限流,我们可以很好地控制系统的qps,从而达到保护系统的目的。
1、基于Redis的setnx、zset
1.2、setnx
比如我们需要在10秒内限定20个请求,那么我们在setnx的时候可以设置过期时间10,当请求的setnx数量达到20时候即达到了限流效果。
缺点:比如当统计1-10秒的时候,无法统计2-11秒之内,如果需要统计N秒内的M个请求,那么我们的Redis中需要保持N个key等等问题。
1.3、zset
其实限流涉及的最主要的就是滑动窗口,上面也提到1-10怎么变成2-11。其实也就是起始值和末端值都各+1即可。我们可以将请求打造成一个zset数组,当每一次请求进来的时候,value保持唯一,可以用UUID生成,而score可以用当前时间戳表示,因为score我们可以用来计算当前时间戳之内有多少的请求数量。而zset数据结构也提供了range方法让我们可以很轻易的获取到2个时间戳内有多少请求,
缺点:就是zset的数据结构会越来越大。
2、漏桶算法
漏桶算法思路:把水比作是请求,漏桶比作是系统处理能力极限,水先进入到漏桶里,漏桶里的水按一定速率流出,当流出的速率小于流入的速率时,由于漏桶容量有限,后续进入的水直接溢出(拒绝请求),以此实现限流。
3、令牌桶算法
令牌桶算法的原理:可以理解成医院的挂号看病,只有拿到号以后才可以进行诊病。
细节流程大致:
1、所有的请求在处理之前都需要拿到一个可用的令牌才会被处理。
2、根据限流大小,设置按照一定的速率往桶里添加令牌。
3、设置桶最大可容纳值,当桶满时新添加的令牌就被丢弃或者拒绝。
4、请求达到后首先要获取令牌桶中的令牌,拿着令牌才可以进行其他的业务逻辑,处理完业务逻辑之后,将令牌直接删除。
5、令牌桶有最低限额,当桶中的令牌达到最低限额的时候,请求处理完之后将不会删除令牌,以此保证足够的限流。
工程化:
1、自定义注解、aop、Redis + Lua 实现限流。
2、推荐 guava 的RateLimiter实现。
9、常见知识点
字符串模糊查询时用Keys可能导致线程阻塞,尽量用scan指令进行无阻塞的取出数据然后去重下即可。
多个操作的情况下记得用pipeLine把所有的命令一次发过去,避免频繁的发送、接收带来的网络开销,提升性能。
bigkeys可以扫描redis中的大key,底层是使用scan命令去遍历所有的键,对每个键根据其类型执行STRLEN、LLEN、SCARD、HLEN、ZCARD这些命令获取其长度或者元素个数。缺陷是线上试用并且个数多不一定空间大,
线上应用记得开启Redis慢查询日志哦,基本思路跟MySQL类似。
Redis中因为内存分配策略跟增删数据是会导致内存碎片,你可以重启服务也可以执行activedefrag yes进行内存重新整理来解决此问题。
1、Ratio >1 表明有内存碎片,越大表明越多严重。
2、Ratio < 1 表明正在使用虚拟内存,虚拟内存其实就是硬盘,性能比内存低得多,这是应该增强机器的内存以提高性能。
3、一般来说,mem_fragmentation_ratio的数值在1 ~ 1.5之间是比较健康的。
10、End