【技術派后端篇】技術派中的白名單機制:基于Redis的Set實現

在技術派社區中,為了保證文章的質量和社區的良性發展,所有發布的文章都需要經過審核。然而,并非所有作者的文章都需要審核,我們通過白名單機制來優化這一流程。本文將詳細介紹技術派中白名單的實現方式,以及如何利用Redis的Set數據結構來管理白名單。

1 為什么要審核?

雖然大部分作者發布的文章都是高質量的,但也有一些作者只是為了體驗發文流程而發布測試內容。如果不經過審核直接上線,可能會導致社區文章質量的下降。因此,審核機制是保證社區文章質量的重要手段。

2 白名單的實現方案

在技術派中,我們為部分作者設置了白名單,這些作者發布的文章無需審核即可直接上線。白名單的實現有多種方案,我們選擇了基于Redis的Set數據結構來實現。以下是幾種可選的方案及其優缺點:

方案優點缺點適用場景
配置文件寫死(硬編碼方式)簡單不靈活,每次改動需改代碼發版,不適用于實際生產項目對配置變動需求極低的簡單測試場景
數據庫配置白名單表靈活,適用性強實現有點重生產環境中對配置靈活性要求高,且能接受一定實現復雜度的場景
基于redis的set實現白名單實現簡單,輕量依賴redis對性能要求較高、且項目中已使用redis,對配置管理有一定靈活性需求的場景

3 技術派中的白名單實現策略

技術派中的白名單就是基于Redis的Set來實現的。以下是詳細的實現策略:

3.1 Redis Set的基本操作

以下是Redis Set的一些基本操作命令:

  • 添加成員SADD key val1 val2
  • 獲取集合成員數量SCARD key
  • 判斷成員是否存在SISMEMBER key val,返回1表示存在,0表示不存在
  • 獲取所有成員SMEMBERS key
  • 隨機移除成員SPOP key
  • 隨機返回成員SRANDMEMBER key count
  • 刪除成員SREM key val

此外,Set還支持多個集合之間的操作,如求差集、交集、并集等。

  • 返回第一個集合與其他集合之間的差異sdiff key1 key2 key3...
  • 返回所有給定集合的差值,并存儲在destinationsdiffstore destination key1 key2 key3...
  • 返回給定集合的交集sinter key1 key2
  • 返回給定集合的交集,并存儲在destination集合中sinterstore destination key1 key2...
  • 返回所有給定集合的并集sunion key1 key2...
  • 返回所有給定集合的并集,并存儲在destination集合中sunionstore destination key1 key2...

3.2 Spring項目中使用RedisTemplate操作Set

在Spring項目中,我們可以使用RedisTemplate來操作Redis的Set。以下是一些常用的操作示例:

  • 新增成員
public void add(String key, String value) {redisTemplate.opsForSet().add(key, value);
}
  • 刪除成員
public void remove(String key, String value) {redisTemplate.opsForSet().remove(key, value);
}
  • 判斷成員是否存在
public void contains(String key, String value) {redisTemplate.opsForSet().isMember(key, value);
}
  • 獲取所有成員
public Set<String> values(String key) {return redisTemplate.opsForSet().members(key);
}
  • 集合運算
public Set<String> union(String key1, String key2) {return redisTemplate.opsForSet().union(key1, key2);
}public Set<String> intersect(String key1, String key2) {return redisTemplate.opsForSet().intersect(key1, key2);
}public Set<String> diff(String key1, String key2) {return redisTemplate.opsForSet().difference(key1, key2);
}

3.3 白名單的使用實例

在技術派中,白名單的相關業務邏輯封裝在com.github.paicoding.forum.service.user.service.AuthorWhiteListService中。以下是一些核心方法:

  • 判斷作者是否在白名單中boolean authorInArticleWhiteList(Long authorId);

  • 獲取所有白名單用戶List<BaseUserInfoDTO> queryAllArticleWhiteListAuthors();

  • 添加用戶到白名單void addAuthor2ArticleWhitList(Long userId);

  • 從白名單中移除用戶void removeAuthorFromArticelWhiteList(Long userId);

實現代碼如下:

@Service
public class AuthorWhiteListServiceImpl implements AuthorWhiteListService {/*** 實用 redis - set 來存儲允許直接發文章的白名單*/private static final String ARTICLE_WHITE_LIST = "auth_article_white_list";@Autowiredprivate UserService userService;@Overridepublic boolean authorInArticleWhiteList(Long authorId) {return RedisClient.sIsMember(ARTICLE_WHITE_LIST, authorId);}/*** 獲取所有的白名單用戶** @return*/@Overridepublic List<BaseUserInfoDTO> queryAllArticleWhiteListAuthors() {Set<Long> users = RedisClient.sGetAll(ARTICLE_WHITE_LIST, Long.class);if (CollectionUtils.isEmpty(users)) {return Collections.emptyList();}List<BaseUserInfoDTO> userInfos = userService.batchQueryBasicUserInfo(users);return userInfos;}@Overridepublic void addAuthor2ArticleWhitList(Long userId) {RedisClient.sPut(ARTICLE_WHITE_LIST, userId);}@Overridepublic void removeAuthorFromArticleWhiteList(Long userId) {RedisClient.sDel(ARTICLE_WHITE_LIST, userId);}
}

核心封裝的幾個公共方法,位于com.github.paicoding.forum.core.cache.RedisClient#sIsMember

/*** 判斷value是否再set中** @param key* @param value* @return*/
public static <T> Boolean sIsMember(String key, T value) {return template.execute(new RedisCallback<Boolean>() {@Overridepublic Boolean doInRedis(RedisConnection connection) throws DataAccessException {return connection.sIsMember(keyBytes(key), valBytes(value));}});
}/*** 獲取set中的所有內容** @param key* @param clz* @param <T>* @return*/
public static <T> Set<T> sGetAll(String key, Class<T> clz) {return template.execute(new RedisCallback<Set<T>>() {@Overridepublic Set<T> doInRedis(RedisConnection connection) throws DataAccessException {Set<byte[]> set = connection.sMembers(keyBytes(key));if (CollectionUtils.isEmpty(set)) {return Collections.emptySet();}return set.stream().map(s -> toObj(s, clz)).collect(Collectors.toSet());}});
}/*** 往set中添加內容** @param key* @param val* @param <T>* @return*/
public static <T> boolean sPut(String key, T val) {return template.execute(new RedisCallback<Long>() {@Overridepublic Long doInRedis(RedisConnection connection) throws DataAccessException {return connection.sAdd(keyBytes(key), valBytes(val));}}) > 0;
}/*** 移除set中的內容** @param key* @param val* @param <T>*/
public static <T> void sDel(String key, T val) {template.execute(new RedisCallback<Void>() {@Overridepublic Void doInRedis(RedisConnection connection) throws DataAccessException {connection.sRem(keyBytes(key), valBytes(val));return null;}});
}

3.4 白名單的應用場景

在文章發布的核心服務中,我們通過白名單機制來決定文章是否需要審核。代碼位于com.github.paicoding.forum.service.article.service.impl.ArticleWriteServiceImpl,以下是一些關鍵代碼片段:

  • 判斷是否需要審核
private boolean needToReview(ArticleDO article) {BaseUserInfoDTO user = ReqInfoContext.getReqInfo().getUser();if (user.getRole() != null && user.getRole().equalsIgnoreCase(UserRole.ADMIN.name())) {return false;}return article.getStatus() == PushStatusEnum.ONLINE.getCode() && !articleWhiteListService.authorInArticleWhiteList(article.getUserId());
}
  • 發布文章
private Long insertArticle(ArticleDO article, String content, Set<Long> tags) {if (needToReview(article)) {article.setStatus(PushStatusEnum.REVIEW.getCode());}// 保存文章、內容和標簽// ...
}
  • 更新文章
private Long updateArticle(ArticleDO article, String content, Set<Long> tags) {boolean review = article.getStatus().equals(PushStatusEnum.REVIEW.getCode());if (needToReview(article)) {article.setStatus(PushStatusEnum.REVIEW.getCode());}// 更新文章、內容和標簽// ...
}

3.5 管理員操作白名單

管理員可以通過com.github.paicoding.forum.web.admin.rest.AuthorWhiteListController來管理白名單用戶:

@RestController
@Api(value = "發布文章作者白名單管理控制器", tags = "作者白名單")
@Permission(role = UserRole.ADMIN)
@RequestMapping(path = {"api/admin/author/whitelist"})
public class AuthorWhiteListController {@Autowiredprivate AuthorWhiteListService articleWhiteListService;@GetMapping(path = "get")@ApiOperation(value = "白名單列表", notes = "返回作者白名單列表")public ResVo<List<BaseUserInfoDTO>> whiteList() {return ResVo.ok(articleWhiteListService.queryAllArticleWhiteListAuthors());}@GetMapping(path = "add")@ApiOperation(value = "添加白名單", notes = "將指定作者加入作者白名單列表")@ApiImplicitParam(name = "authorId", value = "傳入需要添加白名單的作者UserId", required = true, allowEmptyValue = false, example = "1")public ResVo<Boolean> addAuthor(@RequestParam("authorId") Long authorId) {articleWhiteListService.addAuthor2ArticleWhitList(authorId);return ResVo.ok(true);}@GetMapping(path = "remove")@ApiOperation(value = "刪除白名單", notes = "將作者從白名單列表")@ApiImplicitParam(name = "authorId", value = "傳入需要刪除白名單的作者UserId", required = true, allowEmptyValue = false, example = "1")public ResVo<Boolean> rmAuthor(@RequestParam("authorId") Long authorId) {articleWhiteListService.removeAuthorFromArticleWhiteList(authorId);return ResVo.ok(true);}
}

4 總結

本文介紹了技術派中白名單機制的實現,重點講解了如何利用Redis的Set數據結構來管理白名單用戶。通過白名單機制,我們能夠有效減少不必要的審核流程,提升用戶體驗。同時,本文也展示了如何在Spring項目中使用RedisTemplate來操作Redis的Set,希望對大家有所幫助。

Redis的五種基本數據結構(String、List、Set、ZSet、Hash)是每個開發者都應該掌握的知識點。然而,僅僅了解這些數據結構是不夠的,更重要的是能夠結合實際場景來選擇合適的數據結構,這樣才能真正發揮Redis的優勢。

5 思維導圖

6 參考鏈接

  1. 技術派Redis實現作者白名單
  2. 項目倉庫(GitHub)
  3. 項目倉庫(碼云)

7 附錄:Redis 五種數據結構的應用場景

Redis 提供了五種基本數據結構:字符串(String)、哈希(Hash)、列表(List)、集合(Set)和有序集合(Sorted Set)。每種數據結構都有其獨特的特性和適用場景。以下是每種數據結構的應用場景詳解:

7.1 字符串(String)

應用場景:

  • 緩存數據:將經常訪問的數據緩存在 Redis 中,以加快訪問速度。例如,緩存用戶信息、商品信息等。
  • 計數器:記錄某個事件發生的次數,例如網站的訪問次數、文章的點贊次數等。可以使用 INCRDECR 命令來實現。
  • 分布式鎖:使用字符串的 SETNX 命令來實現分布式鎖。SETNX 命令在鍵不存在時設置鍵值,可以用來實現互斥鎖。

示例代碼:

// 緩存數據
redisTemplate.opsForValue().set("user:1", "John Doe");
String user = redisTemplate.opsForValue().get("user:1");// 計數器
redisTemplate.opsForValue().increment("page:view:count");
Long viewCount = redisTemplate.opsForValue().get("page:view:count");// 分布式鎖
Boolean lockAcquired = redisTemplate.opsForValue().setIfAbsent("lock:key", "lockValue");
if (lockAcquired) {try {// 執行業務邏輯} finally {redisTemplate.delete("lock:key");}
}

7.2 哈希(Hash)

應用場景:

  • 存儲對象屬性:將對象的屬性存儲在哈希中,方便對屬性進行讀寫操作。例如,存儲用戶信息、商品信息等。
  • 緩存對象:將對象序列化后存儲在哈希中,以便快速獲取和更新對象。
  • 記錄用戶信息:存儲用戶的詳細信息,如用戶名、年齡、性別等。

示例代碼:

// 存儲對象屬性
redisTemplate.opsForHash().put("user:1", "name", "John Doe");
redisTemplate.opsForHash().put("user:1", "age", 30);
String name = (String) redisTemplate.opsForHash().get("user:1", "name");
Integer age = (Integer) redisTemplate.opsForHash().get("user:1", "age");// 緩存對象
User user = new User("John Doe", 30);
redisTemplate.opsForHash().putAll("user:1", new ObjectMapper().convertValue(user, Map.class));
User cachedUser = new ObjectMapper().convertValue(redisTemplate.opsForHash().entries("user:1"), User.class);

7.3 列表(List)

應用場景:

  • 消息隊列:用于實現消息隊列,將生產者產生的消息存儲在列表中,消費者從列表中獲取消息進行處理。
  • 最新動態:存儲用戶的最新動態或消息,如微博的用戶動態、新聞網站的最新消息等。
  • 實時排行榜:用于存儲用戶的分數或權重,并根據分數進行排序,實現實時排行榜功能。

示例代碼:

// 消息隊列
redisTemplate.opsForList().rightPush("message:queue", "message1");
String message = redisTemplate.opsForList().leftPop("message:queue");// 最新動態
redisTemplate.opsForList().rightPush("user:1:timeline", "動態1");
List<String> timeline = redisTemplate.opsForList().range("user:1:timeline", 0, -1);// 實時排行榜
redisTemplate.opsForList().rightPush("leaderboard", "user:1");
redisTemplate.opsForList().rightPush("leaderboard", "user:2");
List<String> leaderboard = redisTemplate.opsForList().range("leaderboard", 0, -1);

7.4 集合(Set)

應用場景:

  • 好友關系:存儲用戶的好友關系,利用集合的交集、并集、差集等操作來實現好友關系的管理。
  • 標簽管理:將對象關聯的標簽存儲在集合中,方便進行標簽的添加、刪除和檢索。
  • 唯一值集合:用于存儲唯一值,如去重、統計等場景。

示例代碼:

// 好友關系
redisTemplate.opsForSet().add("user:1:friends", "user:2", "user:3");
Set<String> friends = redisTemplate.opsForSet().members("user:1:friends");// 標簽管理
redisTemplate.opsForSet().add("article:1:tags", "技術", "Redis");
Set<String> tags = redisTemplate.opsForSet().members("article:1:tags");// 唯一值集合
redisTemplate.opsForSet().add("unique:values", "value1", "value2");
Set<String> uniqueValues = redisTemplate.opsForSet().members("unique:values");

7.5 有序集合(Sorted Set)

應用場景:

  • 排行榜:存儲用戶的分數,并根據分數進行排序,實現排行榜功能。例如,游戲中的積分排行榜、電商網站的銷量排行榜等。
  • 實時熱門數據:存儲數據的熱度值,并根據熱度值進行排序,用于實時熱門數據的展示。例如,新聞網站的熱門新聞、社交媒體的熱門話題等。
  • 計劃任務:存儲定時任務的執行時間,并根據時間戳進行排序,用于實現計劃任務的調度。

示例代碼:

// 排行榜
redisTemplate.opsForZSet().add("leaderboard", "user:1", 100);
redisTemplate.opsForZSet().add("leaderboard", "user:2", 200);
Set<String> topUsers = redisTemplate.opsForZSet().range("leaderboard", 0, 9);// 實時熱門數據
redisTemplate.opsForZSet().add("hot:news", "新聞1", 10);
redisTemplate.opsForZSet().add("hot:news", "新聞2", 20);
Set<String> hotNews = redisTemplate.opsForZSet().range("hot:news", 0, -1);// 計劃任務
redisTemplate.opsForZSet().add("schedule:tasks", "task1", System.currentTimeMillis() + 60000);
Set<String> tasks = redisTemplate.opsForZSet().rangeByScore("schedule:tasks", 0, System.currentTimeMillis());

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/902057.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/902057.shtml
英文地址,請注明出處:http://en.pswp.cn/news/902057.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

TRAE.AI 國際版本

國際版下載地址&#xff1a; https://www.trae.ai/https://www.trae.ai/ 國際版本優勢&#xff1a;提供更多高校的AI助手模型 Claude-3.5-Sonnet Claude-3.7-Sonnet Gemini-2.5-Pro GPT-4.1 GPT-40 DeepSeek-V3-0324DeepSeek-V3DeepSeek-Reasoner(R1)

關于支付寶網頁提示非官方網頁

關于支付寶網站提示 非官方網站 需要找官方添加白名單 下面可以直接用自己的郵箱去發送申請 支付寶提示“非支付寶官方網頁&#xff0c;請確認是否繼續訪問”通常是因為支付寶的安全機制檢測到您訪問的頁面不是支付寶官方頁面&#xff0c;這可能是由于域名或頁面內容不符合支…

【今日三題】打怪(模擬) / 字符串分類(字符串哈希) / 城市群數量(dfs)

??個人主頁&#xff1a;小羊 ??所屬專欄&#xff1a;每日兩三題 很榮幸您能閱讀我的文章&#xff0c;誠請評論指點&#xff0c;歡迎歡迎 ~ 目錄 打怪(模擬)字符串分類(字符串哈希)城市群數量(dfs) 打怪(模擬) 打怪 #include <iostream> using namespace std;int …

npm install 版本過高引發錯誤,請添加 --legacy-peer-deps

起因&#xff1a;由于使用"react": "^19.0.0", 第三方包要低版本react&#xff0c;錯解決方法&#xff01; npm install --save emoji-mart emoji-mart/data emoji-mart/react npm install --save emoji-mart emoji-mart/data emoji-mart/react npm err…

Python基礎總結(七)之條件語句

文章目錄 條件語句if一、Python中的真假二、條件語句格式2.1 if語句格式2.2 if-else語句2.3 if-elif-else語句 三、if語句嵌套 條件語句if 條件語句其實就是if語句&#xff0c;在講解if語句之前需要知道Python中對于真假的判斷。 一、Python中的真假 在Python中非0的都為真&…

基于Ubuntu2504部署OpenStack E版

OpenStack 初始化環境安裝數據庫、memcahe、rabbitmq等服務安裝keystone服務安裝glance服務安裝placement服務安裝nova服務安裝neutron服務安裝horizon服務 官網 OpenStack Epoxy 鞏固了作為 VMware 替代方案的地位&#xff0c;增強了安全性&#xff0c;并改進了硬件支持 第 3…

可發1區的超級創新思路(python 、MATLAB實現):基于多尺度注意力TCN-KAN與小波變換的時間序列預測模型

一、數學模型與原理 1.1 小波變換多尺度分解 輸入功率序列 x(t) 經小波變換分解為近似系數 Aj? 與細節系數 Dj?: 1.2 多尺度TCN特征提取 對每個尺度子序列 {A3?,D3?,D2?,D1?} 采用獨立TCN: 式中 ?d? 為擴張率 d=2l 的擴張卷積,Wd? 為可學習參數。 1.3 多尺度注…

YOLOv11改進有效漲點專欄:從理論到實戰的深度優化指南

## YOLOv11的進化之路 在目標檢測領域,YOLO系列算法始終保持著革命性的創新步伐。YOLOv11作為該系列的最新演進版本,在保持實時檢測優勢的同時,通過架構層面的深度優化實現了精度與速度的平衡。本文將從**七大核心模塊**出發,系統性地解析針對YOLOv11的有效改進方案,涵蓋從…

Cursor新版0.49.x發布

小子看到 Cursor 0.49.x 版本正式發布&#xff0c;截止今天已經有兩個小patch版本&#xff01;本次更新聚焦于 自動化Rules生成、改進的 Agent Terminal 以及 MCP 圖像支持&#xff0c;并帶來了一系列旨在提升編碼效率和協作能力的改進與修復。 以下是本次更新的詳細內容&…

《手環表帶保養全攻略:材質、清潔與化學品避坑指南》

系列文章目錄 文章目錄 系列文章目錄前言一、表帶材質特性與專屬養護方案二、清潔劑使用紅黑榜三、家庭清潔實驗&#xff1a;化學反應警示錄四、保養實踐方法論總結 前言 手環作為現代生活的智能伴侶&#xff0c;表帶材質選擇豐富多樣。從柔軟親膚的皮質到耐用耐磨的金屬&…

實現批量圖片文字識別(python+flask+EasyOCR)

話不多說,向上效果圖 1)先說框架版本 為什么要先說框架版本呢,因為我在各種版本中嘗試了兩天,總算確定了如下版本適合我,至于其他的版本,各位自己去嘗試 python 3.9.7 EasyOCR 1.7.2 flask 3.0.3 2)執行操作效果圖 2.1)多選文件 2.2)圖片預覽 2.3)提取選中文件 2.4)提取所有文…

國產GPU生態現狀評估:從寒武紀到壁仞的編程適配挑戰

近年來&#xff0c;國產GPU廠商在硬件性能上持續突破&#xff0c;但軟件生態的構建仍面臨嚴峻挑戰。本文以寒武紀、壁仞等代表性企業為例&#xff0c;對比分析其與CUDA生態的兼容性差異&#xff0c;并探討技術突圍路徑。 一、編程適配的核心挑戰 ?編程模型差異與開發成本? …

YOLOv8 Bug 及解決方案匯總 【2024.1.24更新】【環境安裝】【訓練 斷點續訓】OMPError / KeyError

YOLOv8 Bug 及解決方案匯總&#xff1a;深入解析與應對 引言 YOLOv8作為一款高性能的目標檢測算法&#xff0c;在實際應用中難免會遇到各種各樣的問題。本文將對YOLOv8常見的Bug進行匯總&#xff0c;并提供相應的解決方案&#xff0c;旨在幫助開發者更好地使用和優化YOLOv8。…

面試算法高頻08-動態規劃-02

動態規劃練習題 題目描述 給定兩個字符串 text1 和 text2&#xff0c;要求返回這兩個字符串的最長公共子序列。例如對于字符串 “ABAZDC” 和 “BACBAD”&#xff0c;需找出它們最長的公共子序列。子序列是指在不改變其余字符相對位置的情況下&#xff0c;從原始字符串中刪除…

【人工智能學習-01-01】20250419《數字圖像處理》復習材料的word合并PDF,添加頁碼

前情提要 20250419今天是上師大繼續教育人工智能專升本第一學期的第一次線下課。 三位老師把視頻課的內容提煉重點再面授。&#xff08;我先看了一遍視頻&#xff0c;但是算法和圖像都看不懂&#xff0c;后來就直接掛分刷滿時間&#xff0c;不看了&#xff09; 今天是面對面授…

AI寫代碼工具分享:Cursor 高效使用攻略與實戰秘籍

寫在前面 在軟件開發領域,效率和生產力是永恒的追求。集成開發環境(IDE)作為開發者的核心工具,其能力直接影響著開發速度和質量。近年來,人工智能(AI)的浪潮席卷了各個行業,編程領域也不例外。Cursor IDE 正是這股浪潮中的佼佼者,它以 AI-First 的理念,在廣受歡迎的…

守護進程編程

守護進程編程 守護進程的含義 定義 守護進程&#xff08;Daemon Process&#xff09;是在后臺運行的進程&#xff0c;它獨立于控制終端并且周期性地執行某種任務或等待處理某些發生的事件。守護進程是一種很有用的進程&#xff0c;它在系統后臺運行&#xff0c;為系統或其他…

在復雜性的迷宮里尋找路標 —— 讀《人月神話》有感

初讀《人月神話》時&#xff0c;正值參與的第一個大型項目陷入泥潭&#xff1a;需求像不斷膨脹的氣球&#xff0c;團隊規模從 10 人擴充到 30 人&#xff0c;進度卻像被灌了鉛的鐘表&#xff0c;指針越來越沉重。布魯克斯在書中寫下的 "向進度落后的項目增加人力&#xff…

SpringCloud Alibaba微服務工程搭建

前言 在講微服務工程的搭建之前&#xff0c;我們先分析下為什么要使用微服務呢&#xff1f; 1、單體應用的痛點 維護困難&#xff1a;代碼臃腫&#xff0c;牽一發而動全身。擴展性差&#xff1a;無法按需擴展特定功能&#xff0c;只能整體擴容。技術棧僵化&#xff1a;難以引…

flutter json解析增強

依賴:xxf_json 反序列化兼容特征一覽表 類型\是否兼容 int double num string bool int yes yes yes yes yes double yes yes yes yes yes num yes yes yes yes yes string yes yes yes yes yes bool yes yes yes yes yes 專業詞語 .g…