我正在尝试在redis中存储ip号以及相关的ISP信息。我有Maxmind数据,csv文件包含每个ISP的开始和结束编号。
在SQL中查询时,我可以检查IP(在将其转换为数字后)以在一个范围内可用并获得相关的ISP。
我正在考虑将所有范围转换为单个数字,并在Redis中提交所有键值对以便更快地查找。 这大约将导致Redis商店中的40亿个键值对。 我已经完成了几亿个关键值对,但我正在寻找建议/建议,在Redis中转向40亿对。 我必须注意哪些性能问题,或者我有什么方法可以做得更好?
感谢您提出的所有建议。
更新:感谢下面的建议,我可以让这个工作。 以为我会在这里分享Python代码(快速和脏):
import redis import 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;') result = cur.fetchall() r = redis.StrictRedis(host='localhost', port=6379, db=0) ispctr = 1 for row in result: tempDict = {'ispname':row[2],'fromval':row[0],'toval':row[1]} namefield = ispctr r.hmset(namefield,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'] for ip in ipstotest: 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]) print tempval2['ispname']
答案 0 :(得分:4)
我认为这是错误的做法。
将IP映射保持为整数范围(从IP到IP,converted to decimal)并使用传统数据库或使用比较强的NoSQL快速查询主题IP。
答案 1 :(得分:3)
你可以在Redis中存储4B项而不会降低性能,但你需要内存(即一切都必须适合内存)。
此处描述了使用Redis实现此类查询的最佳方法:
在这里:
Redis or Mongo for determining if a number falls within ranges?
因此,最优解决方案的复杂性取决于您认为IP范围是否重叠的事实。
答案 2 :(得分:2)
只需使用geodis即可。它已经为国家/位置查找提供IP,并为您有效地存储这些数据。您可以自由地仅将其用于数据加载,并直接从redis本身请求数据。
答案 3 :(得分:2)
我们用于快速地理IP分辨率的方法是采用所有IP范围并在/24
(前三个四边形)中断开它们,并存储包含这些地址中所有匹配的记录。这为您提供了1600万个密钥和O(1)访问权限。如果你能够容忍客户端分解存储记录的复杂性,那么它的性能不会占用大量的RAM。
更详细:
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...)>
。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之类的事情中进行范围连接(甚至空间连接!)的常用策略:在一些合理的块上进行分区,然后在范围的一端进行索引。