實例詳解Redis實現資料的交集、並集和補集
本篇文章為大家帶來了關於Redis的相關知識,其中主要介紹了關於實現資料的交集、並集和補集的相關問題,如果全部在JVM記憶體中進行計算的話,很容易出現記憶體空間不足導致的OOM異常,下面一起來看一下,希望對大家有幫助。
推薦學習: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 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);
}
登入後複製
/** * 初始化数据并写入文件中 */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);
}}
登入後複製
/** * 读取文件数据并写入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);
}
}
登入後複製
/** * 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);
}
}
登入後複製
/** * 将计算的差集数据写入到指定文件 */ 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);
}
}
登入後複製
/** * * @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);
}
}
登入後複製
/** * 将计算的交集数据写入到指定文件 */ 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);
}
}
登入後複製
/** * 计算多个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);
}
}
登入後複製
/** * 将计算的并集数据写入到指定文件 */ 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}
- 傳回值
- 結果集中成員數量
#SINTERSTORE destination key [key …]
範例說明:key1 = {a,b,c,d} key2 = {c} key3 = {a,c,e} SINTER key1 key2 key3 = {c}
- 傳回值
- 結果集中成員數量
#SUNIONSTORE destination key [key …]
範例說明:key1 = {a,b,c,d} key2 = {c} key3 = {a,c,e} SUNION key1 key2 key3 = {a,b,c,d,e}
- 傳回值
- 結果集中的成員數
以上是實例詳解Redis實現資料的交集、並集和補集的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

Redis集群模式通過分片將Redis實例部署到多個服務器,提高可擴展性和可用性。搭建步驟如下:創建奇數個Redis實例,端口不同;創建3個sentinel實例,監控Redis實例並進行故障轉移;配置sentinel配置文件,添加監控Redis實例信息和故障轉移設置;配置Redis實例配置文件,啟用集群模式並指定集群信息文件路徑;創建nodes.conf文件,包含各Redis實例的信息;啟動集群,執行create命令創建集群並指定副本數量;登錄集群執行CLUSTER INFO命令驗證集群狀態;使

如何清空 Redis 數據:使用 FLUSHALL 命令清除所有鍵值。使用 FLUSHDB 命令清除當前選定數據庫的鍵值。使用 SELECT 切換數據庫,再使用 FLUSHDB 清除多個數據庫。使用 DEL 命令刪除特定鍵。使用 redis-cli 工具清空數據。

要從 Redis 讀取隊列,需要獲取隊列名稱、使用 LPOP 命令讀取元素,並處理空隊列。具體步驟如下:獲取隊列名稱:以 "queue:" 前綴命名,如 "queue:my-queue"。使用 LPOP 命令:從隊列頭部彈出元素並返回其值,如 LPOP queue:my-queue。處理空隊列:如果隊列為空,LPOP 返回 nil,可先檢查隊列是否存在再讀取元素。

使用 Redis 指令需要以下步驟:打開 Redis 客戶端。輸入指令(動詞 鍵 值)。提供所需參數(因指令而異)。按 Enter 執行指令。 Redis 返迴響應,指示操作結果(通常為 OK 或 -ERR)。

在CentOS系統上,您可以通過修改Redis配置文件或使用Redis命令來限制Lua腳本的執行時間,從而防止惡意腳本佔用過多資源。方法一:修改Redis配置文件定位Redis配置文件:Redis配置文件通常位於/etc/redis/redis.conf。編輯配置文件:使用文本編輯器(例如vi或nano)打開配置文件:sudovi/etc/redis/redis.conf設置Lua腳本執行時間限制:在配置文件中添加或修改以下行,設置Lua腳本的最大執行時間(單位:毫秒)

使用Redis進行鎖操作需要通過SETNX命令獲取鎖,然後使用EXPIRE命令設置過期時間。具體步驟為:(1) 使用SETNX命令嘗試設置一個鍵值對;(2) 使用EXPIRE命令為鎖設置過期時間;(3) 當不再需要鎖時,使用DEL命令刪除該鎖。

使用 Redis 命令行工具 (redis-cli) 可通過以下步驟管理和操作 Redis:連接到服務器,指定地址和端口。使用命令名稱和參數向服務器發送命令。使用 HELP 命令查看特定命令的幫助信息。使用 QUIT 命令退出命令行工具。

Redis數據過期策略有兩種:定期刪除:定期掃描刪除過期鍵,可通過 expired-time-cap-remove-count、expired-time-cap-remove-delay 參數設置。惰性刪除:僅在讀取或寫入鍵時檢查刪除過期鍵,可通過 lazyfree-lazy-eviction、lazyfree-lazy-expire、lazyfree-lazy-user-del 參數設置。
