redis位图巧用,节约内存
最近要做一个圣诞抽奖活动,需要记录每天用户签到的记录,以前一般都是用普通的字符串数据类型,每个用户的签到用一个 key
// 用户10在活动第一天的签到key为record:1:10
$key = "record:$day:$id";
if ($redis->get($key)) {
echo '已签到';
} else {
$redis->set($key, 1)
}
那么一个用户一天的签到记录就要占一个字节,用户一多就产生非常多的 key,浪费宝贵的内存。
位图
为了解决这个问题,redis 另一种数据类型位图就非常适合。位图并不是特殊的数据类型,内容其实就是字符串,每一位只存储0或1,非常适合存储这种布尔类型的数据
位图使用 setbit/getbit 来存取数据
> SETBIT key offset value
> GETBIT key offset
比如一个用户圣诞连续五天的签到记录可以只使用一个 key, 10010 代表用户只有第二天和第五天签过到
$key = "record:$id";
if ($redis->getbit($key, $day)) {
echo '已签到';
} else {
$redis->setbit($key, $day, 1)
}
现在一个用户五天的签到记录只会产生一个 key,占用内存仅为 5bit 不到一个字节
进一步,如果你的用户系统中用户 id 是连续的 int 类型,还能更节省。因为只记录每个用户5天的签到记录,在一串位图中,每个用户占5个坑,这样所有的用户的签到数据只会使用一个 key
// 用户1占前5个坑
$offset = ($id - 1) * 5 + $day -1;
if ($redis->getbit('record', $offset)) {
echo '已签到';
} else {
$redis->setbit('record', $offset, 1)
}
现在只需要一个 key 就可以存下所有用户的签到记录了。
需要注意的是位图一个 key 最多存储 512mb 的内容,如果你的用户数大于 8*1024*1024*1024*512 / 5 ≈ 87 亿 并不适用这个方法。
其他用法
bitcount 用来统计指定位置范围内 1 的个数,bitpos 用来查找指定范围内出现的第一个 0 或 1。
> setbit s 0 1
> setbit s 3 1 #s=1001
> bitcount s [start, end]
(integer) 2
> bitpos s 0 [start, end]
(integer) 1
redis位图巧用,节约内存的更多相关文章
- Redis实战(18)Redis位图巧用,节约内存
序言 资料 https://www.cnblogs.com/luke44/p/12031078.html
- 节约内存:Instagram的Redis实践(转)
一.问题: 数据库表数据量极大(千万条),要求让服务器更加快速地响应用户的需求. 二.解决方案: 1.通过高速服务器Cache缓存数据库数据 2.内存数据库 三.主流解Ca ...
- 巧用redis位图存储亿级数据与访问 - 简书
原文:巧用redis位图存储亿级数据与访问 - 简书 业务背景 现有一个业务需求,需要从一批很大的用户活跃数据(2亿+)中判断用户是否是活跃用户.由于此数据是基于用户的各种行为日志清洗才能得到,数据部 ...
- 节约内存:Instagram的Redis实践(转)
Instagram可以说是网拍App的始祖级应用,也是当前最火热的拍照App之一,Instagram的照片数量已经达到3亿,而在Instagram里,我们需要知道每一张照片的作者是谁,下面就是Inst ...
- 节约内存:Instagram的Redis实践
Instagram可以说是网拍App的始祖级应用,也是当前最火热的拍照App之一,Instagram的照片数量已经达到3亿,而在Instagram里,我们需要知道每一张照片的作者是谁,下面就是Inst ...
- Redis位图实现用户签到功能
场景需求 适用场景如签到送积分.签到领取奖励等,大致需求如下: 签到1天送1积分,连续签到2天送2积分,3天送3积分,3天以上均送3积分等. 如果连续签到中断,则重置计数,每月初重置计数. 当月签到满 ...
- 基于Redis位图实现用户签到功能
场景需求 适用场景如签到送积分.签到领取奖励等,大致需求如下: 签到1天送1积分,连续签到2天送2积分,3天送3积分,3天以上均送3积分等. 如果连续签到中断,则重置计数,每月初重置计数. 当月签到满 ...
- Redis位图法记录在线用户的状态
Redis位图法记录在线用户的状态 位图 Redis官方文档对于位图的介绍如下: 位图不是一个真实的数据类型,而是定义在字符串类型上的面向位的操作的集合.由于字符串类型是二进制安全的二进制大对象,并且 ...
- Redis(八)理解内存
Redis所有的数据都存在内存中,当前内存虽然越来越便宜,但跟廉价的硬盘相比成本还是比较昂贵,因此如何高效利用Redis内存变得非常重要. 高效利用Redis内存首先需要理解Redis内存消耗在哪里, ...
随机推荐
- IntelliJ IDEA 中设置左菜单字体, 编辑器字体和控制台的字体
IntelliJ IDEA 中设置左菜单字体大小 File-Settings,然后选择appearance,下图右侧红色边框中的内容即设置菜单的字体和大小 IntelliJ IDEA 中设置当前编 ...
- springboot使用dubbo和zookeeper
2019-11-17 yls 创建服务接口模块 接口工程只提供接口,不提供实现,在后面的提供者和消费者中使用 在使用接口的模块中只需要写具体实现类,避免了在每个模块中重复编写接口 在接口中引入依赖包 ...
- mysql中 drop、truncate和delete的区别
mysql中drop.truncate和delete的区别 (1)DELETE语句执行删除的过程是每次从表中删除一行,并且同时将该行的删除操作作为事务记录在日志中保存以便进行进行回滚操作. TRUNC ...
- 理解MySQL数据库事务-隔离性
Transaction事务是指一个逻辑单元,执行一系列操作的SQL语句. 事务中一组的SQL语句,要么全部执行,要么全部回退.在Oracle数据库中有个名字,叫做transaction ID 在关系型 ...
- Android 8.1 自定义热点的时候设置了热点maxLength="32",但是在希伯来语等状态下还是发现在没到32个字符之前就无法把热点设置成功了
初步认为应该是与热点名称的字节数有关. 然后开始查看源码. /Settings/res/xml/tether_prefs.xml 中的 <Preference android:key=" ...
- Java基础知识总结之类的集合
Java集合概述 1.集合类也叫作容器类.它的功能相当于一个容器.可以存储数量不确定的数据,以及保存具有映射关系的数据(也被称为关联数组). 2.Java的集合(容器),它是用来”装对象的“(实际上是 ...
- Django安装和使用---python(3)
一.安装 一般使用cmd 安装就可以 pip install django // 这是最新版本 pip install django==2.0.2(自定义安装2.0.2版本) 手动安装通过下载方式 d ...
- Java设计模式之鸭子模式
这两天在看HeadFirst设计模式,第一种鸭子模式都不太理解.后来在百度知道上看了某大神的解释 明白了不少. 列出如下: 假设我们需要设计出各种各样的鸭子,一边游泳戏水, 一边呱呱叫.很明显这时我们 ...
- Redis集群同步问题
之前被面试官问到:Redis集群中主从数据同步是从库异步读取主库,那么Redis集群其他主与主之间的数据是怎么共享的呢?或者说是怎么同步的? emmmm……当时我就懵逼了,这不是考试范围啊卧槽~只能老 ...
- (四)OpenStack---M版---双节点搭建---Glance安装和配置
↓↓↓↓↓↓↓↓视频已上线B站↓↓↓↓↓↓↓↓ >>>>>>传送门 1.创建glance数据库 2.获得 admin 凭证来获取只有管理员能执行的命令的访问权限 3 ...