`

使用redis队列实现抢红包

阅读更多
使用redis队列实现抢红包

(1)1个大红包生成n份小红包,保存到数据库

(2)每个大红包对应两个redis队列,一个是未消费红包队列,另一个是已消费红包队列。开始时,把未抢的小红包全放到未消费红包队列里。
未消费红包队列里是json字符串,如{userId:'', money:'300', id:''}。

(3)判断是否领取过?
在redis中用一个map来过滤已抢到红包的用户。
抢红包时,先判断用户是否抢过红包,如果没有,则从未消费红包队列中取出一个小红包,
再push到另一个已消费队列中,最后把用户ID放入去重的map中。

(4)用一个单线程批量把已消费队列里的红包取出来,再批量update领取红包的用户ID到数据库里。

red_packet表中增加一个状态status:小红包是否存入数据库 1-已保存

问题:
什么时候更新大红包的状态?

某个用户发送红包:createSmallRedPackets(总金额, 红包数)
其他用户抢红包:grapRedPacketRedis(大红包id, 用户id)

大红包分的小红包可以放在定时任务里,这样就避免了与数据库的交互,更加节省时间

redis如何保存key-map<String,String>及对map的操作 -使用hash替代   用field字段保存用户id

public interface IRedPacketService {

/**
   * 获取红包信息.
   * @param id --红包id
   * @return 红包具体信息
   */
  public RedPacketPO getRedPacket(Integer id);
 
  /**
   * 扣减抢红包数.
   * @param id -- 红包id
   * @return 更新记录条数
   */
  public int decreaseRedPacket(Integer id);
 
  /**
   * 抢红包
   * @param redPacketId 红包id
   * @param userId 用户id
   * @return 影响记录数.
   */
  public int grapRedPacket(Integer redPacketId, Integer userId);
 
  /**
   * 抢红包 使用存储过程
   * @param redPacketId 红包id
   * @param userId 用户id
   * @return 影响记录数.
   */
  public int grapRedPacketProc(Integer redPacketId, Integer userId);
 
  /**
   * 生成小红包并放入redis队列
   * @param amount
   * @param count
   */
  public void createSmallRedPackets(double amount, Integer count);
 
  /**
   * 通过redis队列来抢红包
   * @param redPacketId
   * @param userId
   * @return
   */
  public int grapRedPacketRedis(Integer redPacketId, Integer userId);
 
  /**
   * 更新大红包状态 0-未保存 1-已存入数据库
   * @param po
   * @return
   */
  int updateRedPacketStatus(RedPacketPO po);
 
  /**
   * 获取小红包未入库的大红包信息
   * @return
   */
  List<RedPacketPO> getRedPacketByStatus();
}

create table red_packet
(
   id                   int(12)     auto_increment COMMENT '红包编号',
   user_id              int(12)                        COMMENT '发红包的用户id',
   amount               decimal(16,2)                  COMMENT '红包金额',
   send_date            timestamp                      DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '发红包日期',
   total                int(12)                        COMMENT '红包总数',
   unit_amount          decimal(12)                    COMMENT '单个红包的金额',
   stock                int(12)                        COMMENT '红包剩余个数',
   version              int(12) default 0              COMMENT '版本号',
   status               char(1) comment '状态 0-未入库 1-已保存到数据库',
   primary key(id)
);
用户抢红包表
create table red_packet_user
(
   id                   int(12)                        auto_increment COMMENT '用户抢到的红包id',
   red_packet_id        int(12)                        COMMENT '大红包id',
   user_id              int(12)                        COMMENT '抢红包用户的id',
   amount               decimal(16,2)                  COMMENT '抢到的红包金额',
   grab_time            timestamp                      DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '抢红包时间',
   note                 varchar(256)                   null COMMENT '备注',
   primary key(id)
);

insert into red_packet(user_id, amount, send_date, total, unit_amount, stock,status)
values(1, 10000, now(), 2000, 5, 2000,'0');


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics