28
© 2016, Amazon Web Services, Inc. or its Affiliates. All rights reserved. 杨晓,有米科技 高频交易移动广告平台的架构变迁

高频交易移动广告平台的架构变迁...• 使用ua_nginx_module l 加上几段lua代码可以很方便得出每个域名的统计信息 • 使用_http_dyups_module ngx 可以增加减少

  • Upload
    others

  • View
    35

  • Download
    0

Embed Size (px)

Citation preview

© 2016, Amazon Web Services, Inc. or its Affiliates. All rights reserved.

杨晓,有米科技

高频交易移动广告平台的架构变迁

提纲

1. 业务模式 2. 早期的架构 3. 面临的挑战 4. 架构的变迁

业务模式

我们广告平台的广告分两大类: • 嵌入手机APP的SDK请求的广告 • DSP广告

SDK Server

RTB-Server

Endpoints

ADX-Server

业务模式

以上两种广告分类都可以分为以下两个步骤处理: 1. 拿到广告并投放 2. 广告效果确认

获取广告库存 获取用户标签

匹配筛选

更新广告库存 对上下游结算

作弊检查

早期的架构

• 很经典的LNMP • 早期流量不大时工作良好

AD Request AD Effect&Billing

Redis

MySQL

面临的挑战

• 横向扩展 • 从几百QPS到几万QPS • 从单个数据中心到多个数据中心

• 响应速度 • 响应速度直接影响广告的转化率 • DSP的响应时间不得超过100MS

• 灵活伸缩 • 节假日流量暴涨 • 每天流量高峰,低谷时段

• 海量数据 • 毫秒级DMP数据快速存取 • 多维度自由组合查询报表

横向扩展

随着流量的增长,以一种优雅的方式加机器提高吞吐量是很重要的,我们的主要思路是高低频操作分离,读写分离,需要横向扩展的机器做到无状态。 根据这个思路我们首先对我们的投放结算逻辑进行了拆分。 原来的方式的问题: 1. 结算时需要用到一个时段内的效果数据,没法拆分 2. 投放要求快速返回,结算需要较多的计算 存在这些前提: 1. 结算相对于投放广告频率不高 2. 结算结果并不需要返回给用户

AD Request AD Effect&Billing

Redis

MySQL

通过日志传输服务分离结算

效果记录上报上来,逻辑层马上将效果记录传给消息队列,汇集到日志服务器的磁盘,日志服务器每分钟分析最新的日志,将结果写入数据库。

Redis

MySQL

AD Request

AD Effect

MQ

Filesystem Analytics Cron

Logic Node

Log Node

日志传输服务

当时大概2012年,我们的服务在物理机房,考察了多种消息队列。 最终我们看中了ZeroMQ的性能和非中心化的功能,自己封装了一层,实现了producer和consumer,并且加上了重传保障。 刚开始我们用C语言来实现,不久就用Golang来重写,因为Golang有良好的并发调度特性可以简化程序编写。

RabbitMQ Redis ZeroMQ

性能 6k+ IOPS 3w+ QPS 6w QPS

中心化 YES YES NO

其它优势 Topic Simple

日志传输服务

使用ZeroMQ的Push模式,整个日志传输服务包含3个角色。 • Register:类似Zookeeper,服务发现。 • Client:接收WebAPP传来的日志,推送

给Server。 • Server:接收Client传来的日志,写入磁

盘。

Register

Server Client

Register,Heartbeat Servers

Data Client Server

File

日志传输服务

ZeroMQ方案日志传输服务的优点: • 资源占用极少,在1w/s日志的时候全部server加起来也只要用满一个CPU • 避免Server进程单点 • 性能比较强,生产环境上峰值1w+/s日志没问题 缺点: • 和业务耦合度太高,无法成为通用组件 • 只能将日志写到一个磁盘里面,日志的分析都要读那个磁盘

日志传输服务改用Kafka

• 灵活的Topic和Partition机制 • 同一个内容可以有多个消费者对内容进行不同的处理 • 很好支持Spark Streaming • 4台c4.xlarge支持10w/s 日志读写没问题 • 有很直观的 Kafka Offset Manager

多节点部署

把结算分离出来后广告投放服务对数据库只读 • 在一个机房里投放服务器可以随便增加了 • 添加机房也变得比较简单

多节点部署

• MySQL主从同步 • 日志分析结果通过队列的同步

细节处理: • DMP数据同步 • 节点间网络延迟延伸出的结算限

量等问题

Master

Slave

node1

node2

Logic

Logic

Read

Read Log

rabbitmq

Log

rabbitmq

Result

Result

Logic Logic

Logic

响应速度

响应速度越快广告转化率越高 • 负载均衡策略 • Golang • 多地部署

负载均衡策略

我们采用Nginx+Constistent Hash的负载均衡方案 • 一个用户的请求固定路由到特定的机器 • 充分利用本地缓存,本地缓存的命中率可以达到70% • 减少机器增减的影响

0

2^32-10

0

2^32-10

Golang

• 我们用PHP快速实现了功能,但在广告行业这种高并发的场景不适合 • 逐步分离一些组件改用Golang实现 • 用Golang代替PHP,单机吞吐量提高5倍,响应速度快接近10倍

灵活伸缩

现象: • 每天晚上10点和凌晨4点是请求量的高峰低谷 • 节日期间流量会大涨 在AWS上我们不再需要服务器时刻保持可以对抗峰值请求的性能,我们在流量涨起来时添加广告投放服务器,在流量低时缩减服务器可以有效节约成本。 考虑到我们实际情况:我们需要Consistent Hash,以及一天多次发布新代码的频率;我们自己通过Nginx插件,AWS的API,以及Ansible的Dynamic Inventory 功能实现了一套对业务开发同事无感知的快速扩容方案。

快速扩容系统

1. Controller通过QPS,负载等指标发现需要增加机器

2. Controller调用AWS的API给运行中的Logic机器创建镜像

3. Controller通过新创建的镜像启动n台新的机器 4. Controller确认新的机器可用 5. Controller发送新的Upstream列表给Nginx 6. Nginx reload 后将流量分配到新机器

Nginx

Logic Logic Controller

Proxy Add

Start&Check

Logic Logic

快速扩容技术要点

• 使用 lua_nginx_module 加上几段lua代码可以很方便得出每个域名的统计信息 • 使用 ngx_http_dyups_module 可以增加减少 upstream,再配合我们写的几段lua代码

将更新后的upstream保存到 Nginx的配置文件里 • 通过AWS的API,我们在扩容之前制作镜像并使用最新镜像启动,并且通过EC2的

cloud-init 脚本确保运行的代码最新 • Controller可以配置健康检查链接,只有在新增机器确认状态正常时才添加到 upstream • 我们通过给新增的机器设置标签或者 autoscaling group 将广告投放机器分为一组,通

过 Ansible 的 Dynamic Inventory 特性可以方便地批量操纵这一组机器

快速扩容效果

海量数据

数据类型 • 广告行为 • 报表和日志

广告行为 • 数据量接近10亿,每行原始信息1-50KiB不等 • 几毫秒内响应 • 1000+ QPS • 实时更新

广告行为

原来的广告行为存取方案 • 数据存放在 SSD 上的 MariaDB • 一张表分512个 Partition • 根据业务精简每一行数据 • 开启数据库的压缩功能 • 将 MariaDB 当作KV数据库来用 • 多个从库

缺点: • 复杂

ID Data

x {1:1,2:1}

y {1:1,3:1}

MariaDB

Key Value

1 BundleID1

2 BundleID2

Merge

1

2

Logic

3

广告行为

DynamoDB

ID Data

x {BundleID1:1,BundleID2 :1}

y {BundleID2:1,BundleID3:1}

Logic

现在的广告行为存取方案 • 使用DynamoDB直接存

优点: • 简单 • 不用担心容量问题 • 可配置吞吐量 • 访问延迟有保障

报表和日志的存储和分析

以前的方案 • 日志先落地到磁盘然后转存S3 • 将重要的日志存到MongoDB供查询 • 将汇总的结果存到MySQL

缺点 • 单机实时数据分析吞吐量小 • 用crontab跑脚本难以让处理过程可视化 • MongoDB Cluster 维护相对麻烦

File

S3

EMR

Mongo MySQL

报表和日志的存储和分析

现在的方案 • 日志不再落地到磁盘后再分析而是使用Spark

Streaming • 分析得到的报表存放到Redshift • 分析得到的用户相关的信息存放到DDB

优势 • EMR的Spark Streaming足够实时分析每秒好几万行

的日志并且支持热扩容 • 使用支持存放海量数据的Redshift可以方便快速存取

上百个维度的报表数据 • DDB中的数据可供投放服务快速获取

S3

EMR

MySQL

Kafka

Spark Streami

ng

Redshift DDB

Thanks