zoukankan      html  css  js  c++  java
  • 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
    
  • 相关阅读:
    jsp servlet table 集合list 数据 绑定
    Linux下“/”和“~”的区别
    android 百度地图 定位获取位置失败 62错误
    PostgreSQL 空间数据类型point、 line等
    PostgreSQL 与 PostGIS
    MySQL及navicat for mysql中文乱码
    eclipse报错:Multiple annotations found at this line:
    Multiple markers at this line
    css中绝对定位和相对定位的区别
    关于display的属性:block和inline-block以及inline的区别,float相关说明
  • 原文地址:https://www.cnblogs.com/luke44/p/12031078.html
Copyright © 2011-2022 走看看