使用redis有序集合sorted set設計高效查詢ip所在地

1、將純真版ip數據  xxx.data 導入至 redis(整個過程只花費了幾秒)

引入nuget包 CSRedisCore,使用方法見:https://github.com/2881099/csredis

/// <summary>
/// 更新ip庫,請先將ip庫上傳至 /data/qqwry.dat,gb2312格式
/// </summary>
/// <returns></returns>
[HttpPost("update_ip")]
public APIReturn 更新ip庫() {
	RedisHelper.Remove("iplib");
	var lines = Encoding.GetEncoding("GB2312").GetString(System.IO.File.ReadAllBytes("/data/qqwry.dat")).Split(new string[] { "\r\n" }, StringSplitOptions.None);
	var lines_index = 0;
	while(lines_index < lines.Length) {
		var members = new List<(double, string)>();
		for (var b = 0; b < 50000; b++) {
			try {
				var ipstart = Lib.Ip2Long(lines[lines_index].Substring(0, 15).Trim());
				var ipend = Lib.Ip2Long(lines[lines_index].Substring(16, 15).Trim());
				var location = lines[lines_index].Substring(32).Replace("CZ88.NET", "").Trim();

				members.Add((ipend, $"{ipstart}-{ipend} {location}"));
			} catch {

			}
			if (++lines_index >= lines.Length) break;
		}
		if (members.Count > 0)
			RedisHelper.ZAdd("iplib", members.ToArray());
	}

	return AR.成功;
}
public static long Ip2Long(string ip) {
	char[] separator = new char[] { '.' };
	string[] items = ip.Split(separator);
	return long.Parse(items[0]) << 24
		| long.Parse(items[1]) << 16
		| long.Parse(items[2]) << 8
		| long.Parse(items[3]);
}
public static string Long2Ip(long ipInt) {
	StringBuilder sb = new StringBuilder();
	sb.Append((ipInt >> 24) & 0xFF).Append(".");
	sb.Append((ipInt >> 16) & 0xFF).Append(".");
	sb.Append((ipInt >> 8) & 0xFF).Append(".");
	sb.Append(ipInt & 0xFF);
	return sb.ToString();
}

 

2、定義根據ip查詢所在地的函數(單次查詢效率在1ms以內)

 

public static string GetLocationByIpAddress(string ip) {
	if (string.IsNullOrEmpty(ip)) return "未知";
	var find = RedisHelper.ZRangeByScore("iplib", Lib.Ip2Long(ip), double.MaxValue, 1, 0);
	if (find.Any()) return find.First().Substring(find.First().IndexOf(' '));
	return "未知";
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章