目錄
BitMap是什麼
Redis中的BitMap
setbit指令介紹
空間佔用、以及第一次分配空間所需的時間
##使用場景一:用戶簽到
首頁 資料庫 Redis 分析Redis中bitmap的用法(範例場景解說)

分析Redis中bitmap的用法(範例場景解說)

Jul 17, 2021 pm 04:02 PM
bitmap redis集群

在Redis中我們常用到set,get等指令,細心的你有沒有發現,還有幾個相似的指令叫setbit,getbit,它們是用來幹嘛的?

BitMap是什麼

就是透過一個bit位元來表示某個元素對應的值或狀態,其中的key就是對應元素本身。我們知道8個bit可以組成一個Byte,所以bitmap本身會極大的節省儲存空間。

Redis中的BitMap

Redis從2.2.0版本開始新增了setbit,getbit,bitcount等幾個bitmap相關指令。雖然是新指令,但是並沒有新增新的資料類型,因為setbit等指令只不過是在set上的擴充。

setbit指令介紹

指令 SETBIT key offset value  
複雜度 O(1)  
設定或清空key的value(字串)在offset處的bit值(只能0或1)。

空間佔用、以及第一次分配空間所需的時間

在一台2010MacBook Pro上,offset為2^32-1(分配512MB)需要~ 300ms,offset為2^30-1(分配128MB)需要~80ms,offset為2^28-1(分配32MB)需要~30ms,offset為2^26-1(分配8MB)需要8ms。 <來自官方文件>  
大概的空間佔用計算公式是:($offset/8/1024/1024)MB

##使用場景一:用戶簽到

很多網站都提供了簽到功能(這裡不考慮資料落地事宜),並且需要展示最近一個月的簽到情況,如果使用bitmap我們怎麼做?一言不合亮代碼!

<?php
$redis = new Redis();
$redis->connect('127.0.0.1');

//用户uid
$uid = 1;

//记录有uid的key
$cacheKey = sprintf("sign_%d", $uid);

//开始有签到功能的日期
$startDate = '2017-01-01';

//今天的日期
$todayDate = '2017-01-21';

//计算offset
$startTime = strtotime($startDate);
$todayTime = strtotime($todayDate);
$offset = floor(($todayTime - $startTime) / 86400);

echo "今天是第{$offset}天" . PHP_EOL;

//签到
//一年一个用户会占用多少空间呢?大约365/8=45.625个字节,好小,有木有被惊呆?
$redis->setBit($cacheKey, $offset, 1);

//查询签到情况
$bitStatus = $redis->getBit($cacheKey, $offset);
echo 1 == $bitStatus ? '今天已经签到啦' : '还没有签到呢';
echo PHP_EOL;

//计算总签到次数
echo $redis->bitCount($cacheKey) . PHP_EOL;

/**
* 计算某段时间内的签到次数
* 很不幸啊,bitCount虽然提供了start和end参数,但是这个说的是字符串的位置,而不是对应"位"的位置
* 幸运的是我们可以通过get命令将value取出来,自己解析。并且这个value不会太大,上面计算过一年一个用户只需要45个字节
* 给我们的网站定一个小目标,运行30年,那么一共需要1.31KB(就问你屌不屌?)
*/
//这是个错误的计算方式
echo $redis->bitCount($cacheKey, 0, 20) . PHP_EOL;
登入後複製

使用場景二:統計活躍用戶

使用時間作為cacheKey,然後用戶ID為offset,如果當天活躍過就設定為1  

那麼我如果計算某幾天/月/年的活躍用戶呢(暫且約定,統計時間內只有有一天在線就稱為活躍),有請下一個redis的命令 
命令 BITOP operation destkey key [key .. .]  
說明:對一個或多個保存二進位位元的字串key 進行位元操作,並將結果儲存到destkey 上。
說明:BITOP 指令支援AND 、 OR 、 NOT 、 XOR 這四種操作中的任一參數

//日期对应的活跃用户
$data = array(
'2017-01-10' => array(1,2,3,4,5,6,7,8,9,10),
'2017-01-11' => array(1,2,3,4,5,6,7,8),
'2017-01-12' => array(1,2,3,4,5,6),
'2017-01-13' => array(1,2,3,4),
'2017-01-14' => array(1,2)
);

//批量设置活跃状态
foreach($data as $date=>$uids) {
  $cacheKey = sprintf("stat_%s", $date);
  foreach($uids as $uid) {
    $redis->setBit($cacheKey, $uid, 1);
  }
}

$redis->bitOp('AND', 'stat', 'stat_2017-01-10', 'stat_2017-01-11', 'stat_2017-01-12') . PHP_EOL;
//总活跃用户:6
echo "总活跃用户:" . $redis->bitCount('stat') . PHP_EOL;

$redis->bitOp('AND', 'stat1', 'stat_2017-01-10', 'stat_2017-01-11', 'stat_2017-01-14') . PHP_EOL;
//总活跃用户:2
echo "总活跃用户:" . $redis->bitCount('stat1') . PHP_EOL;

$redis->bitOp('AND', 'stat2', 'stat_2017-01-10', 'stat_2017-01-11') . PHP_EOL;
//总活跃用户:8
echo "总活跃用户:" . $redis->bitCount('stat2') . PHP_EOL;
登入後複製
假設目前網站有5000W用戶,那麼一天的資料大約是50000000/8/1024 /1024=6MB

使用場景三:使用者線上狀態

前段時間開發一個項目,對方給我提供了一個查詢目前使用者是否在線的介面。不了解對方是怎麼做的,自己考慮了一下,使用bitmap是一個節約空間效率又高的一種方法,只需要一個key,然後用戶ID為offset,如果在線就設置為1,不在線就設置為0,和上面的場景一樣,5000W用戶只需要6MB的空間。

//批量设置在线状态
$uids = range(1, 500000);
foreach($uids as $uid) {
  $redis->setBit('online', $uid, $uid % 2);
}
//一个一个获取状态
$uids = range(1, 500000);
$startTime = microtime(true);
foreach($uids as $uid) {
  echo $redis->getBit('online', $uid) . PHP_EOL;
}
$endTime = microtime(true);
//在我的电脑上,获取50W个用户的状态需要25秒
echo "total:" . ($endTime - $startTime) . "s";

/**
* 对于批量的获取,上面是一种效率低的办法,实际可以通过get获取到value,然后自己计算
* 具体计算方法改天再写吧,之前写的代码找不见了。。。
*/
登入後複製
推薦學習:《

redis影片教學

#

以上是分析Redis中bitmap的用法(範例場景解說)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

利用ThinkPHP6實現Redis集群 利用ThinkPHP6實現Redis集群 Jun 20, 2023 am 08:36 AM

隨著網路的快速發展,高併發的問題也愈發突出。針對這個問題,Redis的出現成為了一個重要的方案,它透過記憶體讀寫的方式,解決了傳統關係型資料庫讀寫壓力過大的問題。然而,單節點Redis在高並發情況下仍然存在效能瓶頸,因此需要使用Redis叢集。本文將講述如何使用ThinkPHP6實作Redis叢集。一、Redis集群介紹Redis集群是Redis官方提供的分

如何透過Redis實現PHP資料快取的叢集部署? 如何透過Redis實現PHP資料快取的叢集部署? Aug 10, 2023 am 08:13 AM

如何透過Redis實現PHP資料快取的叢集部署?簡介:PHP應用在面對高並發和大流量時,常會遇到資料庫效能瓶頸的問題,這時候使用快取技術能很好地提升系統的效能和並發能力。 Redis作為一個高效能的記憶體鍵值資料庫,被廣泛應用於快取方案的實作。本文將介紹如何透過Redis實現PHP資料快取的叢集部署,以進一步提升效能和可擴充性。一、Redis集群概述Redis

Redis中的Redis集群和PHP的使用方法 Redis中的Redis集群和PHP的使用方法 May 15, 2023 pm 03:22 PM

Redis是一款強大的記憶體鍵值對儲存資料庫。與常規的RDBMS(關聯式資料庫管理系統)相比,它具有更高的效能和更好的伸縮性。 Redis的優點之一是它可以作為分散式系統的核心技術。在這篇文章中,我們將探討Redis集群的概念以及如何在PHP中使用Redis集群。 Redis集群是什麼?簡單來說,Redis叢集即為多個Redis實例的聚合體。 Redis集群允許我們

Redis與Node.js的叢集方案:如何實現高可用性 Redis與Node.js的叢集方案:如何實現高可用性 Jul 29, 2023 pm 05:42 PM

Redis與Node.js的叢集方案:如何實現高可用性引言:隨著網際網路的快速發展,資料的處理變得越來越龐大且複雜。為了確保系統的高可用性和可擴展性,我們需要使用分散式叢集架構來處理儲存和處理大量資料的需求。 Redis作為高效能的記憶體資料庫,結合Node.js作為後端程式語言,可以建立高可用的分散式叢集方案。本文將介紹如何使用Redis與Node.js實現

學習Go語言中的資料庫函數並實作Redis叢集的讀寫操作 學習Go語言中的資料庫函數並實作Redis叢集的讀寫操作 Jul 29, 2023 pm 12:21 PM

學習Go語言中的資料庫函數並實現Redis叢集的讀寫操作引言:資料庫是當今網路應用不可或缺的一部分,而Go語言作為一門開發簡潔高效的程式語言,也具備了良好的資料庫操作能力。本文將介紹如何在Go語言中使用資料庫函數,並實作Redis叢集的讀寫操作。一、Go語言中的資料庫函數Go語言中對資料庫的操作主要透過database/sql包來實現。該套件提供了基本的數據

Redis與PHP的叢集方案:如何實現高可用性與擴充性 Redis與PHP的叢集方案:如何實現高可用性與擴充性 Jul 30, 2023 pm 08:51 PM

Redis與PHP的叢集方案:如何實現高可用性和擴展性引言:Redis是一種開源的高效能記憶體資料庫,常用於建立快速、可擴展的應用程式。而PHP作為一門流行的伺服器端腳本語言,與Redis配合使用能夠實現高可用性和擴展性的叢集方​​案。本文將介紹如何使用Redis與PHP建立一個高可用性和擴展性的集群,並透過程式碼範例詳細說明。一、Redis集群的搭建安裝與配置Re

如何利用Redis和Julia語言實現高可用叢集功能 如何利用Redis和Julia語言實現高可用叢集功能 Sep 20, 2023 am 10:58 AM

如何利用Redis和Julia語言實現高可用叢集功能引言:隨著網路業務的發展,對於系統的可用性要求越來越高。為了確保系統在發生故障時能夠繼續提供服務,高可用性成為了各行業中的關鍵需求之一。本文將介紹如何利用Redis和Julia語言實現高可用叢集功能,並提供具體的程式碼範例。一、什麼是高可用群集高可用群集是透過將多個節點組織在一起,從而形成一個整體的系統,

Redis集群擴容方案及實作細節 Redis集群擴容方案及實作細節 Jun 21, 2023 am 10:58 AM

Redis是一個高效能的開源記憶體資料儲存服務,因其快速讀寫速度、可持久化儲存和多種資料結構支持,越來越受到開發者們的青睞。隨著業務的不斷壯大,Redis的儲存容量已經無法滿足需求,這時需要進行擴充。本文將介紹Redis集群擴容的方案及其實作細節。 Redis集群的概念Redis集群是指將多個Redis實例連接在一起,形成一個大的Redis實例集合,可以提高Re

See all articles