(八)其他组件(redis、zk、dubbo、MQ、ES)

1、redis

redis缓存优势:redis数据结构⽐memcached更丰富,基本可以完全替换

        redis社区⽐较活跃,性能也强⼤,也⽀持持久化等功能

       结合业务,⽐如常用商品排序用到了有序集合zset

常用结构:String:key-value、hash:存储对象,⼀个key有多个值、list:列表型数据,消息队列等、set:⽆序集合、去重,交集、并集等,⽐如查看共同好友,在社交关系⽅⾯、数据排重等、sroted set:有序集合,去重,做榜单

redis是单线程:基于内存,绝⼤部分请求是纯粹的内存操作,CPU不是Redis的瓶颈,所以单线程就可以,避免了不必要的CPU上下⽂切换和其他竞争条件,⽐如锁操作等;底层是使⽤多路I/O复⽤模型,⾮阻塞IO;Redis6 后⽀持多线程,但是默认不开启;

持久化⽅式:⽀持AOF和RDB持久化

  AOF:以⽇志的形式记录写、删除操作,没有查询操作,以⽂本记录, ⽀持秒级持久化、兼容性好;AOF⽂件通常要⼤于RDB⽂ 件,所以恢复⽐RDB慢;

  RDB:以指定的时间间隔 将内存中的数据集快照写⼊磁盘,但不能做到实时持久化;⽂件紧凑,体积⼩,RDB在恢复速度⽐AOF的恢复速度要快;

3.2、redis淘汰机制

先进先出First In,First Out:插入队尾,淘汰队首;新访问的数据插⼊FIFO队列尾部,数据在FIFO队列中顺序移动,淘汰FIFO队列头部的数据;

最近最少使⽤ Least recently used:插入队首,淘汰队尾;如果数据最近被访问过,那么将来被访问的⼏率也更⾼;每当缓存数据被访问,则将数据移到链表头部,当链表满的时候,将链表尾部的数据丢弃。

最近不经常使⽤ Least Frequently Used:记录数据频率,按频率排序;根据数据的历史访问频率来淘汰数据,如果数据过去被访问多次,那么将来被访问的频 率也更⾼;把数据加⼊到链表中,按频次排序,⼀个数据被访问过,把它的频次+1,发⽣淘汰的时 候,把频次低的淘汰掉;

3.3、缓存击穿/雪崩

缓存击穿 :缓存过期,缓存中没有但数据库中有的数据;若是热点数据大量访问去查数据库,DB会瞬间压力增大;单一key出现过期;数据不过期/定时刷缓存/首次访问 加锁后续线程循环sleep请求 重刷到缓存;

缓存穿透:查询不存在数据,缓存中没有,去查数据库,导致DB压力大,比如查ID为-1000.到-1的数据;校验数据合理性/缓存存下key-null数据防止二次;

缓存雪崩:多个key出现过期,导致DB瞬间压力大;随机过期时间/定时刷数据/热点永不过期;

 

优势:数据类型多String、hash、list、set、zset,通过redisObject直接存储;持久化AOF/RDB-默认RDB配置appendonly,RDB可手/自持久化,主流AOF;单线程纯内存操作 速度快;

淘汰策略:先进先出、最近最少使用、最近最不经常使用;

并发问题:redis是C语言开发的,单线程,采用队列 将并发访问变为队列串行;纯内存操作,cpu不是瓶颈,没有上下文切换和资源竞争,也不存在加锁;

分布式锁:        

异步队列:list,lpush+lpop+sleep/blpop,

持久化:RDBSave/BGSAVE/RDBLoad;AOF的flush方法;redis序列化协议--客户端+服务器,规定格式请求,执行完毕返回结果;+回复-错误*数组等5种;

集群:单机/  主从复制--没有降低主库写压力/  哨兵--监控心跳-故障切换慢会丢失/代理/cluster-无主节点;

redis内存模型:内存分配器,分配总内存,线程内存,内存碎片比率;

实际操作:redis-server;redis-cli+keys/scan/del/exists;treeNMS-占用率/连接数/增删改查;配置文件名称、目录、开启AOF、持久化策略等;Incr一个int报错/1/++1;

新特性:Pub/Sub发布订阅-两个client;Bloom过滤-存在错误/位图数组同样k个hash函数更新1或查1判断;RedisSearch-索引+文档/安装配置,对中文不好;aof定期重写压缩,aof与bgsave混合写;同步磁盘策略;

redis实现原理:字典-字典type/hash/index-字典表size/isused-数据索引表-数据; redis单线程+队列+发配给处理器;  过期处理:定期-每100MS随机抽删除+惰性-请求时判断过期删除;  set+eval;

  redis集群:ruby环境,大等于6个redis,安装gem包,6节点配置port和集群true,redis-trib的create命令启动;分数据分片0-16383;新节点,不均衡,节点下线,分片迁移;通过meet命令相互通信创建stateNode节点等;  redis单线程原子性;语法命令错误才会回滚;半支持事务;  不同key不同槽;

  数据一致性:设置超时时间;定时去刷数据;canal伪装成从库去获取binlog;

 

1.1、常用MQ

MQ优点:解耦系统、异步化、削峰        缺点:系统可⽤性降低、复杂度增⾼、维护成本增⾼

ActiveMQ:历史悠久,⽀持多种语⾔的客户端和协议,⽀持多种语⾔    吞吐量不⾼,多队列性能低,存在消息丢失,较少使用

Kafka:⾼吞吐量,分布式发布订阅消息,数据较少丢失,⽀持多个⽣产者和消费者,常用于大数据平台;  不⽀持批量和⼴播,⽂档⽐较少, 运维难度⼤,需要掌握Scala

RabbitMQ:Erlang语⾔编写,易⽤性、扩展性、⾼可⽤性等⽅⾯表现不错    源码不容易被掌握

RocketMQ:纯Java开发,具有⾼吞吐量、⾼可⽤性、适合⼤规模分布式系统,⽀持海量堆积, ⽀持指定次数和时间间隔的 失败消息重发,⽀持consumer端tag过滤、延迟消息  新组件资料较少

1.2、发送方式

SYNC同步发送:短信、邮件

ASYNC异步发送:回调成功触发后续流程,下单通知到ERP系统

ONEWAY⽆需要等待响应:耗时短可靠性低,收集日志、操作习惯等

⽅式

发送 TPS

结果

靠性

发送

丢失

发送

丢失

发送

最快

延迟消息:Producer将消息发送到消息队列 broker,不希望马上消费,而是等待某个时间点后销消费;--路由信息到上班节点发送

1.3、顺序性、避免重复消费、可靠性

顺序性:消息生产与消费顺序一致;全局有序(较少使用)/局部有序(一组数据被顺序消费,性能高);--订单路由信息;

  原理:顺序生产:⼀个topic下⾯有多个queue队列,同个业务id放置到同个queue队列⾥;

     顺序消费:使⽤MessageListenerOrderly单线程消费,集群消费时锁住正在消费的消息队列;而不是使用多线程的MessageListenerConcurrently消费;

  无法广播,无法异步否则无法严格保持顺序,不能多线程;

避免重复消费:业务实现,redis去重(消息ID,setNX()存在/Incr自增1存在),数据库设计去重表(消息ID做唯一索引)

  幂等性:⼀个请求,不管重复来多少次,结果是不会改变的

可靠性:producer端:不采⽤oneway,使⽤同步或者异步⽅式;做好重试,但是重试的Message key必须唯⼀;保存关键日志信息(关键字段,投递时间、投递状态、重试次数、请求体、响应体);

    broker端:多主多从架构,多机房;同步双写、异步刷盘 (同步刷盘消息不丢失,可靠性更⾼,但是性能差点,根据业务选择) ;

    consumer端:处理完消息后,调⽤ack告诉消息队列消费成功;幂等性处理;保存消费日志信息;

 

1.4、消息堆积(恢复消费/更快速度去消费,需要4步)

  1、Consumer不消费问题:若不消费,则使其恢复正常消费,根据业务需要看是否要暂停;

  2、增加Consumer数量:临时topic队列扩容,并提⾼消费者能⼒,增加Consumer节点;

  3、临时分发程序:若堆积仍多且数量固定,则从旧topic读取到临时新topic中,新topic的queue数量必须扩容多倍,多个Consumer节点快速消费;--一般queue数量要大于Consumer节点数量

  4、堆积消息处理完成后,恢复正常数量,再次检查逻辑或服务;

1.5、延迟发送,二次确认

 

broker中有多个不同topic分片,每个分片中有多个同一topic的queue;  topic在每个broker中都有1个分片,分片中有多个queue;

NameServer-路由注册中心,Broker-消息存储服务器;  Broker每30S心跳到NameServer;NameServer每10s清除120s心跳Broker,更新topic的路由信息;Producer每30s去获取路由信息;

broker中保存 提交日志文件、磁盘索引文件、消息消费队列;

重复问题:消息重新发送、消费异常;消费进度本身的不及时;拉取异常后的重新拉取;

MQ的ack机制:重新投递retrytopic,重试多次到死信队列;以group+queue来管理offset消费进度;拉取消费组,从尾/首/某时间点开始消费,只回传最小offset值;卡必消费成功位置;

 

 

节点node-索引index-分片shard/type-文件document

写流程:选择某node节点发送请求,节点会根据路由算法转发到主分片,主分片处理完毕再同步备份分片; 路由算法shard=hash(routing) %取余数 number_of_primary_shards索引下主分片数量

  原理-近实时搜索refresh是:先写到内存中,同时写translog;每隔1s读取内存创建新阶段,新阶段先写入缓存,再写入磁盘;缓存数据可以直接被查询;flush实现磁盘持久化;

读流程:类似上述流程,只是读是会在 主分片 和 备份分片 之间随机轮训的去读取;

lucene:倒序索引算法;一词对应多文档;字典顺序生序;

translog:事务日志,针对的缓存与内存数据;flush持久化时清空,建磁盘+1log文件;索引文件和日志文件各有一份,冗余;  事务数,偏移量,log号;

 

 

 

1、高并发系统-系统拆分、用redis缓存、MQ交互、分库分表、读写分离、ES

分布式锁:数据库锁方法名建唯一索引;redis的set的key-value-expire,key是业务方法的,value是当前线程单据,解锁时判断value;

2、亿级数据查询

数据库--建立索引,存储过程,

  分库-因表多而数据多,根据业务模块,将库拆分成不同的数据库;

  分表-单表数据多,拆分表,垂直拆分--拆分字段;水平拆分--按业务按年月去拆分,按照面试官说的业务去拆,mycat中间件;

缓存--使用redis,

搜索引擎--使用ES,canal来伪装成从库线程读取binlog更新ES

3、netty

NIO:IO多路复用/非阻塞IO,用一个线程兼容做下述3件事情;BIO-Accept连接请求、读操作请求、写操作请求,都会等待阻塞;

Netty:网络应用框架;封装了JDK的NIO,提供了高性能的客户端与服务器端;Accept连接请求是一个线程,读写操作请求是另一个线程;

Dubbo的服务提供者、消费者和性能统计节点之间使用 Netty 进行异步/同步通信; RocketMQ 的消息生产者和消息消费者之间也采用 Netty 进行高性能、异步通信;

 

 

zab:恢复模式与广播模式;

zk选举流程和同步策略:初始流程-服务器LOOKING状态下,每个服务投票vote(sid, ZID)和自己的self()比较,先value后key取大发出去;Leader变Leading,Follower变Following状态;  新节点/宕机不影响,leader挂了才影响会重选;非观察者全转LOOKING状态;  初始轮次+投票,接收投票 轮次和pk票,变更投票 统计,更改状态;  Observer不参与投票和事务提交,提高读性能;

zk基于zab:过半机制+leader提交事务广播到所有follower;quorumPeer.start()磁盘读数据+上下文+选举;run方法有makeLeader()创建;leader.lead()创建StateSummary标记最新事务和提交次数+与Learner单线程长连接+LearnerHander监控新节点;followLeader方法-Follower.registerWithLeader()建立长链接5次+syncWithLeader()去同步数据-清空/删除无效;

 

TCP4层:网络接口层(物理+数据链路)、网际层、传输层(tcp、udp)、应用层(+会话+表示);

rpc远程调用的服务治理框架;节点间的服务请求;客户端将参数转字节流传给服务端操作再返回结果,涉及到序列化等问题;  SOA思想-一个中心同一规范去处理或监控多个系统;

默认dubbo协议,支持http、hessian等协议;以zk、redis做注册中心;已经停止更新;  spring-cloud以Eureka注册中心,仅支持http;  通信框架是netty框架;

Hessian:基于http-post,类似于http+自己的序列化,它着重数据仅带简单类型标记,文件小;java序列化-数据、类、继承关系等全部字节流序列化;

默认重试2次;tries+timeout+服务端处理业务;

dubbo原理:解析服务-类似Spring加载bean到容器,解析xml中dubbo标签加载成bean对象转化成url的参数传给protocol节点;暴露服务-通过RegistryProtocol类的export方法先将ip端口+url传到注册中心,再同步到protocol节点暴露服务;引用服务-通过RegistryProtocol的refer查询url并获得提供者引用;消费节点的zkRegistry的saveProperties会缓存全量URL,新服务不行;消费-通过ReferenceConfig的init方法调refer方法生成invoke实例来获取接口;

  负载均衡:实现loadbalance接口继承*类,doselect方法,getWeight获取权重方法;随机数/轮训次数/活跃度数组等;

dubbo生产消费,通过xml中,配置retries 再重试次数/cluster 失败后操作-failfast报错、failsafe忽略等实现容错;

           配置loadbalance实现负载均衡等,默认romdom随机,基本没人修改,还有 权重轮训/hash/最小活跃等;

容错与负载均衡:权重随机-大量均匀/轮训-慢服务卡积累/最小活跃数-调用前后计差越慢越靠后越少/一致性hash-参数一致调同台 服务挂掉去平分;

  失败切换-查,失败报错-写;失败忽略;并行调用等单返回;retries/Cluster/forks/LoadBalance

  

标签:reference id声明服务;service ref引用服务;protocol 协议声明;application应用声明;provider超时声明;

监控:dubbo-admin,可视化页面搜索服务,查看生产消费者信息;

 常见问题:No provider available/check registry--服务提供者挂了,或者version没对应上;启动时检查依赖可用,否则报错;Data length too large--返回数据太大,加条件而不是改payload;父子类同名变量覆盖--Hessian去重;

 

posted on 2021-05-08 10:20  奇天异下  阅读(923)  评论(0编辑  收藏  举报

导航