背景
最近公司做了一些營銷活動,投入資金進行了流量推廣,pv、UV都做了統計。老板說,我要看下用戶的區域分布的數據。
以前的文章我講過,pv、UV如何統計?我們是基于ip進行統計的。用的ip能獲取到,那通過ip查詢歸屬地就ok了。
思維擴展下,ip 查詢歸屬地的的場景還蠻多的,我列舉一些:
場景
- 網絡安全調查:當發生網絡攻擊或惡意行為時,通過查詢IP地址的歸屬地可以幫助調查人員追蹤攻擊者的位置和身份,進而采取相應的應對措施。
- 電商網站反欺詐:電商平臺可以通過查詢IP的歸屬地來檢測是否有異常行為,如異地登錄或使用虛假身份信息下單,從而防止欺詐行為發生。
- 廣告定向投放:在在線廣告市場中,根據用戶所在地區進行IP歸屬地查詢可以幫助廣告主精準定位目標受眾,提高廣告投放效果和ROI。
- 地理位置服務:地圖應用、天氣預報和周邊生活服務等可以利用IP歸屬地查詢來確定用戶的大概地理位置,提供個性化的地理服務和信息。
- 網站流量分析:網站管理員可以利用IP歸屬地查詢來分析網站訪問的地域分布情況,評估市場覆蓋范圍,制定針對性的營銷策略和內容優化計劃。
這些具體的使用場景說明了IP歸屬地查詢在網絡安全、營銷推廣、個性化服務等方面的重要作用,能夠幫助用戶更好地理解用戶行為和優化業務流程。
谷歌搜索了下,第三方提供的ip查詢歸屬地服務,挺多的,但是收費、收費、收費!!!免費也有些,但是怕不穩定。
無意間找到了ip2region這個項目,一直持續維護更新,試用后,效果杠桿的。那我們怎么用的,繼續往下看
ip2region
Ip2region 是什么
ip2region - 是一個離線IP地址定位庫和IP定位數據管理框架,10微秒級別的查詢效率,提供了眾多主流編程語言的 xdb 數據生成和查詢客戶端實現。
Ip2region 特性
1、IP 數據管理框架
xdb 支持億級別的 IP 數據段行數,默認的 region 信息都固定了格式:國家|區域|省份|城市|ISP,缺省的地域信息默認是0。 region 信息支持完全自定義,例如:你可以在 region 中追加特定業務需求的數據,例如:GPS信息/國際統一地域信息編碼/郵編等。也就是你完全可以使用 ip2region 來管理你自己的 IP 定位數據。
2、數據去重和壓縮
xdb 格式生成程序會自動去重和壓縮部分數據,默認的全部 IP 數據,生成的 ip2region.xdb 數據庫是 11MiB,隨著數據的詳細度增加數據庫的大小也慢慢增大。
3、極速查詢響應
即使是完全基于 xdb 文件的查詢,單次查詢響應時間在十微秒級別,可通過如下兩種方式開啟內存加速查詢:
- vIndex 索引緩存 :使用固定的 512KiB 的內存空間緩存 vector index 數據,減少一次 IO 磁盤操作,保持平均查詢效率穩定在10-20微秒之間。
- xdb 整個文件緩存:將整個 xdb 文件全部加載到內存,內存占用等同于 xdb 文件大小,無磁盤 IO 操作,保持微秒級別的查詢效率。
Ip2region 支持那些語言
Ip2region大部分主流語言都支持,支持的語言如下:
Ip2region怎么用
在這里,我以golang語言作為演示,其他語言,可以看下官方文檔
例子:我需要查詢ip為:218.63.140.248 的歸屬地
下載ip2region.xdb包
訪問ip2region 項目,ip的庫文件在data目錄下,點擊下載即可
package 獲取
go get github.com/lionsoul2014/ip2region/binding/golang
完全基于文件的查詢
package mainimport ("fmt""github.com/lionsoul2014/ip2region/binding/golang/xdb""time"
)func main() {//dbPath寫入你下載的ip2region.xdb文件的路徑,我這里放在了當前目錄下var dbPath = "ip2region.xdb"searcher, err := xdb.NewWithFileOnly(dbPath)if err != nil {fmt.Printf("failed to create searcher: %s\n", err.Error())return}defer searcher.Close()// 查詢218.63.140.248對應的地址var ip = "218.63.140.248"var tStart = time.Now()region, err := searcher.SearchByStr(ip)if err != nil {fmt.Printf("failed to SearchIP(%s): %s\n", ip, err)return}fmt.Printf("{region: %s, took: %s}\n", region, time.Since(tStart))// 備注:并發使用,每個 goroutine 需要創建一個獨立的 searcher 對象。
}
查詢結果
此ip的歸屬地為: 中國云南省昆明市電信
緩存整個 xdb 數據
可以預先加載整個 ip2region.xdb 到內存,完全基于內存查詢,類似于之前的 memory search 查詢。
package mainimport ("fmt""github.com/lionsoul2014/ip2region/binding/golang/xdb""time"
)func main() {//dbPath寫入你下載的ip2region.xdb文件的路徑,我這里放在了當前目錄下var dbPath = "ip2region.xdb"// 1、從 dbPath 加載整個 xdb 到內存cBuff, err := xdb.LoadContentFromFile(dbPath)if err != nil {fmt.Printf("failed to load content from `%s`: %s\n", dbPath, err)return}// 2、用全局的 cBuff 創建完全基于內存的查詢對象。searcher, err := xdb.NewWithBuffer(cBuff)if err != nil {fmt.Printf("failed to create searcher with vector index: %s\n", err)return}defer searcher.Close()// 查詢218.63.140.248對應的地址var ip = "218.63.140.248"var tStart = time.Now()region, err := searcher.SearchByStr(ip)if err != nil {fmt.Printf("failed to SearchIP(%s): %s\n", ip, err)return}fmt.Printf("{region: %s, took: %s}\n", region, time.Since(tStart))// 備注:并發使用,每個 goroutine 需要創建一個獨立的 searcher 對象。
}
查詢結果:
方案比對
- 基于文件的查詢,響應時間:38us
- 基于緩存的查詢,響應時間:10.29μs
生成環境使用建議使用方式為:基于緩存的查詢
生產如何使用
以上的演示,只是個demo,如果要放在線上如何使用呢?
- 以sdk的形式嵌入到項目,使用基于緩存的查詢方式。
- ip查詢的場景很多,可以單獨構建一個ip查詢的公共服務,提高給各個業務線使用
sdk接入的方式,用到的業務線都需要對接一次,ip2region.xdb如果有更新,所有用到的項目都要自己去更新升級db文件,維護成本太高。如果你的項目比較單一,sdk接入也是不錯的
我們的方案:因為我業務線相對太多,如果各個業務線自己接,維護的成本太高。我們決定構建IP查詢歸屬地公共服務,往外提供查詢的能力。后續服務的升級、維護等,統一在公共服務里面來做。