【问题标题】:More than 4 billion key value pairs in Redis?Redis 中超过 40 亿个键值对?
【发布时间】:2012-05-07 08:16:36
【问题描述】:

我正在尝试将 ip 号码与相关的 ISP 信息一起存储在 redis 中。我有 Maxmind 数据,并且 csv 文件包含每个 ISP 的开始和结束编号。

在 SQL 中查询时,我可以检查某个 IP(将其转换为数字后)是否在某个范围内可用并获取相关的 ISP。

我正在考虑将所有范围转换为单独的数字,并在 Redis 中提交所有键值对以加快查找速度。 这大约会在 Redis 存储中产生 40 亿个键值对。 我已经为几亿个键值对做了这个,但是当我在 Redis 中移动到 40 亿对时,我正在寻找建议/建议。 我必须注意的任何性能问题,或者有什么方法可以更好地做到这一点?

感谢您的所有建议。

更新:感谢下面的建议,我可以让它工作。 以为我会在这里分享 Python 代码(又快又脏):

导入redis 导入 pymysql conn = pymysql.connect(host='localhost',user='user',passwd='password',db='foo') cur = conn.cursor() cur.execute('select startipnum,endipnum,isp from wiki.ipisp order by endipnum;') 结果 = cur.fetchall() r = redis.StrictRedis(host='localhost', port=6379, db=0) ispctr = 1 结果中的行: tempDict = {'ispname':row[2],'fromval':row[0],'toval':row[1]} 名称字段 = ispctr r.hmset(名称字段,tempDict) r.zadd('ispmaxindex',row[1],namefield) ispctr = ispctr+1 conn.close() ipstotest = ['23.23.23.23','24.96.185.10','203.59.91.235','188.66.105.50','99.98.163.93'] 对于 ipstotest 中的 ip: ipvalsList = [int(ipoct) for ipoct in ip.split('.')] ipnum = (16777216*ipvalsList[0]) + (65536*ipvalsList[1]) + (256*ipvalsList[2]) + ipvalsList[3] ipnum = long(ipnum) tempVal1 = r.zrangebyscore('ispmaxindex',ipnum,float('Inf'),0,1) tempval2 = r.hgetall(tempval1[0]) 打印 tempval2['ispname']

【问题讨论】:

    标签: redis


    【解决方案1】:

    我认为这是错误的做法。

    将 IP 映射保持为整数范围(从 IP - 到 IP,converted to decimal)并使用传统数据库或使用强大的比较功能的 NoSQL 快速查询您的主题 IP。

    【讨论】:

    • 这就是我从 maxmind 得到的,从和到的 IP 范围转换为十进制。我尝试了 MySQL,范围查询似乎很慢,这就是为什么我认为键值查找会更快/更有效。当我监控访问我的网站的 IP 时,我还想实时查找(过去 5 分钟内的所有 ip ~ 5000+ IP)
    • 根据您网站的使用配置文件,您可以在 Redis 中缓存匹配项(除了我建议的内容)。那就是 - 一旦你找到一个从到匹配到给定 IP,将它保存在 Redis 中。如果您的使用配置文件包含频繁的回访者或来自同一区域的访问者,则此有限大小的缓存将为您提供出色的性能,而不会遇到 Redis 内存大小问题。
    • Offer..那是目标。这就是我现在正在做的事情,并根据高于频率阈值的访问者逐步添加到我的 Redis 商店。感谢您的建议。
    【解决方案2】:

    您可以在 Redis 中存储 4B 项,而不会降低性能,但您需要内存(即所有内容都必须适合内存)。

    此处描述了使用 Redis 实现此类查询的最佳方法:

    store ip ranges in Redis

    这里:

    Redis or Mongo for determining if a number falls within ranges?

    因此,最佳解决方案的复杂性取决于您认为 IP 范围可以重叠与否这一事实。

    【讨论】:

    • 非常有用的链接。将更多地探索这些。谢谢迪迪埃。
    【解决方案3】:

    只需使用geodis。它已经进行了 IP 到国家/地区的查找,并为您有效地存储了这些数据。您可以免费使用它,仅用于数据加载和直接从 redis 本身请求数据。

    【讨论】:

      【解决方案4】:

      我们用于快速 Geo-IP 解析的方法是获取所有 IP 范围并在 /24(前三个四边形)处打破它们,并在这些地址中存储包含所有匹配项的记录。这为您提供了 1600 万个密钥和 O(1) 访问权限。如果您能容忍分解存储记录的客户端复杂性,那么它在不占用大量 RAM 的情况下表现出色。

      更详细的:

      • 获取所有范围,并按前 24 位对其进行拆分。
        • 范围128.100.60.0-128.100.60.9变成一条记录,<128.100.60 | 0 9 | (...recA...)>
        • 128.100.60.10 - 128.100.62.80 的范围将变为<128.100.60 | 10 255 | (...recB...)><128.100.61 | 0 255 | (...recB...)><128.100.62 | 0 80 | (...recB...)>
      • 将所有具有相同前缀的记录组合成一个散列,其键是其范围的top。所以
        • 128.100.60:{9: {...recA...}, 255: {...recB...}}
        • 128.100.61:{255: {...recB...}}
        • 128.100.62:{80: {...recB...}, ...}

      要检索特定IP,通过其24位键检索复合记录,并返回子键大于最后一部分的第一个结果。如果我查找128.100.60.20,我会发现9 没有更大,但255 更大,所以返回recB

      这是在 Hadoop 等事物中进行范围连接(甚至是空间连接!)的常用策略:在某个合理的块上分区,然后在范围的一端建立索引。

      【讨论】:

        猜你喜欢
        • 2020-07-01
        • 2014-07-29
        • 1970-01-01
        • 1970-01-01
        • 2012-05-31
        • 2022-12-17
        • 2011-06-12
        • 2023-02-21
        • 1970-01-01
        相关资源
        最近更新 更多