2

関連する ISP 情報とともに IP 番号を redis に保存しようとしています。Maxmind データがあり、csv ファイルには各 ISP の開始番号と終了番号が含まれています。

SQL でクエリを実行すると、(数値に変換した後) IP が範囲内で使用可能かどうかを確認し、関連する ISP を取得できます。

すべての範囲を個々の数値に変換し、Redis ですべてのキーと値のペアを送信して、ルックアップを高速化することを考えていました。これにより、およそ 40 億のキーと値のペアが Redis ストアに作成されます。私は数億のキーと値のペアに対してこれを行いましたが、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(ホスト='localhost'、ポート=6379、デシベル=0)
ispctr = 1
結果の行:
    tempDict = {'ispname':row[2],'fromval':row[0],'toval':row[1]}
    名前フィールド = 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']
ipstotest の ip の場合:
    ipvalsList = [ip.split('.') の ipoct の場合は int(ipoct)]
    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']
4

4 に答える 4

4

やり方が間違っていると思います。

IP マッピングを整数範囲 (IP から IP まで、10 進数に変換) として保持し、従来の DB または比較に強い NoSQL を使用して対象の IP をすばやくクエリします。

于 2012-05-07T09:46:44.470 に答える
3

4B のアイテムを Redis に格納してもパフォーマンスが特に低下することはありませんが、これにはメモリが必要です (つまり、すべてがメモリに収まる必要があります)。

この種のクエリを Redis で実装する最適な方法は、次のとおりです。

IP 範囲を Redis に保存する

そしてここ:

数値が範囲内にあるかどうかを判断するためのRedisまたはMongo?

したがって、最適なソリューションの複雑さは、IP の範囲が重複する可能性があるかどうかによって異なります。

于 2012-05-07T10:21:36.127 に答える
2

高速Geo-IP解決に使用するアプローチは、すべてのIP範囲を取得し、それらを/24(最初の3つのクワッド)で分割し、それらのアドレスにすべての一致を保持するレコードを保存することです。これにより、1600万のキーとO(1)アクセスが可能になります。保存されたレコードを分割するというクライアント側の複雑さを許容する場合は、RAMを大量に消費することなくパフォーマンスを発揮します。

さらに詳細に:

  • すべての範囲を取得し、最初の24ビットで分割します。
    • 範囲128.100.60.0-128.100.60.9は1レコードになり、<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ことがわかりましたが、それは大きかったので、戻ります。9255recB

これは、Hadoopのようなもので範囲結合(空間結合でさえも!)を行うための一般的な戦略です。適切なチャンクでパーティションを作成し、範囲の一方の端でインデックスを作成します。

于 2012-12-18T02:52:25.487 に答える
2

geodisを使用するだけです。すでに国/場所へのIPルックアップを実行し、それらのデータを効率的に保存します。データの読み込みにのみ自由に使用でき、redis自体から直接データをリクエストできます。

于 2012-05-07T15:41:05.027 に答える