redis 的bitmap 開源包 bitmapist的應用

2019獨角獸企業重金招聘Python工程師標準>>> hot3.png

原理:http://my.oschina.net/u/1458120/blog/545224

bitmap包:https://github.com/Doist/bitmapist

要求redis>= 2.6.0?

bitmapist-master.zip ?安裝自己下載解壓 python setup.py install

(由于包內默認連接本機redis 6379 端口 ,如果想要修改 把下載的包放到自己的項目中 修改__init__.py中

SYSTEMS = {'default': redis.Redis(host='192.168.1.3', port=6379)
}

不能運行在集群模式下,使用時最好keys *查看存過哪些key ?設置過期時間
?

事件標記默認天周月

只標記天可修改__init__.py 中_mark()函數

# obj_classes = [MonthEvents, WeekEvents, DayEvents]
# obj_classes = [DayEvents]

推薦閱讀:

http://www.zhihu.com/question/21581696?

(cohort analysis 同期群分析)感覺bitmapist的 cohort 講的就是這?

聲明:本文的測試大部分都是 開源中的原測試加上自己的一些理解,讀者可以直接看源文

# -*- coding: utf-8 -*-
# from builtins import range
import os
import traceback
import subprocess
import atexit
import socket
import time
import pytest
from bitmapist.cohort import get_dates_datafrom bitmapist import setup_redis, delete_all_eventsfrom datetime import datetime, timedeltafrom bitmapist import mark_event, unmark_event,\MonthEvents, WeekEvents, DayEvents, HourEvents,\BitOpAnd, BitOpOr, get_event_names
from bitmapist.cohort import get_dates_data
##################################################################
#下面是啟動redis服務 如果已經啟動可忽略def redis_server():"""Fixture starting the Redis server"""redis_host = '192.168.15.100'redis_port = 6379if is_socket_open(redis_host, redis_port):yield Noneelse:proc = start_redis_server(redis_port)wait_for_socket(redis_host, redis_port)yield procproc.terminate()
def setup_redis_for_bitmapist():setup_redis('default', '192.168.15.100', 6379)setup_redis('default_copy', 'l92.168.8.101', 6380)def start_redis_server(port):"""Helper function starting Redis server"""devzero = open(os.devnull, 'r')devnull = open(os.devnull, 'w')#查看自己的redis-serverm命令proc = subprocess.Popen(['/usr/local/redis/bin/redis-server', '--port', str(port)],stdin=devzero, stdout=devnull, stderr=devnull,close_fds=True)#close_fds關閉子進程atexit.register(lambda: proc.terminate())return procdef is_socket_open(host, port):"""Helper function which tests is the socket open"""sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)sock.settimeout(0.1)return sock.connect_ex((host, port)) == 0def wait_for_socket(host, port, seconds=3):"""Check if socket is up for :param:`seconds` sec, raise an error otherwise"""polling_interval = 0.1iterations = int(seconds / polling_interval)sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)sock.settimeout(0.1)for _ in range(iterations):result = sock.connect_ex((host, port))if result == 0:sock.close()breaktime.sleep(polling_interval)else:raise RuntimeError('Service at %s:%d is unreachable' % (host, port))########################################################################################
def base_test():try:setup_redis_for_bitmapist()redis_server()#mark_event的兩個重要參數now=None, track_hourly=None,# track_hourly =True標記用戶小時活躍  默認只標記到月周天#now=None時指現在時間   否則 指定到特定的用戶活躍時間mark_event('active', 123, track_hourly=True)now = datetime.utcnow()unmark_event('active', 124, track_hourly=True)#取消標記print MonthEvents('active', now.year, now.month).has_events_marked()print set(get_event_names(batch=2))#獲取所有的事件名稱set(["active"])print set(get_event_names(prefix='b', batch=2))#獲取所有以b開頭的事件名稱set()set([])# Monthassert 123 in MonthEvents('active', now.year, now.month)assert 124 not in MonthEvents('active', now.year, now.month)# Weekassert 123 in WeekEvents('active', now.year, now.isocalendar()[1])assert 124 not in WeekEvents('active', now.year, now.isocalendar()[1])# Dayassert 123 in DayEvents('active', now.year, now.month, now.day)assert 124 not in DayEvents('active', now.year, now.month, now.day)# Hourassert 123 in HourEvents('active', now.year, now.month, now.day, now.hour)assert 124 not in HourEvents('active', now.year, now.month, now.day, now.hour)assert 124 not in HourEvents('active', now.year, now.month, now.day, now.hour-1)mark_event("active",124)#標記用戶125本月活躍mark_event('active', 125)assert 125 in MonthEvents('active', now.year, now.month)#取消用戶125本月活躍unmark_event('active', 125)assert 125 not in MonthEvents('active', now.year, now.month)yesterday = now - timedelta(days=1)mark_event('active', 126, now=now)mark_event('active', 127, now=yesterday)#把用戶活躍標記到昨天的月周天上#獲取活躍的用戶數 提示錯誤沒有bitcount命令 要求redis>= 2.6.0  info查看redis版本print MonthEvents('active', now.year, now.month).get_count()#4print list(WeekEvents('active', now.year, now.isocalendar()[1]))# [123, 124, 126, 127]print list(MonthEvents('active', now.year, now.month))#[123, 124, 126, 127]ev = DayEvents('active', now.year, now.month,now.day) # [123, 124, 126]print list(ev)#3print len(ev)#3print list(DayEvents('active',yesterday.year,yesterday.month,yesterday.day))#[127]last_month = datetime.utcnow() - timedelta(days=30)ago3_month = datetime.utcnow() - timedelta(days=60)# 123,127 128上月活躍,127 上上月活躍mark_event('active', 127, now=ago3_month)mark_event('active', 123, now=last_month)mark_event('active', 127, now=last_month)mark_event('active', 128, now=last_month)# 近三個月都活躍的用戶(交集)active_3_months = BitOpAnd(MonthEvents('active', ago3_month.year, ago3_month.month),MonthEvents('active', last_month.year, last_month.month),MonthEvents('active', now.year, now.month))print list(active_3_months)#[127]active_3_months.delete()#嵌套查詢active_3_months = BitOpAnd(MonthEvents('active', ago3_month.year, ago3_month.month),MonthEvents('active', last_month.year, last_month.month),BitOpAnd(MonthEvents('active', now.year, now.month)))print list(active_3_months)#[127]# 近三個月活躍過的用戶(并集)print list(BitOpOr(MonthEvents('active', ago3_month.year, ago3_month.month),MonthEvents('active', last_month.year, last_month.month),MonthEvents('active', now.year, now.month)))#[123, 124, 126, 127, 128]#用備份redis查詢active_2_months = BitOpAnd('default_copy',MonthEvents('active', last_month.year, last_month.month),MonthEvents('active', now.year, now.month))print list(active_2_months)active_2_months.delete()delete_all_events()#清理所有的bitmapexcept:traceback.print_exc()def test_bit_operations_complex():now = datetime.utcnow()tom = now + timedelta(days=1)mark_event('task1', 111, now=now)mark_event('task1', 111, now=tom)mark_event('task2', 111, now=now)mark_event('task2', 111, now=tom)mark_event('task1', 222, now=now)mark_event('task1', 222, now=tom)mark_event('task2', 222, now=now)mark_event('task2', 222, now=tom)now_events = BitOpAnd(DayEvents('task1', now.year, now.month, now.day),DayEvents('task2', now.year, now.month, now.day))tom_events = BitOpAnd(DayEvents('task1', tom.year, tom.month, tom.day),DayEvents('task2', tom.year, tom.month, tom.day))both_events = BitOpAnd(now_events, tom_events)print list(both_events)def test_bitop_key_sharing():#測試key共享today = datetime.utcnow()#假設task1為唱歌 task2為跳舞mark_event('task1', 111, now=today)mark_event('task2', 111, now=today)mark_event('task1', 222, now=today)mark_event('task2', 222, now=today)ev1_task1 = DayEvents('task1', today.year, today.month, today.day)ev1_task2 = DayEvents('task2', today.year, today.month, today.day)ev1_both = BitOpAnd(ev1_task1, ev1_task2)#今天即唱歌又跳舞的ev2_task1 = DayEvents('task1', today.year, today.month, today.day)ev2_task2 = DayEvents('task2', today.year, today.month, today.day)ev2_both = BitOpAnd(ev2_task1, ev2_task2)print ev1_both,ev2_bothprint ev1_both.redis_key,ev2_both.redis_keyprint  len(ev1_both), len(ev2_both)#2,2ev1_both.delete()print  len(ev1_both), len(ev2_both)#0,0 同一個查詢的實例相同def test_bit_operations_magic():delete_all_events()mark_event('foo', 1)mark_event('foo', 2)mark_event('bar', 2)mark_event('bar', 3)foo = DayEvents('foo')bar = DayEvents('bar')print list(foo & bar)#交集print  list(foo | bar)#并集print  list(foo ^ bar)#異或 (foo和bar不相同的)print  list(~foo & bar)#[2]#[1, 2, 3]#[1, 3]#[3]def test_cohort():'''測試場景:當天注冊用戶 三天內每天有多少活躍過'''today = datetime.utcnow()#20160608yes = today - timedelta(days=1)ago2 = today - timedelta(days=2)#20160606tomorrow = today +timedelta(days=1)after2 = today +timedelta(days=2)####################################前天注冊用戶追蹤#前天注冊mark_event("regist",111,now=ago2)mark_event("regist",112,now=ago2)mark_event("regist",113,now=ago2)mark_event("regist",114,now=ago2)mark_event("regist",115,now=ago2)#前天活躍mark_event("active",111,now=ago2)mark_event("active",112,now=ago2)mark_event("active",113,now=ago2)mark_event("active",114,now=ago2)#昨天活躍的mark_event("active",111,now=yes)mark_event("active",112,now=yes)mark_event("active",113,now=yes)#今天活躍的mark_event("active",115,now=today)############################昨天注冊用戶追蹤#昨天注冊mark_event("regist",116,now=yes)mark_event("regist",117,now=yes)mark_event("regist",118,now=yes)mark_event("regist",119,now=yes)mark_event("regist",120,now=yes)#昨天活躍mark_event("active",116,now=yes)mark_event("active",117,now=yes)mark_event("active",118,now=yes)mark_event("active",119,now=yes)#今天活躍mark_event("active",119,now=today)mark_event("active",120,now=today)#明天活躍mark_event("active",116,now=tomorrow)########################################################今天注冊用戶追蹤#今天注冊mark_event("regist",121,now=today)mark_event("regist",122,now=today)mark_event("regist",123,now=today)#今天活躍mark_event("active",121,now=today)mark_event("active",122,now=today)#明天活躍mark_event("active",121,now=tomorrow)#后天活躍mark_event("active",123,now=after2)for select1,select1b,select2,select2b in [('regist', None, 'active', None)]:'''select1:初始條件 本例指注冊select1b:select1的附屬條件 例如中國注冊用戶(mark_event("registchina",123,now=today))select2:初始條件下的過濾select2b:同select1btime_group:時間跨度 `days`, `weeks`, `months`, `years`as_precent:0輸出經過select過濾后的數量  1百分比num_results:time_group+num_results 得到關注的時間范圍  如近三天、三周、三月 三年num_of_rows:對select1(或select1+select1b)條件下的select2(或select2+select2b)輸出未來幾天(周/月/年)的本例:近三天(time_group+num_results=3days)當天注冊用戶(select1='regist')三天內(num_of_rows=3)每天的活躍(select2='active')人數'''r = get_dates_data(select1=select1, select1b=select1b,select2=select2, select2b=select2b,time_group='days', as_precent=0,num_results=3, num_of_rows=3)print list(r)#當天注冊   #當天活躍  #未來三天活躍
# [[datetime.datetime(2016, 6, 6, 6, 21, 43, 845437), 5,               4,     3, 1, 0.0],
#  [datetime.datetime(2016, 6, 7, 6, 21, 43, 845437), 5,               4,     2, 1, 0.0],
#  [datetime.datetime(2016, 6, 8, 6, 21, 43, 845437), 3,               2,     1, 1, '']]
#以6號為例  20160606 當天注冊5人 4人活躍  未來三天20160607 在20160606注冊的人中其中3人活躍 20160608 1人活躍 20160609 0人活躍(0.0代表有人活躍但不在20160606的注冊人中 '' 代表壓根沒人活躍)
#redis中查找key:
#:6379> BITCOUNT trackist_regist_2016-6-7
#6379> BITCOUNT trackist_regist_W2016-27
#6379> BITCOUNT trackist_buyid_regist_2016-6
if __name__ == '__main__':test_bitop_key_sharing()delete_all_events()test_bit_operations_magic()delete_all_events()test_cohort()

?

?

轉載于:https://my.oschina.net/u/1458120/blog/688739

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/284459.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/284459.shtml
英文地址,請注明出處:http://en.pswp.cn/news/284459.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Django Views(視圖函數)

http請求中產生兩個核心對象: http請求:HttpRequest對象 http響應:HttpResponse對象 所在位置:django.http 之前我們用到的參數request就是HttpRequest 檢測方法:isinstance(request,HttpRequest) 1 HttpRequest對象…

Android 4 +https(如何啟動TLS1 1 and TLS1 2)

之前用的網絡請求框架是鴻洋的OkHttpUtils,網絡請求在5.0手機上使用https沒有問題,但是最近突然使用了一個4.4的系統,就報錯SSLException ....咋地咋地 然后 我們的副總給我們找一個博客,如何解決4.系統出現的這個問題&#xff0…

massCode 一款優秀的開源代碼片段管理器

本文將介紹一款適合程序員使用的個人代碼片段管理工具 massCode[1]。massCode小時候,也許我們每個人都會被老師要求有一個到處摘錄優美句子段落的作文素材本 —— 采蜜集。不可否認,這對我們的寫作水平的提高確實有很大的幫助。對開發人員來說當然也需要…

【ArcGIS Pro微課1000例】0021:Win10系統ArcGIS Pro3.0.1安裝教程(附ArcGIS Pro下載)

本文講解Win10系統上ArcGIS Pro3.0.1安裝教程,附軟件包下載。 文章目錄 一、 軟件安裝步驟1. 安裝.net Runtime 62. 安裝ArcGIS Pro3. 安裝中文語言4. 刪除代理二、軟件下載地址一、 軟件安裝步驟 [軟件名稱]: ArcGIS Pro 3.0.1 [軟件大小]:4.33GB [安裝環境]: Win 11/Win …

iOS逆向工程——非越獄調試

其實iOS的逆向分析業界已經十分成熟了,網上也有許多有趣的嘗試(一步一步實現iOS微信自動搶紅包(非越獄)。本文著重于如何在非越獄機器上進行調試,出于學習及總結的目的,記錄于此。 本文以破解游戲夢幻西游為例,逐步講解整個調試流…

[轉]2022 Flutter 宣布發布 Windows 正式版

原文鏈接: https://medium.com/flutter/announcing-flutter-for-windows-6979d0d01fed 自從推出 Flutter 以來,我們一直專注于為漂亮的定制應用提供跨平臺解決方案,這些應用被編譯為機器代碼并充分利用設備的底層圖形硬件功能。 今天這一愿景…

電腦經常彈出“不支持的硬件”解決辦法

電腦經常彈出“不支持的硬件”解決辦法。 通過微軟官方查證,這是由于以上處理器需要最新的Windows10系統才會這樣子的,而大多出現該提示的都安裝了Win7或是Win8.1系統。 來至微軟官方的說明 此錯誤出現的原因是各代新處理器要求最新Windows版本以獲得支持。 例如,Windows 1…

使用 Web API 上傳和下載多個文件

原文作者:Jay Krishna Reddy原文鏈接:https://www.c-sharpcorner.com/article/upload-and-download-multiple-files-using-web-api/翻譯:沙漠盡頭的狼(谷歌翻譯加持,文中版本使用.NET 6升級)---正文開始---…

詳解T-SQL的聯接機制

T-SQL的聯接分三種類型: 交叉聯接 ( cross join ) 內部聯接 (inner join) 外部聯接 (outer join) 每種聯接在邏輯上經歷不同的階段,分為笛卡爾乘積、篩選、添加外部行,如圖: 聯接類型 階段 交叉聯接 笛卡兒乘積 內部聯接…

Android FrameWork學習(一)Android 7 0系統源碼下載 編譯

最近計劃著研究下 Android 7.0 的系統源碼,之前也沒做過什么記錄,這次正好將學習的內容記錄下來,方便以后復習鞏固。 既然要學習我們的系統源碼,那我們第一步要做的就是下載源碼并進行編譯了。 #硬件環境要求 ###1. 編譯環境 按照…

【MapGIS精品教程】002:GDB本地數據庫的使用

本文主要內容為MapGISGDB本地數據庫的使用,包括:GDB企業管理器的認識、GDB本地數據庫的創建方法、GDB本地數據庫的備份和恢復。 1. GDB企業管理器的認識 GDB是地理數據的資源管理器,主要對空間數據進行有序組織與管理。 GDB數據管理包括&…

RabbitMQ學習3----運行和管理RabbitMQ

1.服務為管理 Erlang天生就是為了讓應用程序無需知道對方是否存在同一臺機器上即可互相通信。 Erlang節點:Erlang虛擬機的每個實例。多個Erlang應用程序可以運行在同一個節點之上。節點之間可以進行本地通信(不管他們是運行在同一臺服務器之上&#xff0…

各代移動網絡性能

摘自《中國元宇宙白皮書》 下載整書完整版https://www.aliyundrive.com/s/gXQvRLM22kD

EFCore高級Saas系統下單DbContext如何支持不同數據庫的遷移

前言隨著系統的不斷開發和迭代默認的efcore功能十分強大,但是隨著Saas系統的引進efcore基于表字段的多租戶模式已經非常完美了,但是基于數據庫的多租戶也是可以用的,但是也存在缺點,缺點就是沒有辦法支持不同數據庫,mi…

poj 1679: The Unique MST【次小生成樹】

題目鏈接 參考博客 希望注釋足夠清楚。。歡迎指出不足~ #include<cstdio> #include<cstring> #include<algorithm> using namespace std;const int maxn110; const int INF0x3f3f3f3f;int n,m; int mp[maxn][maxn]; int maxlen[maxn][maxn]; //maxlen…

51. Python 數據處理(2)

1.Python 修改excel文件import xlrd import xlutils.copy excelr xlrd.open_workbook("hello.xlsx") excelw xlutils.copy.copy(excelr) sheet1 excelw.get_sheet(0) sheet1.write(3, 5, "xlutils.copy test test") excelw.save("hello.xlsx"…

人工智能十大流行算法

導讀&#xff1a;本文為有志于成為數據科學家或對此感興趣的讀者們介紹最流行的機器學習算法。 作者&#xff1a;Fahim ul Haq 譯者&#xff1a;劉志勇&#xff0c;策劃&#xff1a;趙鈺瑩 來源&#xff1a;InfoQ&#xff08;ID&#xff1a;infoqchina&#xff09; 機器學習是…

Win7+Win10雙系統安裝全攻略

安裝雙系統,不僅能給你非凡的體驗,還可以滿足工作中因系統版本,兼容性,處理器等原因帶來的不便。本文講解Win7+Win10雙系統安裝全攻略,親測可用。 1. 硬盤分區 本文講解利用固態硬盤+機械硬盤的分區方式。 固態硬盤:為了絕對提高系統運行的速度,將固態硬盤作為雙系統的…

[矩形并-掃描線-線段樹]Picture

最近在補數學和幾何&#xff0c;沒啥好寫的&#xff0c;因為已經決定每天至少寫一篇了&#xff0c;今天隨便拿個題水水。 題目大意&#xff1a;給你N個邊平行于坐標軸的矩形&#xff0c;求它們并的周長。(N<5000) 思路&#xff1a;這個數據范圍瞎暴力就過了&#xff0c;但我…

聊聊研發團隊中的“人”

大家好&#xff0c;我是Z哥。漢字博大精深&#xff0c;很多時候我們可以通過拆字來更形象地理解一個詞的含義。比如“團隊”這個詞的兩個字"團"和“隊”單獨看也都是表示一種由多人組成的組織。再做一下拆字就是“口”“才”和“耳”“人”。前者表示一個人才如果沒有…