架构的复杂度主要来源于“高性能”“高可用”“可扩展”等几个方面nginx
常见的性能指标:nginx负载均衡性能是3万左右,mc的读取性能5万左右,kafka号称百万级,zookeeper写入读取2万以上,http请求访问大概在2万左右。算法
消息队列的复杂性主要体如今这几个方面:高性能消息读取、高可用消息写入、高可用消息存储、高可用消息读取。数据库
(1)备选方案不要过于详细。备选=阶段解决的是技术选型问题,而不是技术细节。
(2)备选方案的数量以 3~5个为最佳。
(3)备选方案的技术差别要明显。
(4)备选方案不要只局限于已经熟悉的技术。编程
(1) 适用场景
Kafka适合日志处理;RocketMQ适合业务处理。
公号-Java大后端
2018-05-24
极客时间
hongfenghuoju/7832[2018/8/6 9:13:44]
(2) 性能
Kafka单机写入TPS号称在百万条/秒;RocketMQ大约在10万条/秒。Kafka单机性能更高。
(3) 可靠性
RocketMQ支持异步/同步刷盘;异步/同步Replication;Kafka使用异步刷盘方式,异步Replication。RocketMQ所支持的同步方式提高了数据的可靠性。
(4) 实时性
均支持pull长轮询,RocketMQ消息实时性更好
(5) 支持的队列数
Kafka单机超过64个队列/分区,消息发送性能下降严重;RocketMQ单机支持最高5万个队列,性能稳定(这也是适合业务处理的缘由之一)后端
备选有轮询、权重分配、ip_hash、fair、url_hash缓存
轮询(默认)服务器
每一个请求按时间顺序逐一分配到不一样的后端服务器,后端服务器分配的请求数基本一致,若是后端服务器“down掉”,能自动剔除。
加权轮询
根据权重来进行轮询,权重高的服务器分配的请求更多,主要适应于后端服务器性能不均的状况,如新老服务器混用。
ip_hash
每一个请求按访问IP的hash结果分配,这样每一个访客固定访问一个后端服务器,主要用于解决session的问题,如购物车类的应用。
fair
按后端服务器的响应时间来分配请求,响应时间短的优先分配,可以最大化地平衡各后端服务器的压力,能够适用于后端服务器性能不均衡的状况,也能够防止某台后端服务器性能
不足的状况下还继续接收一样多的请求从而形成雪崩效应。
url_hash
按访问URL的hash结果来分配请求,每一个URL定向到同一个后端服务器,适用于后端服务器可以将URL的响应结果缓存的状况。网络
数据库设计两类表,一类是日志表,用于消息写入时快速存储到MySQL中;另外一类是消息表,每一个消息队列一张表。
业务系统发布消息时,首先写入到日志表,日志表写入成功就表明消息写入成功;后台线程再从日志表中读取消息写入记录,将消息内容写入到消息表中。
业务系统读取消息时,从消息表中读取。
日志表表名为MQ_LOG,包含的字段:日志ID、发布者信息、发布时间、队列名称、消息内容。
消息表表名就是队列名称,包含的字段:消息ID(递增生成)、消息内容、消息发布时间、消息发布者。
日志表须要及时清除已经写入消息表的日志数据,消息表最多保存30天的消息数据。session
直接采用MySQL主从复制便可,只复制消息存储表,不复制日志表。架构
采用ZooKeeper来作主备决策,主备服务器都链接到ZooKeeper创建本身的节点,主服务器的路径规则为“/MQ/server/分区编号/master”,备机为“/MQ/server/分区编
号/slave”,节点类型为EPHEMERAL。
备机监听主机的节点消息,当发现主服务器节点断连后,备服务器修改本身的状态,对外提供消息读取服务。
消息队列系统设计两个角色:生产者和消费者,每一个角色都有惟一的名称。
消息队列系统提供SDK供各业务系统调用,SDK从配置中读取全部消息队列系统的服务器信息,SDK采起轮询算法发起消息写入请求给主服务器。若是某个主服务器无响应或者
返回错误,SDK将发起请求发送到下一台服务器。
消息队列系统提供SDK供各业务系统调用,SDK从配置中读取全部消息队列系统的服务器信息,轮流向全部服务器发起消息读取请求。
消息队列服务器须要记录每一个消费者的消费状态,即当前消费者已经读取到了哪条消息,当收到消息读取请求时,返回下一条未被读取的消息给消费者。
考虑到消息队列系统后续可能会对接多种不一样编程语言编写的系统,为了提高兼容性,传输协议用TCP,数据格式为ProtocolBufer
一、发送端和消费端如何寻址
利用zookeeper作注册中心,把broker的地址注册到zk上,发送端和消费端只要配置注册中心的地址便可获取集群因此broker地址,当有broker下线时,发送端和消费端能及时更新broker地
址。
二、发送端消息重试
当发送消息发生网络异常时(不包括超时异常),能够从新选择下一台broker来重试发送,重试策略能够自定义。
三、消息消费采用pull仍是push?
考虑push模式会更复杂,故放弃,采用pull模式,消费端主动去拉,为了达到与push模式相同的低延迟效果,能够采用长轮询的方式,消费端轮询拉取消息费,当有消费可消费时,返回消息,
若是没有可消费的消息,挂起当前线程,直到超时或者有可消费的消息为止。
四、消息重复问题
消息中间件不解决消息重复的问题,有业务系统本身根据业务的惟一id去重。
五、顺序消息
发送端在发生顺序消息时,只发送到相同broker的相同队列,消费端消费时,顺序消息只能由同一个消费端消息。
六、定时消息
发送端指定消息延时多长时间消费,broker端定时扫描定时消息,达到延时时间的消息加入到消费队列。
七、事务消息
发送端分两步,先预发送消息,broker端只记录消息为预发送状态,再执行本地事务,而后再根据本地事务的成功或者失败发送确认消息(回滚仍是提交),这步若是发生异常,broker启动定
时任务,把未确认的消息发送给发送端回查事务状态(须要发送端提供回查接口)。
Memcache是纯内存缓存,支持基于一致性hash的集群;而Redis同时支持持久化、 支持数据字典、支持主备、支持集群,看起来比Memcache好不少啊