Aswan&hump

  • 1,109 views
Uploaded on

 

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
    Be the first to like this
No Downloads

Views

Total Views
1,109
On Slideshare
0
From Embeds
0
Number of Embeds
0

Actions

Shares
Downloads
4
Comments
0
Likes
0

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide
  • 红色箭头代表事件。 Scheduler 是中心。

Transcript

  • 1. 阿斯旺与驼峰hongjiang 2011.7.27
  • 2. OfferDetail 访问统计► 1)大数据量:每天 2000 万 PV 左右,每周 pv 超过 1 亿。去重后 offer 量在 5000~7000 万之间。► 2)离散性:统计连续的 5 周,对访问去重后将近 1.5 亿 ( 总 offer 为 2.4 亿 ) 。每天有 80% 的 offer 只访问了 1 次,放大到一周,仍有 30% 多的 offer 只被访问 1 次。► 3) 重叠率不高:以周为单位,第 1 周访问过 offer 在第 2 周又被访问到的约 40~55% 之间。
  • 3. 解决方法► 1) 缓存全部没有意义,找热点► 2) 即使只缓存热点,想要达到较高的命中 率,也依然要缓存很大量的数据。千万级的 数据量,必须采用分布式
  • 4. 思路:冷热交换 出队 入队Head 权 重 大 的 排 在 队 首 Head 入队 出队
  • 5. Aswan 的架构Client Client Client Client Client Client Index Index Scheduler Storage Storage Storage Storage Storage
  • 6. 服务器端的角色► 1) Scheduler: 调度 / 配置 / 注册中心。事件的中心。 并通过一致性哈希来将数据分布在各台 Storage 上 。► 2) Index: 索引服务器,用于定位某个 key 存储在 哪个 Storage 上。 Index 可配置单台或多台,上面 的数据是一致的。多台主要起到负载均衡的作用。► 3) Storage: 存储服务器,根据数据权重的变化自 动调节其级别。
  • 7. 客户端► 与 memcached 的 client 不同,“轻”客户 端, client 知道的很少,服务器端的变化对 client 来说是透明的,比如新增 / 减少 Storage ,对 client 来说是无需了解的。► client 定时从配置中心获取可用的 Index 列 表。实现方式同 napoli
  • 8. Client 的一次请求过程1) 未命中的情况: Client 2 未命中, 返回 null 1 Query 6 更新 Index Index 3 发送事件 Scheduler 4 定位并通知 Storage 5 更新后反馈
  • 9. Client 的一次请求过程2) Index 命中 , Storage 未命中的情况: 1 Query Client Index 2 命中,返回存储节点5 Set 4 返回 3 Get location Val 为空 Storage
  • 10. 数据更新的解决► 使用 napoli 监听变更 remove Scheduler Task napoli remove Storage Storage Storage
  • 11. 存储结构► 借鉴 Redis 的做法,提供 K-V, K-Hash, K- List 等结构应用场景: 1) 页面的异步加载,同一个 id 对应几个 value ,可采用 K-Hash 2) 交易订单数, A 页面显示 20 条, B 页面 显示 10 条,可采用 K-List
  • 12. 通讯框架的选择1, 序列化 1) protocolBuffers: 不适宜在现有业务上采用。 2) json/hessian: 性价比未必高 3) Thrift : 想采用,但不熟悉 4) 现在采用 java serialize + gzip 以后再优化这里有一个详细的对比:https://github.com/eishay/jvm-serializers反馈给温少后,他很快对 fastjson 做了优化,后又根 据江航的建议采用 asm 优化,最 1.1.1 版 fastjson 已经超过了 protoBuffers
  • 13. 通讯框架的选择2, 通讯协议 1) mina/netty : 缺乏 NIO 网络编程的经验,其中的 陷阱也不少。 http://www.slideshare.net/killme2008/nio-trick-and-trap-8464155 2) tb-remoting: dubbo 最初采用的。基于 mina , 后来 dubbo 开发了自己 dubbo-remoting 通讯框架 ,基于 netty3 ,但在写 Aswan 时还没有发布。 3) http: 采用嵌入式 jetty 用于 http 连接管理。简 单,但 http 在并发较高时衰减的较快,性能不佳。
  • 14. Jetty 的调优► 1) 增加 jetty.acceptors 以应对高并发 使用 apache ab 50 并发测试, acceptors=8 比 2 有 明显提高  http 在并发情况下的衰减 (acceptors=2) :  1 个线程 http 耗时平均 1.7ms 左右,  10 个线程并发将衰减到 5ms 左右,  20 个线程并发将衰减到 10ms ,  50 个线程降到 20ms
  • 15. Jetty 的调优► 2) Http-KeepAlive 是否起了作用?开启 keepAlive , SelectChannelEndPoint 的实 例数应该是较稳定的。
  • 16. 事件过程 : 上 -> 下 StorageIndexServerEventQueue Scheduler BlockingQueueEventQueue 消费端 多线程 单线程串 行通知
  • 17. 事件过程 : 上 -> 下IndexServer Scheduler EventQueue BlockingQueue 消费者: 单线程 Storage: ChangeRecorder 消费者: 消费者 生产者 单线程 缓冲区 缓冲区 Exchanger :达到一定量再消费
  • 18. 事件过程 : 下 -> 上Storage SchedulerExchanger 多线程Exchanger 异 步 Exchanger 单线程串Exchanger 行通知 Index Index
  • 19. 事件队列► 借鉴 AWT 中的 EventQueue com.alibaba.aswan.server.index.WeightingChangeEventQueue.java► 事件的合并: coalesceEvent ,对于离散事 件意义不大。► 锁分离: 两把锁, putlock 和 tacklock 参考 LinkedBlockingQueue
  • 20. 缓冲区的设计Exchanger : 简单好用。需考虑缓冲区的大小。生产 者的节奏与消费者的节奏是否匹配的上。Queue: 需考虑批量消费的需求。自实现批量出列, 或者单个出列后累计一定量再一并处理。如果是 BlockingQueue 注意初始容量,太小会导致高并发 情况下生产者阻塞。进而可能引起网络阻塞等连锁 反应。 Aswan 在第一个测试版本遇到过。
  • 21. 一致性哈希的选择► Ketama 通过 MD5 实现 last.fm 最早采用, spy/xmemcached 等 client 也采用。 测试中发现 240 个虚拟节点最佳。 see: com.alibaba.aswan.server.schedule.locator.KetamaLocator.java► MurmurHash ,更高效的 Hash , Redis 的 java-client 中采用
  • 22. 权重因素► 1) 访问次数: 越多越好► 2) 最后访问事件:越近越好权重公式:权重值 = 访问次数 * 系数系数与最后访问时间有关,越近系数越高:系数公式: Math.pow(WEEK_FACTOR, lastAccTime - startTime)// week_factor 是一个经验值public static final float WEEK_FACTOR = 1.35F
  • 23. 权重因素► 3) 增加优先级属性,某些过大的对象优先 级设置低一些,比如大于 1m 的只能沦为二 等公民,不能存储在 L1 中
  • 24. Storage 的内部结构 L2 L1ColdPool Val 存在磁盘 Val 存在内存 Swap Swap
  • 25. 双向队列的实现 DoubleEndedPriorityQueue 维持 2 个 heap,minheap 和 maxheap 2 7 5 4 6 26 7 5 4 Min heap Max heap http://www.cise.ufl.edu/~sahni/dsaaj/enrich/c13/double.htm
  • 26. 性能的考虑► 1)千万级对象,需要分成很多个区域 否则同步问题成了瓶颈,参考 ConcurrentHashMap 的做法,每 1 万个元素存储在 一个 Segment 上► 2) 避免频繁的堆排序,堆中元素改变超过一个阈值 再进行重排序。► 3) 双向堆注意关联影响,对 referent 做一层包装, 清除元素时避免引起堆的调整 , 手动排序。
  • 27. GC 策略与内存调优对象太大,采用 Gzip 压缩后平均每个线上 的 OfferDO 对象 5.5k (detail 字段占了大 头)
  • 28. 吞吐量优先还是应用响应优先► UseParallelOldGC or CMS or G1 ?► 一次 Full GC 的代价?  旧生代的空间有 3.5G
  • 29. 按代 GC 策略的组合方式http://blogs.oracle.com/jonthecollector/entry/our_collectors
  • 30. 线上前台应用的 GC 策略以 Exodus2 为例: -server -Xmx2g -Xms2g -Xmn512m -XX:PermSize=128m -XX:MaxPermSize=196m -Xss256k -XX:+DisableExplicitGC // 禁止外部应用程序强制进行垃圾收集 , 将 System.gc() 调用转换成一个空操作 -XX:+UseConcMarkSweepGC // 启用 CMS -XX:+CMSParallelRemarkEnabled // 尽量减少 mark 的时间 -XX:+UseCMSCompactAtFullCollection // 对 live object 进行整理,使 memory 碎片减少 -XX:+UseFastAccessorMethods // 对 get 、 set 方法转成本地代码 -XX:+UseCMSInitiatingOccupancyOnly // 只有在 old generation 在达到初 始化的比例后启动收集 -XX:+UseCompressedOops // 压缩普通对象指针,针对 64 位系统
  • 31. ► 默认老年代到 92% 才进行 GC (一些老版 本的 JVM 是 68% )► 可通过-XX:CMSInitiatingOccupancyFraction=80 指定为 80% 时进行
  • 32. 精简 HashMap► HashMap 中的 Entry 存在浪费► 修改 HashMap ,实现一个 MyHashMap将其初始容量与增长因子设的紧凑一些► 千万对象,内存节省了约 300m
  • 33. 架构的缺陷► 1) 角色较多► 2) 2 次网络访问,比 memcached 等多一次 网络开销。► 3) 想要做到 server 端透明的增减服务器, 但实际这种需求不强烈。► 4) hump ,一个简化版的热点 cache ,将采 用 dubbo-remoting/fastjson ,类似 memcached 方式。包含 K-List, K-Hash 等 存储结构。
  • 34. 分布式领域的一些技术► Gossip 协议 : 去中心化 又被称为反熵( Anti-Entropy ),反熵就是在杂 乱无章中寻求一致 Gossip 的特点:在一个有界网络中,每个节点都随 机地与其他节点通信,经过一番杂乱无章的通信, 最终所有节点的状态都会达成一致。每个节点可能 知道所有其他节点,也可能仅知道几个邻居节点, 只要这些节可以通过网络连通,最终他们的状态都 是一致的,这也是疫情传播的特点。
  • 35. 分布式领域的一些技术Gossip 的案例 :► Cassandra► Redis 的分布式实现草案。 http://redis.io/presentation/Redis_Cluster.pdf
  • 36. 分布式领域的一些技术► Paxos 算法 : 解决数据一致性。 算法比较复杂。Yahoo! 开源的 ZooKeeper 是一个开源的类 Paxos 实现Google Chubby 也基于 paxos 算法
  • 37. 参考► << 面向模式的软件架构 - 第 4 卷 : 分布式 计算的模式语言 >>► Napoli Client► Jedis https://github.com/xetorthio/jedis.git  Redis 的一个 java 客户端