闲鱼技术2022年度白皮书-服务端主题-互动抽奖背后的随机性与算法实现(下)

简介: 闲鱼技术2022年度白皮书-服务端主题-互动抽奖背后的随机性与算法实现

接上篇:https://developer.aliyun.com/article/1225740?spm=a2c6h.13148508.setting.29.595d4f0eudDbz0



三、 关于公平的抽奖算法

 

1. “公平”的维度

 

提到抽奖,大家最先想到的,一定是,如何保证抽奖的公平性?

 

而在开始这一部分前,笔者想先阐明一个观点,公平是多维度的,存在用户视角上的公平,客观意义上的公平,算法上的公平等等多种意义上的公平。

 

比如我们完全可以将一种名之为“抽奖”的东西概率设为100%,然后用库存限制抽中,这样所谓抽奖就退化为秒杀,在没有任何暗箱操作的情况下,我们可以说这是完全公平的,但是客观上来说,也可以认为,对网较差、设备性能不佳或晚了一点参与的用户是相当不公平的。

 

所以,反直觉的一点是,其实抽奖的算法也可以不那么公平,因为在任何一个拥有大量参与用户的活动中,用户的参与已经带来了大量的随机性上的因子,在没有提前看过参与用户的前提下,就算由一个值班同学一拍脑袋说今天是第4090位用户中奖,在某种程度上也是个相当公平的算法。所以,抽奖算法也是最容易设计的算法——因为无论你产出的结果分布有多糟糕,也很难被“开盒”唾骂。

 

实际上,在实践经验中,我们往往更要保证的是,结果的存在性和及时性,也就是说,无论你通过什么手段开出来奖,一定要在约定时间内发到有效的用户手上——延迟与无效是工程上能体现出的最致命的问题。

 

2. 真正应该看重的维度

 

不过,除了公平性之外,抽奖其实还有很多其他维度的业务考量:

 

抽奖机会限制,是只能单次参与?还是能一次性多注参与?还是能反复追加的多次参与?

 

开奖时机限制,是希望即时开奖?还是接受参与结束后定时开奖?

 

奖品分布限制,是所有用户争夺唯一大奖?还是分一二三奖的奖品序列?还是瓜分红包或者积分的面额?人人有奖还是基本无奖?

 

并发系统性能限制,同时来参与、来领奖的用户规模和qps如何?是否会影响演算时间和接口延时?

 

根据业务目标的不同,实际开发中,主要还是根据这些维度的特征实现特定的抽奖算法,以下列举几种常用的抽奖算法:

 

当抽奖的奖品粒度是个时

 

1) 选中法

 

image.png


在得知所有参与用户的情况下,我们可以每次直接生成1-n的随机数的方式,抽出中奖用户的编号。

 

这种方法的缺陷是有可能会造成碰撞,需要考虑如何剔除已经中过奖的用户。但是对于用户规模很大的活动来说,碰撞的概率极低,这种方法是最快速的。

 

当然,我们上面也说过,这个方法无论使用的是怎样天花乱坠的随机函数,并不比你拍脑袋写几个固定数字更高明,还不会遇到碰撞。

 

闲鱼内的“百币夺宝”就采用的此方案,因为每个夺宝活动都是唯一的奖品,与用户约定了选中的号码规则,就可以方便快捷的找出中奖用户。

 

2) 洗牌法

 

洗牌法是对整个中奖名单进行一次shuffle,彻底乱序后留在特定位置的用户成为中奖用户。一般认为这种方法造成的I/O次数是最多的,但还是有很多手段可以进行优化的,比如分区处理。它也存在着最佳的应用场景,比如当一个活动人人都能中基本不同的奖品时。

 

image.png


除此之外,它与选中法一样,实施的前提条件,也是必须获得全部的参与用户信息然后处理,对于实时想获知中奖信息或者想快速开奖的活动并不适用。

 

3) 蓄水池抽样法

 

image.png


抽奖本身也可以视作一种抽样,那么蓄水池抽样法就是一个非常适用的开奖法,它在参与人数未确定时就可以开始运作。我们维护一个大小为奖品数量k的奖池,每个用户过来都有k/n的机会与奖池内一个中奖者进行交换,其中n为当前参与规模。可以证明,这样所有用户的中奖记录仍然是均等的。

 

抽样法本质上可以视作shuffle的一种优化,利用参与人数与中奖规模的差异,免去了一些无用的swap操作。但这个优化会带来两点不同,一来,活动时刻维护着中奖列表,可以让活动终止在任何时刻并即刻开奖,无需等待至所有用户参与完毕后再演算开奖;二来,其容错性和鲁棒性会大大提升,很容易并行化,在参与数量比较巨大的情况下,前后执行产生的概率变化非常微小,而且中间任何一个用户操作出错,都不会对系统整体带来什么关键影响。

 

闲鱼内的“回收抽锦鲤”就采用的此方案,对于各不相同的奖品列表,维护大小为k的中奖者列表,最终留在列表内的就是中奖者。

 

瓜分类型的算法,比如瓜分现金红包或者积分,抽奖的粒度是分

 

4) 瓜分红包算法

 

最著名的自然是微信的瓜分红包算法,每个人瓜分的红包额度是这样计算的,先给每个人瓜分0.01元,然后加上rand0~剩余平均红包金额的两倍,而最后一个人拿到剩余所有钱。

 

这个算法可以保证大家瓜分的期望金额是相同的,但方差会越来越大,从而导致中最大奖的概率在各位置上是不同的。局限性在于,这个算法还是利用了一个先验信息,即参与人数n,需要发红包者预先选择好能领取的数量。

 

其最大的优势是不需要等到所有参与信息都获得之后进行,可以实时开奖。但同时,最大的问题是因为强依赖了“红包剩余金额”这个信息,并发性会比较差,往往还是需要提前演算出结果,无法应对实时高并发的场景。

 

闲鱼内的现金夺宝就采用了这种算法,但是由于参与规模特别巨大,往往是将奖池与参与用户划分为若干批次再进行的开奖。

 

“不公平”但最好用的抽奖算法

 

5) 概率法

 

有时候我们希望用户能即时开出奖来,这个时候我们并不知道整场活动的全貌,只能靠一些先验的经验来决定当前用户的中奖概率,在发奖时实时由概率计算用户是否中奖,比如在奖池内提前规定A奖品中奖概率30%。

 

但概率法并不公平。由于奖品数量有限,库存会消耗光的缘故,对于固定中奖概率来说,后来的中奖概率是小于原来的中奖概率的,假设我们仅有一个奖品一个库存的话,每个人过来的中奖概率应当需要为,才能保证用户无论什么时候参与概率都是相等的。可以看到,这个式子不但计算麻烦,会产生并发问题,居然还有规模限制。而有多个库存的情况下,情况将会更复杂。

 

image.png


实际场景中上我们还有很多其他因素的干扰,特别是业务本身的决策,比如我们并不希望一开始就放出所有库存,中途才放出一点点库存。或者我们希望中奖库存是随着时间过去均匀的消耗掉的,这样我们就有更多的动机去调节这个本来就不公平的概率算法。所以说,概率法,是离客观公平最远的算法。

 

但是,我们一开始的讨论也说明,这部分的不公平只是存在于理论上,如果我们没有人为操控使特定人中奖,在任何用户都是黑盒的情况下,我们还是可以认为,这是公平的,因为用户没有机会判断得知,究竟这个活动的概率分布呈现什么样的情况,从而实现套利。用户只能通过一些经验化的谣言,比如“大额券总是在活动末期要冲量时才会放出”,或者“活动初期中奖概率更高”,来控制参与时机进行博弈。

 

所以,这里的“不公平”打上了引号,事实是概率法由于其充分的运营空间和简明的规则,反而成为应用最广的抽奖方式。

 

值得一提的是,概率法可以采用“概率保持”策略来应对部分奖品库存耗尽或者命中限中的情况,即该部分概率由其他奖品按概率比例再分配,也可以简单做到保证必中。

 

在工程实现上,以上的算法其实都可以在规模到一定程度时,进行分布式优化,将奖池和参与者分而治之;也完全可以在方法间互相结合,来达到想要的业务效果。

 

四、 小结

 

本篇文章从随机数和抽奖算法两个基础的层面,浅显地探讨了一些关于互动抽奖的内容,从最底层实现层面形叙述了抽奖的基本逻辑,但万丈高楼平地起,选定了算法,只是实现十万百万级在线用户参与的抽奖互动玩法的第一步。实际上,抽奖作为在无数互动场都屡试不爽的玩法,在业务实践中有着更复杂的场景与问题,接下来还有关于权益发放,关于用户驱动,以及关于抽奖玩法模型本身的更多内容,敬请期待。

 

相关文章
|
6月前
|
人工智能 运维 算法
基于 C# 深度优先搜索算法的局域网集中管理软件技术剖析
现代化办公环境中,局域网集中管理软件是保障企业网络高效运行、实现资源合理分配以及强化信息安全管控的核心工具。此类软件需应对复杂的网络拓扑结构、海量的设备信息及多样化的用户操作,而数据结构与算法正是支撑其强大功能的基石。本文将深入剖析深度优先搜索(Depth-First Search,DFS)算法,并结合 C# 语言特性,详细阐述其在局域网集中管理软件中的应用与实现。
148 3
|
2月前
|
运维 监控 算法
基于 Java 滑动窗口算法的局域网内部监控软件流量异常检测技术研究
本文探讨了滑动窗口算法在局域网流量监控中的应用,分析其在实时性、资源控制和多维分析等方面的优势,并提出优化策略,结合Java编程实现高效流量异常检测。
98 0
|
3月前
|
监控 算法 安全
基于 C# 基数树算法的网络屏幕监控敏感词检测技术研究
随着数字化办公和网络交互迅猛发展,网络屏幕监控成为信息安全的关键。基数树(Trie Tree)凭借高效的字符串处理能力,在敏感词检测中表现出色。结合C#语言,可构建高时效、高准确率的敏感词识别模块,提升网络安全防护能力。
102 2
|
5月前
|
监控 算法 JavaScript
基于 JavaScript 图算法的局域网网络访问控制模型构建及局域网禁止上网软件的技术实现路径研究
本文探讨局域网网络访问控制软件的技术框架,将其核心功能映射为图论模型,通过节点与边表示终端设备及访问关系。以JavaScript实现DFS算法,模拟访问权限判断,优化动态策略更新与多层级访问控制。结合流量监控数据,提升网络安全响应能力,为企业自主研发提供理论支持,推动智能化演进,助力数字化管理。
141 4
|
5月前
|
存储 监控 算法
内网监控桌面与 PHP 哈希算法:从数据追踪到行为审计的技术解析
本文探讨了内网监控桌面系统的技术需求与数据结构选型,重点分析了哈希算法在企业内网安全管理中的应用。通过PHP语言实现的SHA-256算法,可有效支持软件准入控制、数据传输审计及操作日志存证等功能。文章还介绍了性能优化策略(如分块哈希计算和并行处理)与安全增强措施(如盐值强化和动态更新),并展望了哈希算法在图像处理、网络流量分析等领域的扩展应用。最终强调了构建完整内网安全闭环的重要性,为企业数字资产保护提供技术支撑。
150 2
|
6月前
|
机器学习/深度学习 存储 算法
18个常用的强化学习算法整理:从基础方法到高级模型的理论技术与代码实现
本文系统讲解从基本强化学习方法到高级技术(如PPO、A3C、PlaNet等)的实现原理与编码过程,旨在通过理论结合代码的方式,构建对强化学习算法的全面理解。
1324 10
18个常用的强化学习算法整理:从基础方法到高级模型的理论技术与代码实现
|
6月前
|
存储 监控 算法
基于 Python 哈希表算法的局域网网络监控工具:实现高效数据管理的核心技术
在当下数字化办公的环境中,局域网网络监控工具已成为保障企业网络安全、确保其高效运行的核心手段。此类工具通过对网络数据的收集、分析与管理,赋予企业实时洞察网络活动的能力。而在其运行机制背后,数据结构与算法发挥着关键作用。本文聚焦于 PHP 语言中的哈希表算法,深入探究其在局域网网络监控工具中的应用方式及所具备的优势。
169 7
|
6月前
|
运维 监控 算法
基于 Python 迪杰斯特拉算法的局域网计算机监控技术探究
信息技术高速演进的当下,局域网计算机监控对于保障企业网络安全、优化资源配置以及提升整体运行效能具有关键意义。通过实时监测网络状态、追踪计算机活动,企业得以及时察觉潜在风险并采取相应举措。在这一复杂的监控体系背后,数据结构与算法发挥着不可或缺的作用。本文将聚焦于迪杰斯特拉(Dijkstra)算法,深入探究其在局域网计算机监控中的应用,并借助 Python 代码示例予以详细阐释。
158 6
|
7月前
|
人工智能 监控 算法
Python下的毫秒级延迟RTSP|RTMP播放器技术探究和AI视觉算法对接
本文深入解析了基于Python实现的RTSP/RTMP播放器,探讨其代码结构、实现原理及优化策略。播放器通过大牛直播SDK提供的接口,支持低延迟播放,适用于实时监控、视频会议和智能分析等场景。文章详细介绍了播放控制、硬件解码、录像与截图功能,并分析了回调机制和UI设计。此外,还讨论了性能优化方法(如硬件加速、异步处理)和功能扩展(如音量调节、多格式支持)。针对AI视觉算法对接,文章提供了YUV/RGB数据处理示例,便于开发者在Python环境下进行算法集成。最终,播放器凭借低延迟、高兼容性和灵活扩展性,为实时交互场景提供了高效解决方案。
483 5

热门文章

最新文章