Redis简单案例(三) 连续登陆活动的简单实现
连续登陆活动,或许大家都不会陌生,简单理解就是用户连续登陆了多少天之后,系统就会送一些礼品给相应的用户。最常见的
莫过于游戏和商城这些。游戏就送游戏币之类的东西,商城就送一些礼券。正值国庆,应该也有不少类似的活动。
下面就对这个的实现提供两个思路,并提供解决方案。
思路1(以用户为维度):
他的登陆情况,就可以得到类似这样的一个二进制序列:1110111,如果是7个1,就表示连续7天,如果不是7个1就表示没有连续登
陆7天。所以就能实现这个登陆活动的要求了。
思路2(以天数为维度):
一天之内,用户要么是登陆过,要么是没有登陆过。同样的用1来表示登陆过,用0表示没有登陆过。假设我们连续登陆的活动是2天,
同时有3个用户,那么就要有2个key去存储这3个用户的登陆信息,这样就会得到类似这样的两个二进制序列:101(key1),111(key2)。
此时,对这两个key的每一位都进行逻辑与运算,就会得到101,就表明,用户1和用户3连续登陆了两天。从而达到活动的要求。
下面就简单模拟一下国庆7天假期连续登陆七天的活动。
方案1 :以用户为维度
这时我们就会得到每个用户对应的二进制序列,然后就可以用bitcount命令去得到key含有的1的个数。如果等于7,就是连续登陆了
七天。这样就可以在第七天用户登陆的时间去处理了是否发送礼品了。处理的逻辑是十分简单的。控制器简单逻辑如下:
1 [HttpPost] 2 public IActionResult LoginForEveryone() 3 { 4 Random rd = new Random(); 5 var tran = _redis.GetTransaction(); 6 for (int i = 0; i < 7; i++) 7 { 8 for (int j = 0; j < 1000; j++) 9 { 10 string activity_key = string.Format("holiday:{0}", j.ToString()); 11 // login 1(true) other 0(false) 12 if (rd.Next(0,10) > 6) 13 { 14 tran.StringSetBitAsync(activity_key, i, true); 15 } 16 } 17 } 18 tran.ExecuteAsync(); 19 20 List<int> res = new List<int>(); 21 for (int i = 0; i < 1000; i++) 22 { 23 string activity_key = string.Format("holiday:{0}", i.ToString()); 24 //7 days 25 if (_redis.BitCount(activity_key) == 7) 26 { 27 res.Add(i); 28 } 29 } 30 return Json(new { code = "000", data = res, count = res.Count }); 31 }
登陆的天数。这是一次性模拟操作,与正常情况的登陆操作还是有些许不同的。大致如下:
1 [HttpPost] 2 public IActionResult LoginForEveryone() 3 { 4 //1.login and get the identify of user 5 //2.get the Current day and write to redis 6 string activity_key = string.Format("holiday:{0}", "identify of user"); 7 _redis.SetBit(activity_key, currend day, true); 8 //3.send gift 9 if(currend day==7&& _redis.BitCount(activity_key)==7) 10 { 11 send gift 12 } 13 return ...; 14 }
回到我们模拟的情况,在界面展示时,模拟登陆后会显示累计登陆用户的id。
1 <script id="everyoneTpl" type="text/html"> 2 <span>total:{{count}}</span> 3 <ul> 4 {{each data as item}} 5 <li> 6 {{item}} 7 </li> 8 {{/each}} 9 </ul> 10 </script> 11 <script> 12 $(function () { 13 $("#btn_everyone").click(function () { 14 $.ajax({ 15 url: "/Holiday/LoginForEveryone", 16 dataType: "json", 17 method:"post", 18 success: function (res) { 19 if (res.code == "000") { 20 var html = template('everyoneTpl', res); 21 $("#div_everyone").html(html); 22 } 23 } 24 }) 25 }); 26 }) 27 </script>
这样的话就要让我们的用户标识是数字才行,如果是用guid做的用户标识就要做一定的处理将其转化成数字,这样方便我们
在给用户设置是否登陆。现在假设我们的用户标识是从1~1000。用户标识对应的就是在key中的偏移量。这时我们就会得到每天
对应的二进制序列,然后就可以用bitop命令去得到逻辑与运算之后的key/value。如果这个key对应偏移量(用户标识)是1,就是
连续登陆了七天,处理的逻辑是十分简单的。控制器简单逻辑如下:
1 [HttpPost] 2 public IActionResult LoginForEveryday() 3 { 4 var tran = _redis.GetTransaction(); 5 6 for (int i = 0; i < 7; i++) 7 { 8 for (int j = 0; j < 1000; j++) 9 { 10 //i day,j userId 11 SetBit(i, j, tran); 12 } 13 } 14 tran.Execute(); 15 //get the result 16 _redis.BitOP(_bitWise, _res, _redisKeys.ToArray()); 17 IList<int> res = new List<int>(); 18 for (int i = 0; i < 1000; i++) 19 { 20 if (_redis.GetBit(_res, i) == true) 21 { 22 res.Add(i); 23 } 24 } 25 return Json(new { code = "000", data = res, count = res.Count }); 26 } 27 28 29 private void SetBit(int day, int userId, StackExchange.Redis.ITransaction tran) 30 { 31 switch (day) 32 { 33 case 0: 34 if (_rd.Next(0, 10) > 3) 35 { 36 tran.StringSetBitAsync(_first, userId, true); 37 } 38 else 39 { 40 tran.StringSetBitAsync(_first, userId, false); 41 } 42 break; 43 case 1: 44 if (_rd.Next(0, 10) > 3) 45 { 46 tran.StringSetBitAsync(_second, userId, true); 47 } 48 else 49 { 50 tran.StringSetBitAsync(_second, userId, false); 51 } 52 break; 53 case 2: 54 if (_rd.Next(0, 10) > 3) 55 { 56 tran.StringSetBitAsync(_thrid, userId, true); 57 } 58 else 59 { 60 tran.StringSetBitAsync(_thrid, userId, false); 61 } 62 break; 63 case 3: 64 if (_rd.Next(0, 10) > 3) 65 { 66 tran.StringSetBitAsync(_fourth, userId, true); 67 } 68 else 69 { 70 tran.StringSetBitAsync(_fourth, userId, false); 71 } 72 break; 73 case 4: 74 if (_rd.Next(0, 10) > 3) 75 { 76 tran.StringSetBitAsync(_fifth, userId, true); 77 } 78 else 79 { 80 tran.StringSetBitAsync(_fifth, userId, false); 81 } 82 break; 83 case 5: 84 if (_rd.Next(0, 10) > 3) 85 { 86 tran.StringSetBitAsync(_sixth, userId, true); 87 } 88 else 89 { 90 tran.StringSetBitAsync(_sixth, userId, false); 91 } 92 break; 93 case 6: 94 if (_rd.Next(0, 10) >3) 95 { 96 tran.StringSetBitAsync(_seventh, userId, true); 97 } 98 else 99 { 100 tran.StringSetBitAsync(_seventh, userId, false); 101 } 102 break; 103 default: 104 break; 105 } 106 }
可以看到76和991这两个偏移量(用户标识)对应的二进制位是1,也验证了其连续登陆了7天。当然,更多的明细数据也贴出来了
方案 | 优点 | 缺点 |
以用户为维度 |
1.可以无缝对接,无论用户标识是数字还是其他 2.key对应的数据较少便于观察 |
随着用户数量的增长,要管理的key会越来越多 |
以天数为维度 |
1.有确定数量的key,方便管理 2.key对应的基数大 |
1.偏移量可能需要根据实际情况处理 2.数据查看不是很清晰 |
可至于实际中用那种方案更合适,要根据情况来选择。用户量少的时候,可以用第一种方案,也可以用第二种方案,当用户量很大的时候,
Redis简单案例(三) 连续登陆活动的简单实现相关推荐
- Redis简单案例(二) 网站最近的访问用户
原文:Redis简单案例(二) 网站最近的访问用户 我们有时会在网站中看到最后的访问用户.最近的活跃用户等等诸如此类的一些信息.本文就以最后的访问用户为例, 用Redis来实现这个小功能.在这之前,我 ...
- Redis简单案例(四) Session的管理
Redis简单案例(四) Session的管理 原文:Redis简单案例(四) Session的管理 负载均衡,这应该是一个永恒的话题,也是一个十分重要的话题.毕竟当网站成长到一定程度,访问量自然也是 ...
- sql案例分析:统计连续登陆、日活、蚂蚁森林、排名等
# 当天新用户hive -e \'select count(1) from hm2.daily_helper \where guid not in (select guid from hm2.hist ...
- Android复习12【广播接收者-BroadcastReceiver(简单案例-发送广播、静态注册、动态注册、本地广播、代码示例(别处登陆踢用户下线)、常用系统广播总结、音乐播放器)】
2020-04-28[11周-周二] 音乐播放器Android代码下载:https://wws.lanzous.com/ifqzihaxvij 目 录 简单案例-发送广播 2)动态注册实例(监听网 ...
- zabbix生产环境案例(三)
生产环境案例(三) 链接:https://pan.baidu.com/s/1q5YwJMTcZLcS5OQ0iOu44A 提取码:8gdi 复制这段内容后打开百度网盘手机App,操作更方便哦 1. Z ...
- 简单冲裁模、连续冲裁模、复合冲裁模,你搞懂了吗?
一.冲裁模具按工序组合程度可分为:简单冲裁模.连续冲裁模.复合冲裁模. (一)简单冲裁模即敞开模 1.定义:它是指在一次冲裁中只完成冲孔或落料的一个工序. 2.简单冲裁模按其导向方式可分为: (1)无 ...
- Spring认证中国教育管理中心-Spring Data Redis框架教程三
原标题:Spring认证中国教育管理中心-Spring Data Redis框架教程三 10.15.支持类 Packageorg.springframework.data.redis.support提 ...
- Redis故障案例(一)-特定key批量丢失
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/n88Lpo/article/details/78591111 作者:RogerZhuo 来源:DBA ...
- 数据分析与挖掘 - R语言:贝叶斯分类算法(案例三)
案例三比较简单,不需要自己写公式算法,使用了R自带的naiveBayes函数. 代码如下: > library(e1071)> classifier<-naiveBayes(iris ...
最新文章
- 谈谈android反编译和防止反编译的方法
- ML之HierarchicalClustering:自定义HierarchicalClustering层次聚类算法
- C++类中成员变量的初始化有两种方式
- 在国外当程序员是什么体验?
- app后端设计(php)
- Tomcat为Cookie设置HttpOnly属性
- MySQl中文1001无标题_Mysql中字段类型不一致导致索引无效的处理办法
- mysql更新数据库中int 1_Mysql数据库int(1)和tinyint(1)的区别扩展阅读
- 属猴的人2021年运势预测
- 找不到Share Project(Subversion)_android studio
- ArcMAp10.2生成栅格数据时报错
- E - 娜娜梦游仙境系列——莫名其妙的插曲
- 电脑录音软件哪个好?六款常见的录音软件介绍
- docker使用阿里云Docker镜像库加速
- 服务器主机防护系统有哪些,什么是DDoS防护主机?
- wingide运行两个项目_Wing IDE使用教程:部分调试功能介绍
- Tesseract(识别验证码)
- 第二讲 中国古代密码艺术
- Buct oj 1015
- Ubuntu20.04修改root用户密码
热门文章
- python3抓取b站弹幕_python3写爬取B站视频弹幕功能
- iCMS v8.0.0多终端内容管理系统
- 魔众商城系统源码 v4.0.0 beta
- 安装服务器加硬盘分区,DOL服务器硬盘分区与安装模式
- oracle udev 多路径,Suse 11下多路径及udev配置
- 怎么让图片从左往右移动php,javascript - 想让图片上那个块,在增加块的宽度的时候向右边移动,而不是向左边移动。需要怎么解决?...
- 高性能JavaScript DOM编程
- DNS攻击原理与防范
- 视差滚动的爱情故事之优化篇
- 为facebook添加html/iframe页面 Create A Facebook Landing Page (Static HTML / iFrame)