鏖战双十一-阿里直播平台面临的技术挑战

摘要html


一直以来双十一都是以交易为重心,今年固然也是如此,可是这并不妨碍万能的淘宝将双十一打造的让用户更欢乐、体验更丰富、玩法更多样、内容更有趣,所以,今年也诞生了以直播为特点的游戏双十一会场,也就是本文所要着笔重点介绍的,即阿里直播平台在双十一所面临的复杂技术挑战以及技术选型的台前幕后。前端

大型直播的技术挑战体如今大流量、高并发场景下,视频流的处理、分发,播放质量保障,视频可用性监控,超大直播间实时弹幕及聊天互动,高性能消息通道,内容控制(包括视频内容自动鉴黄及消息文本过滤),以及系统可用性、稳定性保障等等方面。本文将针对其中的一些技术细节,抽丝剥茧,但愿经过些许文字的分析和介绍,能让你们有所启发。java

视频直播

对于直播平台来讲,为了保障各类网络环境下可以流畅的观看视频,须要将高清的输入流转换出多路不一样清晰度的视频流,以支持不一样网络条件下视频清晰度的切换,而因为不一样的端所支持的协议及封装格式并不彻底相同,好比无线端的HTML5页面能够很好的支持HLS协议,可是对于RTMP这类协议基本无能为力,而PC端为了下降延时,须要采用RTMP这一类流媒体协议。所以,为了支持多终端(PC、Andriod、IOS、HTML5)观看,须要对输入流进行编码及封装格式的转换。转码完成以后,还须要对视频流进行分发,毕竟源站的负载能力有限,节点数有限,离大部分用户的物理距离远,对视频这一类十分占用带宽资源的场景来讲,为了提升播放质量减小卡顿,须要尽可能减小到用户的传输链路。所以,一般的作法就是将视频流进行切片存储到分布式文件系统上,分发到CDN,或者是直接经过CDN进行流的二级转发,由于CDN离用户最近,这样才能保证直播内容对于用户的低延时,以及用户的最短路径访问。客户端对延时的要求,以及采用何种协议,决定了视频是否须要分片,分片的目的在于,经过HTTP协议,用户不须要下载整个视频,只须要下载几个分片,就能够播放,实际上直播与录播的技术是相通的,区别在于直播的流没法预测终结时间,而录播的视频流终止时间是已知的。对延时要求没那么高的场景来讲,客户端能够采用HLS协议,毕竟IOS、Andriod、HTML5等无线端应用可以很好的兼容和支持,且经常使用的静态资源CDN能够不作相应改造,就能支持,可是HLS协议的一大天生缺陷就是延时较高,视频内容在切片、分发、客户端下载的过程当中耗费了很长时间。对于时效性要求很是高的场景,就须要采用RTMP、RTSP一类的实时流媒体协议,来下降延时,而且,为了下降源站的压力,须要CDN边缘节点来作流的转发,那么,CDN就必须得支持相应的流媒体协议,也就是一般所说的流媒体CDN。web

因为直播流由主播上传,如何控制违法违规内容特别是黄色内容,成了十分棘手的问题。使人欣慰的是,随着技术的发展,算法对于黄色图像的识别准确率已经很高,基本达到能够在生产环境应用的程度,所以咱们也尝试在视频流分发以前,对视频帧进行提取,而且将图像交给算法进行识别,当超过预设的阈值时,可进行预警或者关停直播间。通过一段时间的实践,取得了必定的效果,下降了人力成本,但不可避免的是图像识别算法时间复杂度高,吞吐率较通常算法低。ajax

直播整个链路是比较长的,包含有接流、转码、切片、分发、客户端下载、播放等众多环节,链路上任何一个节点有问题,均可能致使视频不能播放。所以,关键节点的监控就十分重要,除此以外,还须要对整个链路的可用性进行监控,好比,针对HLS协议来讲,可经过监控相应的m3u8索引列表有没有更新,来判断视频直播流是否中断。固然,如需判断视频流中的帧有没有花屏、有没有黑屏,就更复杂了,何况,监控节点所访问的CDN节点与用户所访问的CDN节点可能并不在同一地域。当前中国的网络环境,特别是跨网段的网络访问,对于流媒体应用来讲,存在较大的不可控因素,客户端网络接入环境对视频的播放有决定性影响。所以,收集终端用户的播放数据质量数据进行反馈,及时进行视频清晰度切换,显得特别重要。这些数据包括客户端的地域分布、播放卡顿信息、视频分片加载时间等等,根据这些信息反馈,能够较为全面的评估CDN节点部署是否合理,是否须要新增CDN节点,视频的转码参数对于不一样机型的兼容性等等,及时进行调整以改善用户体验。正则表达式

 

图1 视频直播架构redis

消息/弹幕

WEB IM应用及弹幕近年来有愈来愈火的趋势,是营销与气氛活跃的一种很是重要的手段。对于同时在线人数庞大的实时聊天互动、实时直播弹幕这一类场景来讲,在保障消息实时性的前提条件下,将会面临很是高的并发压力。举个例子来讲,假设一个活跃的直播间有10w人同时在线,正在直播一场热门的游戏赛事,假设每秒钟每一个人说一句话,将会产生10w条消息,也就是10w/s的消息上行QPS,而每条消息又须要广播给房间里面的每个人,也就是说消息下行将成10w倍的放大,达到惊人的10w*10w=100亿/s的消息下行QPS,而这仅仅是一场直播的QPS,相似的直播可能有多场正在同时进行,对于消息通道来讲,无疑将是一个巨大的挑战。所以,在系统设计的时候,首先要考虑的问题,就是如何下降消息通道的压力。算法

图2 消息的投递与消费数据库

用户将信息投递到消息系统以后,系统首先对消息进行一系列的过滤,包括反垃圾、敏感关键词、黑名单等等,对于信息的过滤后面会详细介绍,此处暂且不表。为了不系统被瞬间出现的峰值压垮,可先将消息投递到消息队列,削峰填谷,在流量的高峰期积压消息,给系统留必定裕度,下降因限流丢消息对业务产生的影响。然后端始终以固定的频率处理消息,经过异步机制保障峰值时刻系统的稳定,这是一个典型的生产者—消费者模型。对于消息的消费端,则可采用多线程模型以固定的频率从消息队列中消费消息,遍历对应房间所对应的在线人员列表,将消息经过不一样的消息通道投递出去。多线程增长了系统的吞吐能力,特别是对须要将消息一次性投递给几万上十万用户这样的场景,能够异步使用大集群并行处理,提升系统的吞吐能力。异步使后端的消息投递可不受前端消息上行峰值流量的干扰,提升系统稳定性。编程

除了采用消息队列异步处理以外,当房间人数太多,或者消息下行压力太大的状况下,还须要进一步下降消息下行通道的压力,这就须要采用分桶策略。所谓的分桶策,实际上就是限制消息的传播范围,假设10w人在同一个房间聊天,每人说一句可能瞬间就会排满整个屏幕,消息在这种状况下基本没有可读性。为提升信息的可读性,同时也下降下行压力,可将每10000人(具体每一个桶的容量能够根据实际需求来调整,这里只举例)放一个桶,用户发送的消息,只在一个桶或者部分桶可见,用户按照桶的维度接收消息,这样一方面前端用户接收到的消息量会少不少(跟用户所处的桶的活跃度相关),而且一条消息也不用发送给全部用户,只发送给一个或者部分桶,以下降消息下行压力。

分桶的策略有不少,最简单粗暴的方式就是根据用户随机。首先根据房间的活跃程度,预估房间该分多少个桶,而后将用户经过hash函数映射到各个桶,随机策略的好处是实现很是简单,能够将用户较为均衡的分配到每一个桶,可是会有不少弊端。首先,准确的预估房间的活跃用户数自己就比较困难,基本靠蒙,这将致使单个桶的用户数量过大或者偏小,太大就会增长消息链路的压力,而偏小则下降用户积极性,后期调整分桶数也会很麻烦,须要将所有用户进行重hash。另外从用户体验的角度来考虑,在直播过程当中,在线用户数正常状况下会经历一个逐渐上升达到峰值而后逐渐降低的过程,因为分桶的缘故,在上升的过程当中,每一个桶的人是比较少的,这必然会影响到弹幕的活跃度,也可能所以致使用户流失,而在降低的过程当中,逐渐会有用户退出直播,又会致使各个桶不均匀的状况出现:

图3 随机hash分桶

另外一种方案是按需分桶,固定每一个桶的大小,当现有的桶都满了以后,再开辟新的分桶,以控制每一个桶的人数,使其不至于太多也不至于太少,这样就解决了以前可能出现的每一个桶人数过少的问题,可是,有个问题将比以前的随机分桶更为明显,老的桶中不断有用户离开,人将逐渐减小,新开辟的桶将愈来愈多,如不进行清理的话,最后的结果仍然是分桶不均衡,而且会产生不少空桶,所以,就须要在算法和数据结构上进行调整:

图4 按需分桶策略

经过一个排序list,每次将新增用户添加到人数最少分桶,这样可让新用户加入最空闲的桶,以保持均衡,当桶满的时候,就再也不添加新的用户,可是,当老用户离开的速度大大高于新用户进来的速度时,桶仍是不均匀的,这时,就须要按期对分桶进行整理,以合并人数少的桶或者回收空桶,而合并的过程当中,新用户又会不断的加入进来,而且,还须要保证消息发送时能读到正确的用户列表,在分布式高并发场景下,为了保证效率,有时候加锁并非那么容易,这就有可能出现脏写与脏读,桶的整理算法将会很是复杂,有点相似于JVM中的内存回收算法。

与大数据量高并发场景下的分库分表策略相似,实际上分桶策略也是一种取舍权衡与妥协,虽解决了原有下行通道压力过大的问题,也引入了新问题。首先,分桶改变了本来普通用户对于消息的可见性,一条消息只对于部分桶的用户可见,而非全部桶的用户,这样不一样的桶内的用户看到的消息多是不一样的,另外一个问题是,以上的分桶策略有可能致使“热门桶”和“冷门桶”效应出现,便可能将不少“吐槽达人”分配到同一个桶,致使该桶的氛围十分活跃,而其余不那么活跃的用户分配到一块儿,以至于出现“冰火两重天”的局面,从而影响产品体验。固然,对于部分特殊的消息,如系统公告内容,或者是部分特殊角色(房间管理员、贵宾、授课的老师等等)所发送的消息,这一类消息须要广播给全部用户,这种状况下就须要系统对消息类型作区分,特殊的消息类型另做处理。

对于消息投递任务来讲,须要知道消息将以什么方式被投递给谁,这样就须要动态地维护一个房间的人员列表,用户上线/下线及时通知系统,以便将用户添加到房间人员列表或者从房间人员列表中移除。用户上线十分简单,只须要在进入房间的时候通知系统便可,但对于下线用户的处理则有点折腾,为何这么说呢?用户退出直播间的方式可能有多种,关闭浏览器tab、关闭窗口、关闭电源、按下home键将进程切换到后台等等,有的操做可能能够获取到事件回调,但也有不少种状况是没法获取事件通知的,这样就会致使人员列表只增不减,房间的人愈来愈多,消息投递量也随之增长,白白的浪费了资源。为解决这一问题,就需采用心跳。

心跳指的是客户端每隔一段时间向服务端汇报在线状态,以维持服务端的在线人员列表,当同时在线人数达到一个很大的量级(如百万级)的时候,每秒心跳的QPS也会变得很是之高,如何保障心跳的高效率、高吞吐就成了岑待解决的问题。首先是通讯协议的选择,是HTTP协议,仍是WebSocket,仍是TCP协议或者其余。HTTP协议的好处在于兼容性及跨终端,全部浏览器、Andriod、IOS的WebView,都能很好支持和兼容,在目前移动重于PC的大环境下,显得尤其重要,可是HTTP协议劣势也是显而易见的,做为应用层协议,单次通讯所要携带的附加信息太多,效率低。WebSocket在移动端的场景下比较合适,可是运用在PC端,需解决众多老版本浏览器的兼容性问题,socket.io的出现则大大简化了这一本来很是复杂的问题。TCP协议在传统的客户端应用上使用较多,可是对于WEB应用来讲,存在自然障碍。使用WebSocket和TCP协议的好处显而易见的,通讯效率会比HTTP协议高不少,而且这两种协议支持双工通讯。

另外一个问题是后端存储的选择,该使用怎样的存储结构来存储在线人员列表这样的数据结构,以支撑这么高的并发读写。通过优化而且使用SSD的关系型数据库相较以往性能已经有了很大的提高,可是对于频繁变化的大量在线人员列表来讲,持久化存储其实是没太大意义的。所以,读写性能更高的内存存储,如memcache,redis,多是一种更现实的选择。memcache只能支持简单的KV对象存储,数据读写须要进行频繁的序列化和反序列化,但吞吐更高,而redis的好处在于丰富的数据类型,如Lists、Hashs、Sets,省去了序列化和反序列化操做,而且支持更高效的分页遍历及count操做:

图5 基于redis Sets构建的分桶存储结构

消息通道

HTTP协议请求/响应式特性决定了它擅长处理浏览型业务,而对于须要与服务端进行频繁交互的即时通信场景来讲,则会显得十分蹩脚。在直播进行的过程当中,用户能够对主播进行吐槽、评论,用户与用户之间也能够进行频繁的交流,须要有像弹幕、WEB IM这样的工具来支持,这种场景下,消息的实时性尤其重要。

要实现这类场景,最简单最粗暴的方式莫过于不断地轮询应用服务器,采用拉的方式读取弹幕以及用户的聊天内容,消息的实时程度取决于拉的频率,拉的过快,可能服务器没法承受,拉的频率太低,则消息的实时性跟不上。轮询的方式太过于粗暴,须要频繁的请求服务器,成本较高,而且用户更新信息的频率实时变化,很难选择比较合理的轮询时间,由于不一样时间段用户发送消息的频率是有很大差别的,对于拉取的信息,客户端须要进行筛选和去重。所以,对于WEB端的即时交互应用,须要采用其余解决方案,如comit服务端推送,或者经过websocket来实现相似的场景。

comet[1]又被称做为反向ajax(Reverse AJAX ),分为两种实现方式,一种是长轮询(long-polling)方式,一种是流(streaming)的形式。在长轮询的方式下,客户端与服务端保持HTTP链接,服务端会阻塞,直到服务端有信息传递或者是HTTP请求超时,客户端若是收到响应,则会从新创建链接,另外一种方式是流的形式,服务器推送数据给客户端,可是链接并不关闭,而是始终保持,直到链接超时,超时后客户端从新创建链接,并关闭以前的链接。经过这两种方式,即可借用HTTP协议,来实现服务端与客户端的即时通信。

而WebSocket[2]是IETF所提出的一种新的协议,旨在实现浏览器与服务器之间的全双工(full-duplex)通讯,而传统的HTTP协议仅可以实现单向的通讯,即客户端发起的到服务端的请求,虽然comet在必定程度上能够模拟双向通讯,可是通讯的效率较低,且依赖特定的服务器实现。

图6 WebSocket协议[3]

为什么说comet的通讯效率会低于WebSocket呢,由于无论是comet的长轮询机制仍是流机制,都须要在请求超时后发送请求到服务端,而且,长轮询在服务端响应消息以后,须要从新创建链接,这样又带来了额外的开销。

图7 长轮询与websocket消息发送对比

咱们知道HTTP协议的Request Header中附带了不少信息,可是这中间包含的不少信息有些场景其实并非必须的,这样就浪费了大量的带宽及网络传输时间。而WebSocket协议使得浏览器与服务器只须要一次握手动做,便造成了稳定的通讯通道,二者之间就能够经过frame进行数据传递,而消息传递所发送的Header是也是很小的,这样就会带来效率的提高。

图8 websocket与comet性能对比

经过wireshark抓包能够作一个简单的测试对比, 假设服务端每秒推送50条消息给用户,每条消息的长度为10byte,对应不一样的用户规模,采用websocket和comet两种不一样的通讯机制,所须要传递的字节数如图8所示,可见,随着用户规模及消息量的提高,采用websocket协议进行通讯,将对通讯效率带来数量级的提高,详细的测试过程可参见笔者博客。

引入WebSocket协议,虽然原则上解决了浏览器与服务端实时通讯的效率问题,相较comet这种基于HTTP协议的实现方式,能得到更好的性能,但同时也引入了一些新的问题。摆在首位的即是浏览器的兼容性问题,开发WEB应用程序的一个最头痛的问题就是多版本浏览器的兼容,不一样浏览器产商对于协议的实现有各自的理解,而且,市面上还充斥着大量低版本不支持HTML5协议的浏览器,且这部分用户在中国还占有较大基数,所以在产品研发的过程当中不得不予以考虑。得益于socket.io[4]的开源,经过websocket、Adobe Flash Socket、long-polling、streaming、轮询等多种机制的自适应切换,帮咱们解决了绝大部分浏览器(包括各类内核的webview)的兼容性问题,统一了客户端以及服务端的编程方式。对于不一样平台的消息推送,咱们内部也衍生了一些成熟的技术平台,封装了包括消息推送,消息订阅,序列化与反序列化,链接管理,集群扩展等工做,限于篇幅,这里就很少说了。

文本内容过滤

双十一视频直播的另外一个挑战在于,如何对弹幕这一类的UGC内容进行过滤。根据以往经验,对淘宝来讲,若是内容不通过滤直接透出,毫无疑问用户将看到满屏的广告,大量的广告信息将直接致使部分功能没法使用。所以,文本内容过滤,对于咱们来讲能够说是一门基本功。早期垃圾、广告内容,或者非法信息的识别,主要依赖于人工,可是当下WEB2.0 DT时代,对于海量的信息进行人工筛查显然不太现实,社会在发展,技术也在进步,一系列新的文本筛查及过滤技术被运用到了工程领域。

敏感词匹配

经过长时间的累积,大点的网站通常都会有一份敏感词列表,若是用户提交的内容包含敏感词,就须要进行转义(转换成***),或者是拒绝发表。那如何判断文本中是否包含敏感词,以及如何进行敏感词过滤呢?若是敏感词只有不多的几个,那最简单的方式固然是经过关键词搜索算法或者是正则表达式进行匹配,但实际状况显然要复杂的多,须要过滤的关键词可能有成千上万个,而正则表达式的效率其实是比较低的,尤为在高并发场景下,对系统的吞吐能力要求很是之高。所以,这种场景下就须要有更高效的算法。目前较为常见的是采用Trie树算法或者是Trie算法的变种,如空间和时间复杂度都较为均衡的双数组Trie树算法来实现。Trie树也称为字典树或者是单词查找树,它的好处在于能够利用字符串的公共前缀以减小查询时间,最大限度的减小字符串比较次数,下降关键词在内存中占用的存储空间。

图9 Trie树结构

Trie本质上是一个有限状态机,根据输入的数据进行状态转移。假设敏感词包含“美利坚”、“美丽”、“金币”、“金子”、“帝王”,而输入的文本是“个人同桌是一个美丽的姑娘”,每读取一个字符做为输入,根据这个字符以及它的后续字符对Trie树进行查找,直到叶子节点,即可以找出文本中包含的违禁词“美丽”以及这个词在文本中对应的位置和频次。

固然,也能够经过构造多级的Hash Table来简化Trie树的实现,相同父节点的字放在同一个Hash Table中,以减小没必要要的查询,对于输入的文原本说,只须要将字符一个个依次做为输入对Hash Table进行查找,如包含对应的key,则继续,直到查询到最下层叶子节点。

图10 多级Hash Table简化Trie树的实现

在系统变得愈来愈智能的同时,恶意的用户也变得愈来愈狡猾,他们可能会在文本当中夹杂一些干扰字符来绕过敏感词检查,如“美*利*坚”,这就须要咱们对输入的文本作降噪处理,过滤掉其中的干扰字符,再进行匹配。

除了算法的实现以外,在集群环境下,还得综合考虑系统的吞吐以及机器内存的压力,因为敏感词过滤须要依赖庞大的敏感词词库,而且,还需将词库解析成Trie树或者多级的Hash Table置于内存当中,以便查找,这势必将占用大量的内存空间。所以,为了提高内存资源利用率,大部分状况咱们会采用RPC模式部署敏感词过滤服务,可是,在高并发场景下,为了下降因引入敏感词过滤而带来的延时,提升系统的吞吐,又须要将敏感词数据推送到本地内存,经过读本地内存中的数据,下降因RPC带来的时延,当敏感词库有更新时,服务端需将相应的变动信息推送给其余应用。

分类算法

分类实际上就是按照某种标准来给对象贴标签,而后再根据标签进行区分,基于几率统计的贝叶斯分类算法[5]是最多见的分类算法,也是目前垃圾文本识别领域应用最普遍的算法。

使用贝叶斯分类算法进行二分类大体可分为这几个步骤:

  1. 收集大量的垃圾内容和非垃圾内容语料,创建训练的垃圾语料集和正常内容的语料集。
  2. 对语料文本进行分词,提取出独立的字符串,而且统计字符串在文本中出现的频次。
  3. 每一个训练语料集对应一个hash table,好比垃圾语料集放在hashtable_bad中,而非垃圾语料集放在hashtable_good中,而hashtable中存储经过分词提取出的字符串以及对应的词频。
  4. 计算hashtable全部的字符串出现的几率,即P=字符串的词频/字符串的总数。
  5. 综合hashtable_good与hashtable_bad,推测当一串文本中包含某个字符串时,该文本为垃圾内容的几率,对应的数学表达式以下: P(A|ki) = Pbad(ki) / [ Pgood(ki) +Pbad(ki) ],其中事件A表示文本为垃圾内容,k1,k2 ……kn 表明提取的关键词,而P(A|ki)则表示在文本中出现关键词ki时,该文本为垃圾内容的几率,Pbad(ki)为ti在hashtable_bad中的值,而Pgood(ki)为ki在hashtable_good中的值。
  6. 创建新的hashtable_probability存储字符串ki到P(A|ki)的映射。

行文至此,贝叶斯分类的训练学习过程就完成了,接下来就能够根据hashtable_probability来计算文本为垃圾内容的可能性了。假设用户提交的文本内容通过分词获得n个关键词k1,k2,k3……kn,hashtable_probability中对应的值为 P1,P2……Pn ,P(A|k1,k2,k3……kn) 表示在用户提交的文本中同时出现关键字k1,k2,k3……kn时,该段内容为垃圾文本的几率, P(A|k1,k2,k3……kn) =P1*P2*……Pn 。当P(A|k1,k2,k3……kn)超过预约阈值时,能够判断该内容为垃圾内容,经过调整阀值,能够控制反垃圾系统对于内容过滤的严苛程度。

固然,以上只是简单的二分类状况,随着语料库的丰富,能够将垃圾语料进行细分,好比诈骗、广告、黄色、脏话、人身攻击等等,而且能够根据具体场景进行组合和分级使用,由于不一样的使用场景对于文本中出现垃圾文本的容忍程度是不一样的,要求越严苛的环境,势必误杀的几率也会增长,而且在某个场景下,一些语料可能属于垃圾广告内容,而在其余的场景下,可能又属于正常的内容。举例来讲,若是在电商网站的评价中发现留有QQ、微信、电话等联系方式,颇有可能就属于广告内容,而对于社交应用来讲,则属于正常内容。另外对于一些常见词,须要进行过滤,以减小对几率计算的干扰,词实际上也是有权重的,好比出现某些关键词,文档为垃圾内容的几率显著增长,能够适当提高此类词的权重。

贝叶斯算法的优点是随着语料库的不断丰富,可应对恶意用户层出不穷的“新把戏”。基于训练,算法模型能够发现已知类型的垃圾内容,可是对于新出现的类型,算法模型也无能为力,所以就须要外界的干预。要么经过人工标注,要么采用其余方式(如文本重复度判断),来发现新的垃圾文本类型,丰富训练的语料库。随着语料库的丰富,识别的准确性也会愈来愈高,道高一尺魔高一丈,最终在与恶意用户的斗争过程当中,系统的能力也将愈来愈强大。

黑名单用户

对于频繁发送恶意信息的用户,能够采用禁言一段时间或者是永久禁言的的方式进行应对, 这样就须要维护一份用户黑名单,当用户提交UGC内容的时候,先判断是否在黑名单中,若是已经加入黑名单,则拒绝发表。

黑名单的最简单实现方式莫过于采用hash table,借用redis的hash这一类的数据结构进行内存缓存,而且定时进行持久化或是数据备份,防止宕机致使的数据丢失,这种方式实现简单,查询效率也比较高,能够知足大部分场景的使用,可是缺点也十分的明显,采用hash table的方式随着黑名单列表的增长,占用内存的空间愈来愈大,当业务须要对黑名单按必定场景进行区分和隔离的时候,这种状况尤其明显,而且,黑名单列表越大,hash冲突也将越多,以至于查询的效率也会下降,。当对黑名单过滤要求不那么精确的时候,能够采用Bloom Filter[6](布隆过滤器)的方案。

图11 Bloom Filter的基本原理[7]

Bloom Filter是一个m位的数组,初始状态下数组全部位被置0,须要设置黑名单时,经过一系列不一样的hash函数,每一个hash函数将对应的输入元素映射到数组中的一位上,经过hash函数获得数组的索引,将数组对应位置1,在查询的时候,经过相同的hash函数,找到对应的位,若是对应的位不都为1的话,则表示用户不在黑名单中,那么,当全部的位都为1的状况,就表示用户必定黑名单中么?也不必定,多是其余几回用户输入恰好将本次全部位都置1了,如图11所示,当插入x、y、z这三个元素以后,再来查询w,会发现w不在集合之中,而若是w通过三个hash函数计算所得索引处的位全是1,那么Bloom Filter就会告诉你,w在集合之中,实际上这里是误报,w并不在集合之中,这就是所谓误报。从几率上来讲,误报的概率很低,在系统可接受范围内,如须要100%精确判断,则Bloom Filter就不太合适。

基本的Bloom Filter是不支持删除操做的,Counting Bloom Filter的出现解决了这个问题,它将标准Bloom Filter位数组的每一位扩展为一个小的计数器(Counter),在插入元素时给对应的k(k为哈希函数个数)个Counter的值分别加1,删除元素时给对应的k个Counter的值分别减1,Counting Bloom Filter经过多占用几倍存储空间的代价,给Bloom Filter增长了删除操做,可是相比hash table而言,存储效率仍是提高了不少。

 

图12 Counting Bloom Filter的基本原理[8]

系统稳定性

对于每一年的双十一来讲,如何在大流量高并发场景下,保障系统稳定提供服务不宕机,已是一个经久不衰的话题,也是每一年对于技术人员的一次完全的检阅。从大促开始以前的性能优化、依赖梳理、峰值评估,到系统压力测试,新机器采购上线,再到流控阀值的评估、降级开关配置,再到监控数据采集、容灾应急预案、全链路压测、演习,再到实时、离线数据分析等等,关于这些的介绍,相信网上相关文章都已汗牛充栋,此处就再也不赘述。

总结

本篇主要介绍了阿里直播平台在双十一所面临的一些技术挑战,以及应对的方案和思考过程,从音视频直播架构,到弹幕和消息投递,再到消息通道的技术选型、文本过滤的实现机制,大型直播不管是音视频的可靠性保障、视频鉴黄,仍是文本消息通过数万在线用户放大以后的消息下行,以及对于消息内容自己的过滤,都面临了很大的挑战,挑战不可怕,兵来将挡,水来土掩,迎难而上,才能有突破和创新。

参考文献

  • comet, https://software.intel.com/zh-cn/articles/comet-java-realtime-system-essay
  • WebSocket, https://tools.ietf.org/html/rfc6455
  • WebSocket通讯原理
  • socket.io项目地址: http://socket.io/
  • 贝叶斯分类, https://en.wikipedia.org/wiki/Naive_Bayes_classifier
  • Bloom Filter, http://my.oschina.net/kiwivip/blog/133498
  • 图片来源, http://my.oschina.net/kiwivip/blog/133498
  • 图片来源,http://my.oschina.net/kiwivip/blog/133498
相关文章
相关标签/搜索