利用 ip2region
?進行 IP 地址定位
import ("fmt""log""github.com/lionsoul2014/ip2region/binding/golang/xdb"
)func main() {ip := "213.118.179.98"dbPath := ".\\cmd\\ip\\ip2region.xdb"// 1、初始化查詢器//searcher, err := searcherByFile(dbPath)//searcher, err := searcherByVectorIndex(dbPath)searcher, err := searcherByBuffer(dbPath)// 2、執行查詢resp, err := searcher.SearchByStr(ip)if err != nil {log.Fatal("failed to search ip", err)}fmt.Printf("IP: %s, Location: %s\n", ip, resp)
}
方式1:完全基于文件的查詢
func searcherByFile(dbPath string) (*xdb.Searcher, error) {searcher, err := xdb.NewWithFileOnly(dbPath)if err != nil {log.Println("Failed to load ip2region database", err)return nil, err}return searcher, nil
}
特點
- 內存占用少:這種方法不會將數據庫文件加載到內存,而是在查詢時直接從磁盤讀取文件,所以內存占用非常少。
- 查詢速度較慢:由于每次查詢都需要進行磁盤 I/O 操作,所以查詢速度相對較慢,尤其是在高并發場景下,頻繁的磁盤 I/O 可能會成為性能瓶頸。
- 并發使用限制:和?
searcherByVectorIndex
?方法一樣,并發使用時每個 goroutine 都要創建獨立的?searcher
?對象。
方式2:緩存 VectorIndex 索引
func searcherByVectorIndex(dbPath string) (*xdb.Searcher, error) {vIndex, err := xdb.LoadVectorIndexFromFile("ip2region.xdb")if err != nil {log.Println("Failed to load vector index", err)return nil, err}searcher, err := xdb.NewWithVectorIndex(dbPath, vIndex)if err != nil {log.Println("Failed to create searcher with vector index", err)return nil, err}return searcher, nil
}
特點
- 性能優化:借助加載?
VectorIndex
?緩存,查詢時能減少磁盤 I/O 操作。VectorIndex
?是一種索引結構,可快速定位到可能包含目標 IP 的數據塊,從而加快查詢速度。 - 內存占用適中:相較于將整個數據庫加載到內存,僅加載?
VectorIndex
?緩存占用的內存較少,不過比直接從文件查詢時占用的內存多。 - 并發使用限制:并發使用時,每個 goroutine 都要創建獨立的?
searcher
?對象,因為?searcher
?并非線程安全的。
方式3:緩存整個數據庫
func searcherByBuffer(dbPath string) (*xdb.Searcher, error) {buff, err := xdb.LoadContentFromFile(dbPath)if err != nil {log.Println("Failed to load ip2region database", err)return nil, err}searcher, err := xdb.NewWithBuffer(buff)if err != nil {fmt.Println("failed to create searcher with content", err)return nil, err}return searcher, nil
}
特點
- 查詢速度最快:該方法把整個數據庫文件加載到內存中,查詢時無需進行磁盤 I/O 操作,直接在內存中進行查找,因此查詢速度最快。
- 內存占用大:需要將整個數據庫文件加載到內存,所以內存占用較大。如果數據庫文件較大,可能會對系統內存造成壓力。
- 并發安全:使用整個數據庫緩存創建的?
searcher
?對象可以安全地用于并發,多個 goroutine 可以共享同一個?searcher
?對象,無需為每個 goroutine 創建獨立的?searcher
?對象。
總結
- 若系統內存有限,對查詢速度要求不高,可選用?
searcherByFile
?方法。 - 若希望在內存占用和查詢速度之間取得平衡,可采用?
searcherByVectorIndex
?方法。 - 若系統內存充足,對查詢速度要求極高,且有高并發查詢需求,可使用?
searcherByBuffer
?方法。