講解ID-Mapping算法之前,先說幾個重要概念:
MAC(Media Access Control),MAC位址,為網卡的辨別,唯一辨別網絡裝置。
IMEI(International Mobile Equipment Identity),通常說的手機序列号、手機“串号”,在行動電話網絡中識别每一部獨立的手機等行動通訊裝置;序列号共有15位數字,前6位(TAC)是型号核準号碼,代表手機類型。接着2位(FAC)是最後裝配号,代表産地。後6位(SNR)是串号,代表生産順序号。最後1位(SP)一般為0,是檢驗碼,備用。
IMSI(International Mobile SubscriberIdentification Number),儲存在SIM卡中,差別移動使用者的有效資訊;其總長度不超過15位,同樣使用0~9的數字。其中MCC是移動使用者所屬國家代号,占3位數字,中國的MCC規定為460;MNC是移動網号碼,最多由兩位數字組成,用于識别移動使用者所歸屬的移動通信網;MSIN是移動使用者識别碼,用以識别某一移動通信網中的移動使用者。
Android ID是系統随機生成的裝置ID 為一串64位的編碼(十六進制的字元串),通過它可以知道裝置的壽命(在裝置恢複出廠設定或刷機後,該值可能會改變)。
UDID (Unique Device Identifier),蘋果IOS裝置的唯一識别碼,它由40個字元的字母和數字組成,為了保護使用者隐私蘋果已經禁止讀取這個辨別了。
UUID(Universally Unique IDentifier),是基于iOS裝置上面某個單個的應用程式,隻要使用者沒有完全删除應用程式,則這個 UUID 在使用者使用該應用程式的時候一直保持不變。如果使用者删除了這個應用程式,然後再重新安裝,那麼這個 UUID 已經發生了改變。缺點是使用者删除了你開發的程式後,基本上無法擷取關聯之前的資料。
OpenUDID,不是蘋果官方的,是一個替代 UDID 的第三發解決方案, 缺點是如果你完全删除全部帶有OpenUDID SDK 包的App(比如恢複系統等),那麼OpenUDID 會重新生成,而且和之前的值會不同。
IDFA (廣告标示符),蘋果禁用UDID後想出了折中辦法,就是提供另外一套和硬體無關的辨別符,用于給商家監測廣告效果,這就是IDFA。使用者可以在手機設定裡改變這串字元,會導緻商家沒有辦法長期跟蹤使用者行為。
telphone(手機号)。 手機号也可以唯一的辨別使用者。因為兩個人的手機号在同一時間内不會一樣。
上面給出的這幾個資訊都可以唯一辨別一位使用者,可以作為使用者ID号。
假設有一位使用者張三,在第一個手機上使用百度地圖, 在ipad上觀看百度愛奇藝視訊,在第二個手機上使用手機百度app, 在pc電腦上使用百度搜尋,如何将同一個使用者在這些不同端的使用者資訊聚合起來呢?
ID-Mapping主要解決這個問題,用來關聯ID資訊。
算法思路
我們把使用者在各個端的資訊收集起來,假設輸入兩條日志的id資訊為:
line1: < mac1,mac2> < imei1> < tel1>
line2: < mac1> < imei2> < tel1,tel2>
上下是兩條使用者行為日志,看到他們都有mac1,兩條資料應該是同一個使用者。
使用多輪map-reduce的聚合方法,map做資料分塊,reduce做歸并
第一輪,以mac1和 mac2為key字段來map和reduce
Map 輸出:
mac1 line1 < mac1,mac2 > < imei1> < tel1>
mac2 line1 < mac1,mac2> < imei1> < tel1>
mac1 line2 < mac1> < imei2> < tel1,tel2>
Reduce 輸出:
line1 < mac1,mac2> < imei1,imei2> < tel1,tel2>
line1 < mac1,mac2> < imei1> < tel1>
line2 < mac1,mac2> < imei2,imei1> < tel1,tel2>
第二輪, 以line1和 line2為key字段來map和reduce
line2 < mac1,mac2> < imei1,imei2> < tel1,tel2>
第三輪, 以< mac1,mac2>為key字段來map和reduce
Map輸出:
< mac1,mac2> < imei1,imei2> < tel1,tel2>
Reduce輸出:
< mac1, mac2> < imei1,imei2> < tel1,tel2>
依次指定< id >重複上述過程,直到無法歸并
資料和索引設計
資料庫表的設計,設定global-id作為主key,(類似身份證号的作用),其他的字段都可以有多個(map< string,int>),這些用來表示一個使用者的多個身份辨別。
//資料表
global_id string,
imei map<string,int>
mac map<string,int>
imsi map<string,int>
phone_number map<string,int>
idfa map<string,int>
openudid map<string,int>
uid map<string,int>
did map<string,int>
1
2
3
4
5
6
7
8
9
10
例如這四條記錄可以看到其實是一個使用者,存儲的時候就把它們存為一個使用者,用global_id作為key。
由此得到
global_id <=> imei,mac,imsi,phone_number,idfa,openudid,uid,did的互相映射關系。
//索引表
id string
global_id string
線上查詢的時候,假設擷取了mac1類型ID, 根據mac的索引表擷取global_id,然後根據global_id資料表擷取使用者imei、phone_number等其他ID資訊。
ID過期問題
對于僵屍使用者,或者長期不用的使用者,儲存資料沒有意義,浪費資源而且資料長期不更新後可能資料不準确。
可以對每個ID加入活躍度參數,一方面代表使用者的活躍程度,一方面可以對ID的存儲做控制。
使用者行為資料:代表了使用者的活躍度,資料入表活躍度設定為0