利用redis的bitmap实现用户签到功能

一、场景需求

适用场景如签到送积分、签到领取奖励等,大致需求如下:

  • 比如签到1天送1积分,连续签到2天送2积分,3天送3积分,3天以上均送3积分等。
  • 如果连续签到中断,则重置计数,每月初重置计数。
  • 显示用户某个月的签到次数和首次签到时间。
  • 在日历控件上展示用户每月签到情况,可以切换年月显示……等等。

二、代码

以下代码没有积分逻辑,只有签到

import datetime
import redis

class Redis(object):
    def __init__(self):
        self.redis_store = redis.Redis(
            host="127.0.0.1",
            port="6379",
            db="8"
        )


class RedisSignIn(Redis):
    @staticmethod
    def GetDaliySignKey(time=datetime.datetime.now()):
        # 拼接redis的key
        bitmap_key_daily_sign = "daily_sign_{date}"
        return bitmap_key_daily_sign.format(date=time.date())

    def UserDailySign(self, session):
        user_id = session.get("user")
        if not user_id:
            print( "验证失败")
            return
        if self.UserDaliySignByUserId(user_id):
            rec = self.GetSignRecordByUserId(user_id, 7)
            l = len(rec.split('0')[0])
            print(l)
            # 连续签到
            if l > 1:
                pass
            if l > 6:
                pass
        return
    # 获取每月的签到记录
    def GetUserDailySignRecordMonthly(self, session):
        user_id = session.get("user")
        if not user_id:
            print( "验证失败")
            return
        res = self.GetSignRecordByUserId(user_id)
        print(int(res, 2))
        # 二进制数据转换为10进制,拿到的10进制数返回到前端,前端再解析成二进制数进行判断
        return int(res, 2)


    def GetSignRecordByUserId(self, user_id, days=30):
        # 开启管道模拟事务
        with self.redis_store.pipeline(True) as p:
            for i in range(days):
                # 获取key对应值的二进制表示中的某位的值
                p = p.getbit(self.GetDaliySignKey(datetime.datetime.now() - datetime.timedelta(days=i)), user_id)
            # execute返回命令执行结果列表
            res = p.execute()
            # res是一个[1,0,0,0...]的列表
            print(res)
            # 转成字符串的二进制
            return ''.join([str(x) for x in res])

    # 通过user_id用户做每日签到
    def UserDaliySignByUserId(self, user_id):
        if self.GetDailySignByUserId(user_id):
            print( "今天您已签到")
            return
        key = self.GetDaliySignKey()
        # key就是签到日期,将该user_id在key对应的位置上设置为1,表示签到了
        self.redis_store.setbit(key, user_id, 1)
        # 设置key的过期时间
        self.redis_store.expire(key, 60 * 60 * 24 * 30)
        return True

    # 通过user_id获取用户每日签到信息
    def GetDailySignByUserId(self, user_id):
        return self.redis_store.getbit(self.GetDaliySignKey(), user_id)


if __name__ == '__main__':
    session={"user":1003}
    sign=RedisSignIn()
    sign.UserDailySign(session)
    sign.GetUserDailySignRecordMonthly(session)

 

posted @ 2019-07-18 16:49  Maple_feng  阅读(3439)  评论(0编辑  收藏  举报