日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > 数据库 >内容正文

数据库

使用Redis bitmaps进行快速、简单、实时统计

發(fā)布時(shí)間:2024/2/28 数据库 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 使用Redis bitmaps进行快速、简单、实时统计 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

轉(zhuǎn)載自?https://www.cnblogs.com/fvsfvs123/p/4293203.html

getspool.com的重要統(tǒng)計(jì)數(shù)據(jù)是實(shí)時(shí)計(jì)算的。Redis的bitmap讓我們可以實(shí)時(shí)的進(jìn)行類(lèi)似的統(tǒng)計(jì),并且極其節(jié)省空間。在模擬1億2千8百萬(wàn)用戶的模擬環(huán)境下,在一臺(tái)MacBookPro上,典型的統(tǒng)計(jì)如“日用戶數(shù)”(dailyunique users) 的時(shí)間消耗小于50ms, 占用16MB內(nèi)存。Spool現(xiàn)在還沒(méi)有1億2千8百萬(wàn)用戶,但是我們的方案可以應(yīng)對(duì)這樣的規(guī)模。我們想分享這是如何做到的,也許能幫到其它創(chuàng)業(yè)公司。
?

Bitmap以及Redis Bitmaps快速入門(mén)(Crash Course on Bitmap and Redis Bitmaps)

Bitmap(即Bitset)
? ? Bitmap是一串連續(xù)的2進(jìn)制數(shù)字(0或1),每一位所在的位置為偏移(offset),在bitmap上可執(zhí)行AND,OR,XOR以及其它位操作。


位圖計(jì)數(shù)(Population Count)

? ? 位圖計(jì)數(shù)統(tǒng)計(jì)的是bitmap中值為1的位的個(gè)數(shù)。位圖計(jì)數(shù)的效率很高,例如,一個(gè)bitmap包含10億個(gè)位,90%的位都置為1,在一臺(tái)MacBook Pro上對(duì)其做位圖計(jì)數(shù)需要21.1ms。SSE4甚至有對(duì)整形(integer)做位圖計(jì)數(shù)的硬件指令。
?

?

Redis Bitmaps

? ? Redis允許使用二進(jìn)制數(shù)據(jù)的Key(binary keys) 和二進(jìn)制數(shù)據(jù)的Value(binary values)。Bitmap就是二進(jìn)制數(shù)據(jù)的value。Redis的 setbit(key, offset, value)操作對(duì)指定的key的value的指定偏移(offset)的位置1或0,時(shí)間復(fù)雜度是O(1)。


?

一個(gè)簡(jiǎn)單的例子:日活躍用戶

? ? 為了統(tǒng)計(jì)今日登錄的用戶數(shù),我們建立了一個(gè)bitmap,每一位標(biāo)識(shí)一個(gè)用戶ID。當(dāng)某個(gè)用戶訪問(wèn)我們的網(wǎng)頁(yè)或執(zhí)行了某個(gè)操作,就在bitmap中把標(biāo)識(shí)此用戶的位置為1。在Redis中獲取此bitmap的key值是通過(guò)用戶執(zhí)行操作的類(lèi)型和時(shí)間戳獲得的。

? ?? ? 這個(gè)簡(jiǎn)單的例子中,每次用戶登錄時(shí)會(huì)執(zhí)行一次redis.setbit(daily_active_users, user_id, 1)。將bitmap中對(duì)應(yīng)位置的位置為1,時(shí)間復(fù)雜度是O(1)。統(tǒng)計(jì)bitmap結(jié)果顯示有今天有9個(gè)用戶登錄。Bitmap的key是daily_active_users,它的值是1011110100100101。

? ? 因?yàn)槿栈钴S用戶每天都變化,所以需要每天創(chuàng)建一個(gè)新的bitmap。我們簡(jiǎn)單地把日期添加到key后面,實(shí)現(xiàn)了這個(gè)功能。例如,要統(tǒng)計(jì)某一天有多少個(gè)用戶至少聽(tīng)了一個(gè)音樂(lè)app中的一首歌曲,可以把這個(gè)bitmap的redis key設(shè)計(jì)為play:yyyy-mm-dd-hh。當(dāng)用戶聽(tīng)了一首歌曲,我們只是簡(jiǎn)單地在bitmap中把標(biāo)識(shí)這個(gè)用戶的位置為1,時(shí)間復(fù)雜度是O(1)。

[java]?
?

  • Redis.setbit(play:yyyy-mm-dd, user_id, 1)??


Redis.setbit(play:yyyy-mm-dd, user_id, 1)
? ? 今天聽(tīng)過(guò)歌曲的用戶就是key是play:yyyy-mm-dd的bitmap的位圖計(jì)數(shù)。如果要按周或月統(tǒng)計(jì),只要對(duì)這周或這個(gè)月的所有bitmap求并集,得出新的bitmap,在對(duì)它做位圖計(jì)數(shù)。




? ? 利用這些bitmap做其它復(fù)雜的統(tǒng)計(jì)也非常容易。例如,統(tǒng)計(jì)11月聽(tīng)過(guò)歌曲的高級(jí)用戶(premium user):
(play:2011-11-01∪ play:2011-11-02∪ … ∪ play:2011-11-30)∩premium:2011-11

?

1億2千8百萬(wàn)用戶的性能比較(Performance comparison using 128 million users)

? ? 下面的表格顯示了在1億2千8百萬(wàn)用戶上完成的時(shí)間粒度為1天,一周,一個(gè)月的用戶統(tǒng)計(jì)的時(shí)間消耗比較。

PeriodTime(ms)
Daily50.2
Weekly392.0
Monthly1624.8



?

優(yōu)化(Optimizations)

? ? 前面的例子中,我們把日統(tǒng)計(jì),周統(tǒng)計(jì),月統(tǒng)計(jì)緩存到Redis,以加快統(tǒng)計(jì)速度。
? ?

? ? 這是一種非常靈活的方法。這樣進(jìn)行緩存的額外紅利是可以進(jìn)行更多的統(tǒng)計(jì),如每周活躍的手機(jī)用戶—求手機(jī)用戶的bitmap與周活躍用戶的交集。或者,如果要統(tǒng)計(jì)過(guò)去n天的活躍用戶數(shù),緩存的日活躍用戶使這樣的統(tǒng)計(jì)變得簡(jiǎn)單——從cache中獲取過(guò)去n-1天的日活躍用戶bitmap和今天的bitmap,對(duì)它們做并集(Union),時(shí)間消耗是50ms。


?

示例代碼(SampleCode)

下面的Java代碼用來(lái)統(tǒng)計(jì)某個(gè)用戶操作在某天的活躍用戶。
[java]?
?

  • import redis.clients.jedis.Jedis;??
  • import java.util.BitSet;??
  • ...??
  • ? ? Jedis redis = new Jedis("localhost");??
  • ? ? ...??
  • ? ? public int uniqueCount(String action, String date) {??
  • ? ?? ???String key = action + ":" + date;??
  • ? ?? ???BitSet users = BitSet.valueOf(redis.get(key.getBytes()));??
  • ? ?? ???return users.cardinality();??
  • ? ? }? ???


import redis.clients.jedis.Jedis;import java.util.BitSet;...? ? Jedis redis = new Jedis("localhost");? ? ...? ? public int uniqueCount(String action, String date) {? ?? ???String key = action + ":" + date;? ?? ???BitSet users = BitSet.valueOf(redis.get(key.getBytes()));? ?? ???return users.cardinality();? ? }? ? ? ??

下面的Java代碼用來(lái)統(tǒng)計(jì)某個(gè)用戶操作在一個(gè)指定多個(gè)日期的活躍用戶。
[java]?
?

  • import redis.clients.jedis.Jedis;??
  • import java.util.BitSet;??
  • ...??
  • ? ? Jedis redis = new Jedis("localhost");??
  • ? ? ...??
  • ? ? public int uniqueCount(String action, String... dates) {??
  • ? ?? ???BitSet all = new BitSet();??
  • ? ?? ???for (String date : dates) {??
  • ? ?? ?? ?? ?String key = action + ":" + date;??
  • ? ?? ?? ?? ?BitSet users = BitSet.valueOf(redis.get(key.getBytes()));??
  • ? ?? ?? ?? ?all.or(users);??
  • ? ?? ???}??
  • ? ?? ???return all.cardinality();??
  • ? ? }??


import redis.clients.jedis.Jedis;import java.util.BitSet;...? ? Jedis redis = new Jedis("localhost");? ? ...? ? public int uniqueCount(String action, String... dates) {? ?? ???BitSet all = new BitSet();? ?? ???for (String date : dates) {? ?? ?? ?? ?String key = action + ":" + date;? ?? ?? ?? ?BitSet users = BitSet.valueOf(redis.get(key.getBytes()));? ?? ?? ?? ?all.or(users);? ?? ???}? ?? ???return all.cardinality();? ? }

References:

[1] Redis setbit command

?

About Author:

? ?? ?Garyelephant
? ?? ?garygaowork[at]gmail.com
? ?? ? 關(guān)注互聯(lián)網(wǎng)創(chuàng)新、分布式、NOSQL,高并發(fā)技術(shù)。

總結(jié)

以上是生活随笔為你收集整理的使用Redis bitmaps进行快速、简单、实时统计的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。