この記事では、Redis に関する関連知識を提供します。主に、データの交差、結合、補数の実現に関する関連問題を紹介します。すべての計算が JVM メモリ内で実行される場合、その場合、次のような問題が発生しやすくなります。メモリ容量不足による OOM 例外について見ていきましょう。皆様のお役に立てれば幸いです。
推奨される学習: Redis ビデオ チュートリアル
今日は、このようなシナリオをシミュレーションします。ローカルに複数のテキスト ファイルがある。各ファイルには、ユーザーの一意の識別子として多くの 32 ビット文字列が保存されている。各ユーザーは 1 行を保存している。毎日非常に多くのユーザーがいる場合、仕事中に、これらのユーザーに対して交差、結合、または補数の処理を実行する最も簡単な方法は、HashSet を使用して対応する操作を実行するなど、Java でセットを介して操作を実行することですが、そのような操作は存在します 1 つの制限は、一般に JVM 操作中の初期メモリが限られていることですすべての計算が JVM メモリ内で実行されると、メモリ容量不足による OOM 例外が発生しやすくなります。そこで、今日は拡張機能を紹介します。このような交差および補完演算を実行するためのより柔軟な方法: Redis を使用して交差を実現し、データの結合と補完
Redis バージョン: Redis 6.0.6
Jedis バージョン: 4.2.2
ツール hutool バージョン: 5.8.0.M3
##pom ファイル:
<dependencies> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>4.2.2</version> </dependency> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.8.0.M3</version> </dependency></dependencies>
public class RedisCalculateUtils { static String oneFileString = "/Users/tmp/test-1.txt"; static String twoFileString = "/Users/tmp/test-2.txt"; static String diffFileString = "/Users/tmp/diff-test.txt"; static String interFileString = "/Users/tmp/inter-test.txt"; static String unionFileString = "/Users/tmp/union-test.txt"; static String oneFileCacheKey = "oneFile"; static String twoFileCacheKey = "twoFile"; static String diffFileCacheKey = "diffFile"; static String interFileCacheKey = "interFile"; static String unionFileCacheKey = "unionFile"; }
/** * 初始化数据并写入文件中 */public static void writeFile() { File oneFile = new File(oneFileString); List<String> fs = new ArrayList<>(10000); for (int i = 10000; i < 15000; i++) { String s = SecureUtil.md5(String.valueOf(i)); fs.add(s); } FileUtil.writeUtf8Lines(fs, oneFile); File twoFile = new File(twoFileString); fs.clear(); for (int i = 12000; i < 20000; i++) { String s = SecureUtil.md5(String.valueOf(i)); fs.add(s); } FileUtil.writeUtf8Lines(fs, twoFile); }
/** * 读取文件数据并写入Redis */public static void writeCache() { try(Jedis jedis = new Jedis("127.0.0.1", 6379)) { Pipeline p = jedis.pipelined(); List<String> oneFileStringList = FileUtil.readLines(oneFileString, "UTF-8"); for (String s : oneFileStringList) { p.sadd(oneFileCacheKey, s); } p.sync(); List<String> twoFileStringList = FileUtil.readLines(twoFileString, "UTF-8"); for (String s : twoFileStringList) { p.sadd(twoFileCacheKey, s); } p.sync(); } catch (Exception e) { throw new RuntimeException(e); }}
/** * oneKey对应的Set 与 twoKey对应的Set 的差集 并写入 threeKey * @param oneKey 差集前面的集合Key * @param twoKey 差集后面的集合Key * @param threeKey 差集结果的集合Key */ public static void diff(String oneKey, String twoKey, String threeKey) { try(Jedis jedis = new Jedis("127.0.0.1", 6379)) { long result = jedis.sdiffstore(threeKey, oneKey, twoKey); System.out.println("oneKey 与 twoKey 的差集的个数:" + result); } catch (Exception e) { throw new RuntimeException(e); } }
/** * 将计算的差集数据写入到指定文件 */ public static void writeDiffToFile() { File diffFile = new File(diffFileString); try(Jedis jedis = new Jedis("127.0.0.1", 6379)) { Set<String> result = jedis.smembers(diffFileCacheKey); FileUtil.writeUtf8Lines(result, diffFile); } catch (Exception e) { throw new RuntimeException(e); } }
/** * * @param cacheKeyArray 交集集合Key * @param destinationKey 交集集合结果Key */ public static void inter(String[] cacheKeyArray, String destinationKey) { try(Jedis jedis = new Jedis("127.0.0.1", 6379)) { long result = jedis.sinterstore(destinationKey, cacheKeyArray); System.out.println("cacheKeyArray 的交集的个数:" + result); } catch (Exception e) { throw new RuntimeException(e); } }
/** * 将计算的交集数据写入到指定文件 */ public static void writeInterToFile() { File interFile = new File(interFileString); try(Jedis jedis = new Jedis("127.0.0.1", 6379)) { Set<String> result = jedis.smembers(interFileCacheKey); FileUtil.writeUtf8Lines(result, interFile); } catch (Exception e) { throw new RuntimeException(e); } }
/** * 计算多个Key的并集并写入到新的Key * @param cacheKeyArray 求并集的Key * @param destinationKey 并集结果写入的KEY */ public static void union(String[] cacheKeyArray, String destinationKey) { try(Jedis jedis = new Jedis("127.0.0.1", 6379)) { long result = jedis.sunionstore(destinationKey, cacheKeyArray); System.out.println("cacheKeyArray 的并集的个数:" + result); } catch (Exception e) { throw new RuntimeException(e); } }#和合計算の結果を指定されたファイルに書き込みます
/** * 将计算的并集数据写入到指定文件 */ public static void writeUnionToFile() { File unionFile = new File(unionFileString); try(Jedis jedis = new Jedis("127.0.0.1", 6379)) { Set<String> result = jedis.smembers(unionFileCacheKey); FileUtil.writeUtf8Lines(result, unionFile); } catch (Exception e) { throw new RuntimeException(e); } }
key1 = {a,b,c,d} key2 = {c} key3 = {a,c,e} SDIFF key1 key2 key3 = {b,d}SDIFFSTORE コマンドは SDIFF に似ていますが、結果を宛先セットに保存し、結果セットをクライアントに返す点が異なります。
宛先コレクションが既に存在する場合、上書きされます。
#戻り値
結果セット内のメンバーの数key1 = {a,b,c,d} key2 = {c} key3 = {a,c,e} SINTER key1 key2 key3 = {c}SINTERSTORE コマンドは、結果セットを直接返すのではなく、結果を宛先コレクションに保存する点を除けば、SINTER コマンドと似ています。
結果セット内のメンバーの数
key1 = {a,b,c,d} key2 = {c} key3 = {a,c,e} SUNION key1 key2 key3 = {a,b,c,d,e}
結果セット内のメンバーの数
推奨される学習:以上がRedis がデータの交差、結合、および補完を実装する方法の詳細な例の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。