使用redis有序集合sorted set设计高效查询ip所在地

1、将纯真版ip数据  xxx.data 导入至 redis(整个过程只花费了几秒)

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/// <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.成功;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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以内)

 

1
2
3
4
5
6
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 "未知";
}

 

posted @   nicye  阅读(602)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架
点击右上角即可分享
微信分享提示