zoukankan      html  css  js  c++  java
  • 利用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)
  • 相关阅读:
    自动支持图片webp格式压缩,图片服务器升级webserver
    长江商学院介绍及名人校友名单
    恒大许家印靠斗着地主,当上首富
    用GitLab搭建自己的私有GitHub
    vim快速定位到某一行的几种方法和显示行号,定位匹配字符串,显示当前行信息的命令
    mysql数据库表上百万记录优化思路杂谈
    Java打印输出数组的三种方式:传统的for循环方式,for each循环,利用Arrays类中的toString方法
    个人快速成长之系统方法,最小化成长系统
    程序员应该了解的常见软件开发定律
    用python修改文件内容修改txt内容的3种方法
  • 原文地址:https://www.cnblogs.com/angelyan/p/11208370.html
Copyright © 2011-2022 走看看