最近学习了一些中间件,Redis,MQ等,简要整理下以便回顾,复习使用.
MQ
- 为什么要使用MQ: 解耦,异步,削峰.
- 解耦: 如客服系统利用MQ发布订阅模型,监听MQ消息处理,不需要关心其他系统调用是否成功或超市,其他系统需要数据就自己去MQ里面消费,不需要了就取消对MQ的消费即可;
- 异步: A的任务包括BCD的逻辑,A把消息发到MQ队列中即可,BCD再处理,减少请求延迟;
- 削峰: 减少高峰时对服务器的压力,如,数据库每秒从MQ中获取2000个进行处理,避免性能崩溃.
- 缺点: 1) 系统高可用降低,如果MQ挂掉或升级,系统不可用了, 2) 系统复杂度提高,可能有消息丢失,重复消费,顺序消费,堆积,数据一致性问题;
最常用的两种MQ, 中小公司用rabbitMQ,大公司用kafkaMQ.
kafka - 特点: 1) 单机吞吐量在10万级,高吞吐,2)时效性好,延迟在ms以内,3)高可用分布式,一个数据多个副本,少数机器宕机不会丢失数据,不会导致不可用 4) 可靠性,经过参数化配置可以做到0丢失,5) 支持MQ功能,实时计算和日志采集被大规模使用.
- 订阅形式: 基于topic以及按照topic进行正则匹配的发布订阅模式
- 持久化: 支持大量堆积, 支出顺序消息
- 集群方式: 天然的无状态集群, 每台服务器既是master也是slaver
- 顺序问题解决方式: 保证生产者-MQ-消费者是一对一的关系,通过设计或分解来规避,从业务层面保证顺序.
- 重复问题解决方式: 根本原因是网络不可达,如果消费端收到两条一样的消息,保持幂等性保证每条消息都有唯一编号且保证消息处理成与去重表的日志同时出现.
- kafka四种角色: 生产者producer, 消费者consumer, 标签topic,篮子broker, broker支持水平扩展,broker越多,吞吐量越高
10.producer -> push消息到broker
consumer -> pull 从broker订阅并消费
zookeeper 管理集群配置,选举leader,探测broker和consumer的添加和移除,维护partition的领导从属关系,主分区挂了就选举leader,维护topic和partition,topic等原配置信息.
四大接口: producer : 允许应用可以向kafka中topics发布消息;
consumer: 允许应用可以订阅kafka中的topics并消费消息
streams: 允许应用可以作为消息流的处理者
connector API: 提供与应用或系统适配功能,比如与数据库连接器可以捕获表结构的变化
topic 支持多个生产者或消费者同时订阅,topic由多个partition组成,每个partition都有序,根据算法分配到指定分区,每个partition在物理上对应一个文件夹,存储所有消息和索引文件;
数据持久化,先写缓存,等数据量足够大了再批量写入flush.
at least once 目前可以实现消息绝不会丢,但可能重复传输.
怎么优化kafka集群: 1) 组建较大集群, 并保证同一个topic的不同partition位于不同虚拟机,2)监控,对于消费过慢的partition所在的broker,暂停写入,等待消费,3) 将kafka安装在系统盘,/opt完全用于消息存储,不安装其他服务,3)保留物理内存1/2以上给系统,保证pagecache的分配
分布式实现负载均衡: 每个分区在kafka集群中都有副本,副本使kafka具备容错能力,每个分区都由一个服务器左右leader,其他作为followers,leader处理消息的读和写,其他则复制leader,如果leader down了,follower中的一台会自动成为leader.
天然分布式:往多个broker的partition存储数据,将partition以消息日至的方式村塾,通过顺序访问io和缓存才把数据写到磁盘上,提高速度.
异步通信: 不需要立即处理的可以先把消息放到队列,需要的时候处理;
kafka集群之间通信: 集群之间是无法发现对方的,每个kafka向zk中注册有broker,id, 这样组成集群后,每个人通过zk发现彼此.
rabbitMQ
- 优点: 单机吞吐量万级,时效性好,微秒级延时,并发强,性能好
- 工作模式: 主要使用发布订阅模式和路由模式.
- 发布订阅模式:共享资源,每个消费者监听自己的队列,共同争抢当前队列的内容,谁先拿到谁负责消费,隐患是并发下回产生某一个消息被多个消费者共同使用,可以设置一个开关syncronize保证一条消息只能被一个消费者使用;
- 路由模式: 生产者将消息发给交换机按照路由判断,匹配上路由key对应的消费者才能消费;
- 主题模式,是路由模式的一种, 路由功能添加模糊匹配,根据key的规则模糊匹配到对应的队列.
- 怎么路由的: 生产者-理由- 一至多个队列消息发布到交换器,创建消息时设定路由键,通过这个把度列绑定到交换器上,消息到达交换器后rabbitMQ将消息的路由键和队列的路由键进行匹配;
- 常用的交换器: fanout,如果交换器收到消息,会广播到所有绑定的队列上;
- 传输方式: 基于信道传输,是在真实的TCP连接内的虚拟连接;
- 确认机制: 发送方确认,将信道设置成confirm模式,异步的,消息达到目的队列或被写入磁盘,信道会发送一个确认给生产者,如果内部错误导致消息丢失会发送一条nack消息.
- rabbit高可用: 镜像集群模式,每个rabbitMQ节点都有这个queue的一个完整镜像,包含queue的全部数据,可以指定数据同步到所有节点或指定数量的节点,有一个机器宕机没事,其他机器还包含了这个queue的完整数据.
Redis
- Redis是什么: 使用C语言编写的,高性能,非关系型nosql键值对数据库.
- 数据类型: Redis可以存储键和值得映射,键只能是字符串类型,值支持5种 string,hash, list,set,sorted-set;
举例: 1)string: 短信验证码,个人信息等;
2)hash散列表: key为唯一标识,value对应商品详情,新闻详情,个人详情等;
3)list有序, 存储有序且数据相对固定的,如省市区表,字典表等,适合根据写入时间排序的消息等;
4)set,如一个人有哪些好友,可以对两个set提供交集,并集,查找两个共同好友;
5)sorted-set: 是set的增强版本,适合类似top10等. - 优点: 1)读写性能好, 2)支持数据持久化,支持AOF,RDB两种持久化方式,3)支持事务(原子性,一致性,隔离性,持久性). 4)数据结构丰富,value支持5种数据类型 5) 支持主从复制,主机会自动将数据同步到从机,可以进行读写分离.
- 缺点: 1)容量受内存限制,不能作海量数据的高性能读写
2)不具备自动容错和恢复功能,3)较难支持在线扩容,系统上线时必须保证有足够的空间,造成了资源的浪费. - 怎么做到读写分离的: 配置主从节点,master进行写,slave进行读,slave连接到master后发送给一个sync 的命令,master启动存盘进程,传送整个RDB文件,全量复制,之后的操作为增量复制.
- Redis使用的是分布式缓存: 缓存分为本地缓存和分布式缓存, Java使用的是currentHashMap和guava实现的本地缓存,Redis是分布式缓存,多实例共用一份缓存,缓存具有一致性,需要保持高可用.
- Redis为什么快: 1)完全基于内存,数据结构简单,2)采用的单线程,没有因为死锁导致的性能消耗 3)使用多路I/o复用模型,非阻塞io,
- VM机制: 应用场景:计数器,缓存,会话缓存,全页缓存.
- 持久化是什么: 把内存的数据写到磁盘中棉纺织服务宕机内存数据丢失.
- Redis持久化的机制: RDB和AOF. 默认RDB.
- RDB : RedisDatabase, 按照一定的时间将内存数据以快照的形式保存到硬盘中,对应产生的文件是dump.rdb,可以配置save定义快照的周期.
- RDB的优点: 只有一个文件,方便持久化,容灾性好,性能最大化,存盘进程是fork子进程来完成写操作,单独进程完成持久化,主进程不会进行IO操作,保证了Redis的高性能,数据集大时,比AOF效率高.
- RDB缺点: 数据安全性低,持久化之前Redis发生故障的话数据会丢失,适合数据要求不严谨的.
- AOF: append on file 将Redis执行的每次写命令记录到单独的日志文件中,重启Redis时会重写将持久化的日志中文件恢复数据.
- AOF优点: 数据安全,
- AOF缺点: 比RDB文件大,恢复速度慢,数据集大时比RDB启动效率低.
- 过期键的删除策略: 缓存的key过期后,Redis有3种处理方式,
1)定时过期,每个key都要一个定时器,到过期时间就立即清除,对内存友好,但会占用CPU,影响缓存的相应时间和吞吐量;
- 惰性过期,只有当访问一个key时才会判断该key是否已过期,过期则清除,可以节省CPU,但对内存不友好;
- 定期过期, 每隔一定时间扫描一定数量的expires中一定数量的key,清除过期key;
Redis怎么优化: 尽可能的使用散列表,不要为每一个字段设置单独的key,而是把信息存储到一张散列表里面.
通讯协议socket
- 在应用层和传输层之间的一个抽象层,本质是编程接口API,把tcp/IP层的操作抽象为几个接口供应用层调用以实现通信. 通过socket我们才能使用TCP/IP协议,Java.net下有两个类,socket和serversocket,在client和server建立连接后,两端都会产生一个socket实例,操作这个实例,完成所需的会话.
- socket连接分为3个步骤:服务器监听,客户端请求,连接确认, 模式:打开-读写-关闭模式
- 连接过程
- 客户端 初始化socket->connect->send->receive->close
- 服务端 初始化socket->绑定端口->listen开始监听->accept阻塞返回薪的socket描述符,区分客户端,循环received send
- 客户端连接服务器connect->服务器处理请求并回应->客户端读数据,关闭连接;
- socket得通过五元组确定:协议,客户端IP,客户端port,服务端IP,服务端port