最近要做一个圣诞抽奖活动,需要记录每天用户签到的记录,以前一般都是用普通的字符串数据类型,每个用户的签到用一个 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位图巧用,节约内存的更多相关文章

  1. Redis实战(18)Redis位图巧用,节约内存

    序言 资料 https://www.cnblogs.com/luke44/p/12031078.html

  2. 节约内存:Instagram的Redis实践(转)

    一.问题:     数据库表数据量极大(千万条),要求让服务器更加快速地响应用户的需求. 二.解决方案:      1.通过高速服务器Cache缓存数据库数据      2.内存数据库 三.主流解Ca ...

  3. 巧用redis位图存储亿级数据与访问 - 简书

    原文:巧用redis位图存储亿级数据与访问 - 简书 业务背景 现有一个业务需求,需要从一批很大的用户活跃数据(2亿+)中判断用户是否是活跃用户.由于此数据是基于用户的各种行为日志清洗才能得到,数据部 ...

  4. 节约内存:Instagram的Redis实践(转)

    Instagram可以说是网拍App的始祖级应用,也是当前最火热的拍照App之一,Instagram的照片数量已经达到3亿,而在Instagram里,我们需要知道每一张照片的作者是谁,下面就是Inst ...

  5. 节约内存:Instagram的Redis实践

    Instagram可以说是网拍App的始祖级应用,也是当前最火热的拍照App之一,Instagram的照片数量已经达到3亿,而在Instagram里,我们需要知道每一张照片的作者是谁,下面就是Inst ...

  6. Redis位图实现用户签到功能

    场景需求 适用场景如签到送积分.签到领取奖励等,大致需求如下: 签到1天送1积分,连续签到2天送2积分,3天送3积分,3天以上均送3积分等. 如果连续签到中断,则重置计数,每月初重置计数. 当月签到满 ...

  7. 基于Redis位图实现用户签到功能

    场景需求 适用场景如签到送积分.签到领取奖励等,大致需求如下: 签到1天送1积分,连续签到2天送2积分,3天送3积分,3天以上均送3积分等. 如果连续签到中断,则重置计数,每月初重置计数. 当月签到满 ...

  8. Redis位图法记录在线用户的状态

    Redis位图法记录在线用户的状态 位图 Redis官方文档对于位图的介绍如下: 位图不是一个真实的数据类型,而是定义在字符串类型上的面向位的操作的集合.由于字符串类型是二进制安全的二进制大对象,并且 ...

  9. Redis(八)理解内存

    Redis所有的数据都存在内存中,当前内存虽然越来越便宜,但跟廉价的硬盘相比成本还是比较昂贵,因此如何高效利用Redis内存变得非常重要. 高效利用Redis内存首先需要理解Redis内存消耗在哪里, ...

随机推荐

  1. tarjan学习(复习)笔记(持续更新)(各类找环模板)

    题目背景 缩点+DP 题目描述 给定一个n个点m条边有向图,每个点有一个权值,求一条路径,使路径经过的点权值之和最大.你只需要求出这个权值和. 允许多次经过一条边或者一个点,但是,重复经过的点,权值只 ...

  2. 【WPF on .NET Core 3.0】 Stylet演示项目 - 简易图书管理系统(3) - 使用Conductor切换页面

    前两章中, 我们已经实现了这个图书管理系统的登录窗口, 并实施了完善的单元测试. 该是时候回过头来关注我们的主窗口了. 一个功能丰富的系统一般会有多个页面, 我们图书管理系统虽然是"简易&q ...

  3. Vmware虚拟机的安装

    Vmware WorkStation是一款桌面计算机虚拟软件,能够让用户在单一主机上同时运行多个不同的操作系统.每个虚拟操作系统的硬盘分区.数据配置都是独立的,同时又可以将多台虚拟机构建为一个局域网. ...

  4. jquery 数字滚动方法

    jquery 数字滚动方法用的是countUp.js这个插件 target = 目标元素的 ID:startVal = 开始值:endVal = 结束值:decimals = 小数位数,默认值是0:d ...

  5. php debug_backtrace方法跟踪代码调用

    php debug_backtrace方法跟踪代码调用<pre>function string 当前的函数名,参见: __FUNCTION__.line integer 当前的行号.参见: ...

  6. WordPress代码高亮插件SyntaxHighlighter终极使用详解

    子曰: 工欲善其事,必先利其器.作为码农一枚,再加上站长这个已经不再光鲜的称呼,岂能没有一款经济实用.操作简单.而且功能必须强大.样式也必须好看的Wordpress代码高亮插件?!作为一个视代码如生命 ...

  7. 【转载】常见十大经典排序算法及C语言实现【附动图图解】

    原文链接:https://www.cnblogs.com/onepixel/p/7674659.html 注意: 原文中的算法实现都是基于JS,本文全部修改为C实现,并且统一排序接口,另外增加了一些描 ...

  8. 【python测试开发栈】python基础语法大盘点

    周边很多同学在用python,但是偶尔会发现有人对python的基础语法还不是特别了解,所以帮大家梳理了python的基础语法(文中的介绍以python3为例).如果你已然是python大牛,可以跳过 ...

  9. CSS:CSS弹性盒子布局 Flexible Box

    一.简介 flexbox:全称Flexible Box, 弹性盒子布局.可以简单实现各种伸缩性的设计,它是由伸缩容器和伸缩项目组成.任何一个元素都可以指定为flexbox布局.这种新的布局方案在200 ...

  10. 【CPLUSOJ】【USACO】【差分约束】排队(layout)

    [题目描述] Robin喜欢将他的奶牛们排成一队.假设他有N头奶牛,编号为1至N.这些奶牛按照编号大小排列,并且由于它们都很想早点吃饭,于是就很可能出现多头奶牛挤在同一位置的情况(也就是说,如果我们认 ...