专栏名称: i小声读书
「电子书支援计划」是一个以电子书为核心的自我学习计划, 以 Telagram 社群为主要载体,致力于促进中文互联网圈内 的知识交流和资源共享,帮助诸位获得更好的阅读资源和阅 读体验,同时鼓励社群内成员输出优质内容。
目录
相关文章推荐
中国国家地理  ·  「甲行天下」与中华旗舰种同行 ·  15 小时前  
Marine Sedimentology  ·  GRL:放射性核素解密长江水下三角洲侵蚀的级联效应 ·  22 小时前  
中国国家地理  ·  被这种重庆完全震撼 ·  昨天  
中国国家地理  ·  掉下来的"星星",原来在这里就能捡到...... ·  昨天  
安徽省发展改革委  ·  安徽省新能源汽车产业集群建设企业巡展——【2 ... ·  昨天  
安徽省发展改革委  ·  安徽省新能源汽车产业集群建设企业巡展——【2 ... ·  昨天  
51好读  ›  专栏  ›  i小声读书

基于 Redis 实现简单的红包分配算法

i小声读书  · 公众号  ·  · 2019-02-08 09:53

正文


# 编程 # 红包


作者 / 橱柜扫地僧


去看了《流浪地球》,中国人到了任何时候都想着放烟花嘞 🤔, 不过这已经是一部很好的科幻片了:


  • 中国人终于在仰望星空了,而非嫦娥奔月,也就是向外;

  • 农耕民族带着自己的土地(地球)寻找新的家园,符合中国文化;

  • 没有圣母,没有圣母,没有圣母!

建议都去看看

除了烟花,春节怕是离不开红包。春节红包满天飞,在好友群里面可以抢到最大的红包也算是一件高兴的事情了。对于微信红包机制的研究很多,这里就展示一种基于 Redis 实现简单的红包分配算法,逻辑简单,5分钟就可以看完。


下载代码

https://github.com/woojean/demos/tree/master/redis-hongbao


/** 
* 生成红包函数
* $totalMoney 总金额
* $num 红包数量
* $min 红包最小值
*/function gen($totalMoney, $num, $min='0.01'){
  // 分配结果  $ret = [];
  
  // 剩余红包金额  $remainMoney = $totalMoney;  
  
  for ( $i = 1; $i < $num; $i++) {
    // 剩余红包数量    $remainNum = $num-$i;  
    
    // 当前可领取的红包的最大值    $remainMax = ($remainMoney-$remainNum*$min)/$remainNum;  
    
    $allocateMoney = mt_rand($min*100, $remainMax*100)/100;
    $remainMoney = $remainMoney-$allocateMoney;
    $ret[$i] = array(
      'allocation' => $allocateMoney,
      'remainder' => $remainMoney
    );
  }

  // 处理最后一个  $ret[$num] = [
    'allocation'=>$remainMoney,
    'remainder'=>0
  ];
  
  return $ret;}// ======================= demo ========================// 红包总金额$totalMoney = 10;  // 红包总数$num = 10;  $redis = new Redis();$redis->connect('127.0.0.1', 6379);// 库存队列$mapStock = 'queue_stock';  // 已抢队列 uid => hongbao$mapGrab = 'queue_grab';  // 剩余红包索引 
$listIndexs = 'list_indexs';  $allocated = $redis->hlen($mapGrab);if($allocated == $num){
  echo '已抢光!';
  exit;}$inited = $redis->hlen($mapStock);// 如果索引尚未生成,生成红包库存if( 0 == $inited ){
  // 生成红包库存  $stock = gen($totalMoney,$num);  

  // 存储红包索引  foreach($stock as $index => $hongbao){
    $redis->hset($mapStock, $index, json_encode($hongbao));
    $redis->lpush($listIndexs,$index);
  }}// 获取用户ID$uid = intval($_GET['uid']);if( $uid < 1){
  echo '用户ID非法!';
  exit;}// 判断用户是否已经抢过红包$participated = $redis->hexists($mapGrab,$uid);if($participated){
  echo '不能重复参加!';
  exit;}// 分配红包给用户(原子操作,关键!)$index = $redis->lpop($listIndexs);if(intval($index) < 1){
  echo '已抢光!';
  exit;}// todo 操作失败后,将红包的索引push回去$hongbao = $redis->hget($mapStock, $index);$redis->hset($mapGrab, $uid, json_encode($hongbao));echo $uid.' -> ' . json_encode($hongbao);









请到「今天看啥」查看全文