實例詳解Redis實現數據的交集、并集和補集

本篇文章給大家帶來了關于redis的相關知識,其中主要介紹了關于實現數據的交集、并集和補集的相關問題,如果全部在jvm內存中進行計算的話,很容易出現內存空間不足導致的oom異常,下面一起來看一下,希望對大家有幫助。

實例詳解Redis實現數據的交集、并集和補集

推薦學習:redis

場景說明

今天我們來模擬一個這樣的場景,我們在本地有多個文本文件,每個文件里面存了很多的32位的字符串作為用戶的唯一標識,每個用戶存做一行,假如我們每天都有非常大規模的用戶,這樣我們可能在工作中就存在需要對這些用戶進行交集、并集或補集等處理,最簡單的方式是通過Java中的集合來進行運算即可,比如通過HashSet來進行相應的一些運算,但是這樣的運算存在一個局限性,那就是我們一般在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

/** * 讀取文件數據并寫入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);          }      }

Redis命令說明


SDIFFSTORE destination key [key …]

舉例說明:

key1 = {a,b,c,d} key2 = {c} key3 = {a,c,e} SDIFF key1 key2 key3 = {b,d}

SDIFFSTORE 命令的作用和SDIFF類似,不同的是它將結果保存到 destination 集合,而把結果集返回給客戶端。

如果 destination 集合已經存在,則將其覆蓋。

  • 返回值
    結果集中成員數量

SINTERSTORE destination key [key …]

舉例說明:

key1 = {a,b,c,d} key2 = {c} key3 = {a,c,e} SINTER key1 key2 key3 = {c}

SINTERSTORE 命令與 SINTER 命令類似,不同的是它并不是直接返回結果集,而是將結果保存在 destination 集合中。

如果 destination 集合存在, 則會被覆蓋。

  • 返回值
    結果集中成員數量

SUNIONSTORE destination key [key …]

舉例說明:

key1 = {a,b,c,d} key2 = {c} key3 = {a,c,e} SUNION key1 key2 key3 = {a,b,c,d,e}

SUNIONSTORE 命令的功能類似于 SUNION,不同的是不反回結果集,而是存儲在 destination 中。

如果 destination 已經存在,則被覆蓋。

  • 返回值
    結果集中的成員數量

推薦學習:redis

? 版權聲明
THE END
喜歡就支持一下吧
點贊13 分享