2012-05-07 5 views
1

私はredisに関連するISP情報とともにIP番号を格納しようとしています。私はMaxmindのデータを持っており、csvファイルには各ISPの開始番号と終了番号が入っています。Redisでは40億以上のキー値ペアがありますか?

SQLでクエリを実行しているときに、範囲内で使用できるようにIPをチェックして、関連するISPを取得できます。

私はすべての範囲を個別の数値に変換し、高速検索のためにRedisですべてのキー値のペアを送信することを考えていました。 これはおよそ40億のキー値ペアをRedisストアにもたらします。 私は数億のキーバリューのペアでこれを行ってきましたが、私は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'] 

答えて

3

4Bのアイテムはレディスに保存できますが、パフォーマンスは特に低下することはありませんが、メモリが必要です(つまり、すべてがメモリに収まる必要があります)。 Redisの持つクエリのこの種を実装する

最適な方法はここに記載されている:

store ip ranges in Redis

、ここに:

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

ので、最適なソリューションの複雑さが依存しますIPの範囲を考慮するという事実は、重複していてもいなくてもかまいません。

+0

本当に役に立つリンク。これらをさらに探求します。ありがとう、ディディエ。 – harshsinghal

4

私はそれはそれを行うには間違った方法だと信じています。

IPマッピングを整数範囲(IP-To IP、converted to decimal)にしておき、伝統的なDBを使用するか、比較に強いNoSQLを使用して、対象IPをすばやく照会します。

+0

これは私がmaxmindから持っているもので、IPの範囲は10進数に変換されます。私はMySQLを試してみましたが、レンジクエリでは速度が遅くなりました。キー値の検索がより高速で効率的になると思った理由です。また、自分のWebサイトにIPが流れていることを監視しているときに、リアルタイムで検索したい(最後の5分間〜5000回以上のIP)。 – harshsinghal

+0

サイトの利用状況に応じて、Redisでの一致をキャッシュすることができる。私が提案したもの)。つまり、あるIPアドレスに一致するものが見つかると、それをRedisに保存します。あなたの使用状況プロフィールが頻繁に帰国した訪問者または同じ地域の訪問者で構成されている場合、この限られたサイズのキャッシュはRedisのメモリサイズの問題に陥ることなく優れたパフォーマンスを提供します。 –

+1

Ofer..thatsは標的に打撃を与える。これは私が今やっていることであり、頻度閾値以上の訪問者に基づいてRedisストアに段階的に追加しています。あなたの提案をありがとう。 – harshsinghal

2

geodisをそのまま使用してください。すでにIPを国/地域の検索に使用し、それらのデータを効率的に保存します。あなたはデータの読み込みにのみ自由に使用でき、赤字自体から直接データを要求します。

+0

ジオディスはきれいです。ありがとう。 – harshsinghal

2

私たちが高速なGeo-IP解決に使用するアプローチは、すべてのIP範囲を取り、/24(最初の3つのクワッド)で分割し、すべての一致をそのレコードに格納します。これにより、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...)>なるとなります。
  • 同じプレフィックスを持つすべてのレコードを、そのキーの範囲がのハッシュに結合します。 128.100.60だから、
    • キー:{9: {...recA...}, 255: {...recB...}}
    • キー128.100.61{255: {...recB...}}
    • キー128.100.62{80: {...recB...}, ...}

その24ビットキーによる化合物レコードを取得し、特定のIPを取得するために、そしてサブキーが最後の部分よりも大きい最初の結果を返します。 128.100.60.20を調べると、9は大きくないが、255だったので、recBを返します。

これは、Hadoopのようなもので範囲結合(空間結合を含む)を行う一般的な戦略です。妥当なチャンクでパーティションを作成し、範囲の一端でインデックスを作成することです。

関連する問題