中间件阅读笔记

推拉模式的选择

使用长连接拉模式,在消息的实时性方面丝毫不逊推送模式

低延时探索

  • 考量性能从吞吐量和延迟两方面考虑
  • 依赖系统自身的page cache,全链路延时不可控
  • 延时变高导致该时间系统内处理的请求数增多,会导致某些节点不可用并扩散,导致雪崩

锁相关

非公平锁:加锁时不考虑排队问题,直接尝试获取锁,若失败则自动进行排队。
非公平锁导致线程等待时间过长,延迟变高。

锁同步会引起上下文切换,会带来一定开销。上下文切换一般为微妙级,当线程数过多,竞争压力大时,会产生数十毫秒级别的开销。

为避免锁带来的延迟,可利用CAS原语将核心链路无锁化。

内存没那么快

受限于linux的内存管理机制,应用程序访问内存时有时候会产生高延迟。

linux会尽可能用内存来做缓存,大多时候服务器可用内存比较少。当可用内存少时,应用程序申请或者访问新内存页会发生内存回收,当后台内存回收速度不及分配内存的速度时,会进入直接回收(direct reclaim),应用程序会自旋等待内存回收完毕,产生巨大延迟。

通过vm.extra_free_kbytes和vm.swappiness调优来避免。

page cache——利与弊

page cache作为文件缓存能加速数据的读写,但遇到os进行脏页回收/内存回收/内存换入换出等情形时,会产生较大的读写延迟,即偶发的高延迟。

通过内存预分配/文件预热/mlock系统调用/读写分离来消除延迟,同时能利用page cache的优点。

容量保障

降级限流熔断三大措施来保障核心服务的资源,暂停边缘服务。

限流

消息对列中对于慢请求(排队等待时间以及服务时间超过某个阈值的请求)进行容错处理。

对于离线应用场景,利用滑动窗口机制,缓慢缩小窗口以减缓从服务端拉取的频率,降低对服务端的影响。

对于高频交易/数据复制的场景,则采取了快速失败的策略,既能预防应用程序连锁的资源耗尽而引发应用雪崩,又能降低服务端压力,为端到端低延迟带来可靠保障。

降级

通过服务的QOS定义设置,提前约定划分等级,在洪峰期间进行丢车保帅的策略执行。

熔断

Netflix公司开源了他们的熔断解决方案hystrix。

高可用

高可用架构中的技术与权衡

type Backups Master/Slave Master/Master 2PC Paxos
Consistency Weak Eventual Eventual Strong Strong
Transactions No Full Local Full Full
Latency Low Low Low High High
Throughout High High High Low Medium
Data Loss Lots Some Some None None
Failover Down Read-Only RW RW RW

不同的解决方案对各项指标的支持程度各有侧重。基于 CAP 原则,很难设计出一种高可用方案能同时够满足所有指标的优值。

以 Master/Slave为例,一般满足如下几个特性:

  1. Slave是Master的备份,可以根据数据的重要程度设置Slave的个数。数据写请求命中Master,读请求可命中Master或者Slave。
  2. 写请求命中 Master 之后,数据可通过同步或者异步的方式从 Master复制到Slave上;其中同步复制模式需要保证Master和Slave均写成功后才反 馈给客户端成功;异步复制模式只需要保证Master写成功即可反馈给客户端成功。
  3. 数据通过同步或者异步方式从Master复制到Slave上,因此Master/Slave 结构至少能保证数据的终一致性;

异步复制模式下,数据在Master写成功后即可反馈给客户端成功,因此系统拥有较低的延迟和较高的吞吐量,但同时会带来Master故障丢数据的可能性;如期望异步复制模式下Master故障时数据仍不丢,Slave只能以Read-Only的方式等待Master的恢复,即延长了系统的故障恢复时间。相反,Master/Slave结构中的同步复制模式会以增大数据写入延迟、降低系统吞吐量的代价来保证机器故障时数据不丢,同时降低系统故障恢复时间。

消息服务介绍

路由系统

路由系统,各个处理模块管道化,扩展性强。系统监听主站的交易、商品、 物流等变更事件,针对不同业务进行消息过滤、鉴权、转换、存储、日志打点等。 系统运行过程记录各个消息的处理状况,通过日志采集器输出给JStorm分析集 群处理并记录消息轨迹,做到每条消息有迹可循。

存储系统

存储系统,主要用于削峰填谷,基于 BitCask 存储结构和内存映射文件,磁 盘完全顺序写入,速度极佳。数据读取基于 FileRegion 零拷贝技术,减少内存 拷贝消耗,数据读取速度极快。存储系统部署在多个机房,有一定容灾能力。

推送系统

推送系统,基于Disputor构建事件驱动模型,使用Netty作为网络层框架, 构建海量连接模型,根据连接吞吐量智能控制流量,降低慢连接对系统的压力; 使用WebSocket构建 长连接通道,延时更低;使用对象池技术,有效降低 系统GC频率;从消息的触发,到拉取,到发送,到确认,整个过程完全异步, 性能极佳。

架构

面向公网的应用,消息密度低,随机性强,使用服务端推送的消息消费模式。

快速确认消息

公网环境大部分消息一次就会消费成功,少数需要多次尝试。即99%的数据会在几秒内读写各一次,两次操作完成这条数据就失去了意义。

将待消费的数据存到内存,则少数一直未被消费的数据会丢失(内存队列用完)。数据都存到磁盘则磁盘压力大,性能差,为了少数数据而将全部数据都写磁盘不值得。通过多级缓存的思路来处理这类问题效果比较好,即针对这种场景,系统在存储子系统使用HeapMemory、 DirectMemory、FileSystem三级存储结构。

为了保护存储系统内存使用情况,HeapMemory存储近10秒发送记录,其余的数据会异步写入内存映射文件中,并写入磁盘。HeapMemory基于时间维度划分成三个HashMap,随着时钟滴答可无锁切换,DirectMemory基于消息队列和时间维度划分成多个链表,形成链表环,新数据写入指针头链表,末端指针指向的是已经超时的事务所在链表。

这里,基于消息队列维护,可以有效隔离各个队列之间的影响;基于时间分片不仅能控制链表长度,也便于扫描超时的事务。在这种模式下,95%的消息事务会在HeapMemory内完成,5%的消息会 在 DirectMemory完成,极少的消息会涉及磁盘读写,绝大部分消息事务均在内存完成,节省大量服务器资源。