搜索
首页数据库Redisredis中的bitmap实例分析

redis中的bitmap实例分析

May 27, 2023 pm 09:07 PM
redisbitmap

1、BitMap是什么

使用一个位来表示元素的值或状态,该元素本身即为key。Bitmap可以极大地节省存储空间,因为我们知道8个bit可以组成一个Byte。2^32次方40亿数据只需要500M内存,需要内存少了8倍

2、setbit命令介绍 

setbit key offset value
 #设置bitmapkey为20220328  uid为100的用户已签到1
setbit  20220320  100 1 
setbit  20220320  200 1
 setbit  20220321  100 1
setbit  20220321  300 1
  getbit 20220320  100  #返回1,说明这个用户已签到了
  bitcount 20220320  #获取bitmap数量

bitmap的坑

127.0.0.1:6400> setbit bittest 100 1 #设置不存在的offset返回0
(integer) 0
127.0.0.1:6400> setbit bittest 100 1 #设置已存在的offset返回1
(integer) 1

setbit maxKey 4000000000 1 #直接弄了你600多M内存

/**
     * 布隆过滤器bloom Filter
     * 1.百万分之一的概率哈希冲突,所以有存在的不一定存在,但是不存在的百分百不存在
     * 2.不能删除,删除的时候不能简单的直接置为0,可能会影响其他元素的判断,其实问题不大一般生产数据也不会删除的,都是软删除
     * 3.新增数据时候写入bloom Filter
     * 4.2^32次方40亿数据内存占用才600M,超级省内存,查找速度非常快,160M内存可以在千万级数据做到1%的误判
     * 5.bitmap根据offset去申请内存的,所以要省内存的情况要限制offset值
     */
    public function bloomAction(){
        $t1 = time();
         for($i=0;$i<99;$i++){
            $bl = new BloomFilter();
            //$str = "1https://arnaud.le-blanc.net/php-rdkafka-doc/phpdoc/book.rdkafka.html?id=".time();
            $str = "https://dasda.le-blanc.net/php-rdkafka-doc/phpdoc/book.rdkafka.html?id=".mt_rand(1,99999999);
            p($str);
             $res1 = $bl->JSHash($str);//两次哈希3s,md5哈希重复的概率是百万分之一
             p($res1);
        }
        //p($res);
        $t2 = time();
        echo $t2-$t1;
    }
    /**
     * 布隆过滤器初始化 bloom Filter 执行 php  index.php "index/demo/loadDb2bloom"
     */
    public function isExistBloomAction(){
        $redis = redisCursor();
        $email = input("email","","trim");
        $tel   = input("tel","");
         $result = false;
        $msg    = "";
        if(filter_var($email,FILTER_VALIDATE_EMAIL)){
            $key1  = "bloom_user_email";
            $offset = BloomFilter::JSHash($email);
            $result = $redis->getbit($key1,$offset);
            $msg = $email;
        }elseif($tel){
            $key2  = "bloom_user_telephone";
            $offset = BloomFilter::JSHash($tel);
            $result = $redis->getbit($key2,$offset);
            $msg = $tel;
        }
         $result?apiSuccess($msg.",已存在"):apiError($msg.",不存在");
    }
    /**
     * 布隆过滤器初始化 bloom Filter 执行 php  index.php "index/demo/loadDb2bloom"
     */
    public function loadDb2bloomAction(){
        $time1 = time();
        $redis = redisCursor();
         $key1 = "bloom_user_email";
        $key2 = "bloom_user_telephone";
         //setbit() offset 必须是数字,value必须是1或0
        //$redis->setbit($key,30,1);
        $table  = "user";
        $pkid   = "id";
        $field1 = "email";
        $field2 = "telephone";
         $maxid = Db::name($table)->max($pkid);
         $size  = 5000;
        $page  = ceil($maxid/$size);
         for($i=0;$i<$page;$i++){
            $start = $i*$size;
            $where = " $pkid between ".$start."  and ".($start+$size);
            $res = Db::name($table)->where($where)->field("$field1,$field2")->select();
             if($res){//同步到bitmap
                foreach($res as $k=>$v){
                    //布隆过滤器  1.存在的不一定存在, 2.不存在的100%不存在(原因,哈希冲突可能用100W分之一的可能重复)
                    //所以注册的时候判断不存在的,百分百可以注册,存在的可以查询一下数据库是否真的不存在
                     $value1 = BloomFilter::JSHash($v["$field1"]);
                    $value2 = BloomFilter::JSHash($v["$field2"]);
                     $redis->setbit($key1,$value1,1);//email去重
                    $redis->setbit($key2,$value2,1);//mobile去重
                }
            }
             $time2 = time();
            echo $where." 消耗时间 ".($time2-$time1).PHP_EOL;
        }
         $time3 = time();
        echo " 总消耗时间 ".($time3-$time1).PHP_EOL;
    }
<?php
 class BloomFilter
{
    /**
     *  下面的哈希函数随便用一个都行,都是把字符串转换成数字
     */
     /**
     * hash方法类
     * 由Justin Sobel编写的按位散列函数
     * update:Denny
     * 返回之前做了内存限制在160M,超过10亿的哈希后的数值,把它限制在10亿内,此时1000W的数据可做到1%误判,内存不差这600多M的话就别限制了
     * 因为redis的bitmap申请内存是看offset申请内存的,setbit mykey 400000000 1,这样直接申请了600M内存
     */
    public static function JSHash($string, $limitMemory=true,$len = null)
    {
        $hash = 1315423911;
        $len || $len = strlen($string);
         for($i = 0; $i < $len; $i++)
        {
            $hash ^= (($hash << 5) + ord($string[$i]) + ($hash >> 2));
        }
         $hashNum = ($hash % 0xFFFFFFFF) & 0xFFFFFFFF;
         //为了节省内存,超过10亿就对半拆,10亿,这时候大约是130M内存占用,千万级数据可以做到1%误判率,内存足够可以不用判断,直接生成就行了
        //如果数据过4000W的话不用限制了,因为生成的数据最大也是2^32次方40多亿,此时内存占用大概在600M封顶了
        if($limitMemory){
            if($hashNum>4000000000){
                $hashNum = intval($hashNum/5);
            }elseif($hashNum>3000000000){
                $hashNum = intval($hashNum/4);
            }elseif($hashNum>2000000000){
                $hashNum = intval($hashNum/3);
            }
        }
         return $hashNum;
    }
}

以上是redis中的bitmap实例分析的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文转载于:亿速云。如有侵权,请联系admin@php.cn删除
REDIS:流行数据结构指南REDIS:流行数据结构指南Apr 11, 2025 am 12:04 AM

Redis支持多种数据结构,具体包括:1.字符串(String),适合存储单一值数据;2.列表(List),适用于队列和栈;3.集合(Set),用于存储不重复数据;4.有序集合(SortedSet),适用于排行榜和优先级队列;5.哈希表(Hash),适合存储对象或结构化数据。

redis计数器怎么实现redis计数器怎么实现Apr 10, 2025 pm 10:21 PM

Redis计数器是一种使用Redis键值对存储来实现计数操作的机制,包含以下步骤:创建计数器键、增加计数、减少计数、重置计数和获取计数。Redis计数器的优势包括速度快、高并发、持久性和简单易用。它可用于用户访问计数、实时指标跟踪、游戏分数和排名以及订单处理计数等场景。

redis命令行怎么用redis命令行怎么用Apr 10, 2025 pm 10:18 PM

使用 Redis 命令行工具 (redis-cli) 可通过以下步骤管理和操作 Redis:连接到服务器,指定地址和端口。使用命令名称和参数向服务器发送命令。使用 HELP 命令查看特定命令的帮助信息。使用 QUIT 命令退出命令行工具。

redis集群模式怎么搭建redis集群模式怎么搭建Apr 10, 2025 pm 10:15 PM

Redis集群模式通过分片将Redis实例部署到多个服务器,提高可扩展性和可用性。搭建步骤如下:创建奇数个Redis实例,端口不同;创建3个sentinel实例,监控Redis实例并进行故障转移;配置sentinel配置文件,添加监控Redis实例信息和故障转移设置;配置Redis实例配置文件,启用集群模式并指定集群信息文件路径;创建nodes.conf文件,包含各Redis实例的信息;启动集群,执行create命令创建集群并指定副本数量;登录集群执行CLUSTER INFO命令验证集群状态;使

redis怎么读取队列redis怎么读取队列Apr 10, 2025 pm 10:12 PM

要从 Redis 读取队列,需要获取队列名称、使用 LPOP 命令读取元素,并处理空队列。具体步骤如下:获取队列名称:以 "queue:" 前缀命名,如 "queue:my-queue"。使用 LPOP 命令:从队列头部弹出元素并返回其值,如 LPOP queue:my-queue。处理空队列:如果队列为空,LPOP 返回 nil,可先检查队列是否存在再读取元素。

redis集群zset怎么使用redis集群zset怎么使用Apr 10, 2025 pm 10:09 PM

Redis 集群中使用 zset:zset 是一种有序集合,将元素与评分关联。分片策略: a. 哈希分片:根据 zset 键的哈希值分布。 b. 范围分片:根据元素评分划分为范围,并将每个范围分配给不同的节点。读写操作: a. 读操作:如果 zset 键属于当前节点的分片,则在本地处理;否则,路由到相应的分片。 b. 写入操作:始终路由到持有 zset 键的分片。

redis数据怎么清空redis数据怎么清空Apr 10, 2025 pm 10:06 PM

如何清空 Redis 数据:使用 FLUSHALL 命令清除所有键值。使用 FLUSHDB 命令清除当前选定数据库的键值。使用 SELECT 切换数据库,再使用 FLUSHDB 清除多个数据库。使用 DEL 命令删除特定键。使用 redis-cli 工具清空数据。

redis过期策略怎么设置redis过期策略怎么设置Apr 10, 2025 pm 10:03 PM

Redis数据过期策略有两种:定期删除:定期扫描删除过期键,可通过 expired-time-cap-remove-count、expired-time-cap-remove-delay 参数设置。惰性删除:仅在读取或写入键时检查删除过期键,可通过 lazyfree-lazy-eviction、lazyfree-lazy-expire、lazyfree-lazy-user-del 参数设置。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
3 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
3 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
3 周前By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解锁Myrise中的所有内容
3 周前By尊渡假赌尊渡假赌尊渡假赌

热工具

mPDF

mPDF

mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),

SublimeText3 Linux新版

SublimeText3 Linux新版

SublimeText3 Linux最新版

Dreamweaver Mac版

Dreamweaver Mac版

视觉化网页开发工具

SublimeText3 英文版

SublimeText3 英文版

推荐:为Win版本,支持代码提示!

DVWA

DVWA

Damn Vulnerable Web App (DVWA) 是一个PHP/MySQL的Web应用程序,非常容易受到攻击。它的主要目标是成为安全专业人员在合法环境中测试自己的技能和工具的辅助工具,帮助Web开发人员更好地理解保护Web应用程序的过程,并帮助教师/学生在课堂环境中教授/学习Web应用程序安全。DVWA的目标是通过简单直接的界面练习一些最常见的Web漏洞,难度各不相同。请注意,该软件中