最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringData Redis中Hash結(jié)構(gòu)操作方法

 更新時間:2026年03月30日 09:51:05   作者:難釋懷  
本文將帶你全面掌握Spring Data Redis 中 Hash 結(jié)構(gòu)的操作技巧與最佳實踐,本文結(jié)合實例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧

一、前言:為什么用 Hash 存儲對象?

在 Redis 中存儲用戶、商品、配置等結(jié)構(gòu)化數(shù)據(jù)時,你是否面臨以下選擇?

  • ? 是將整個對象序列化為 JSON 存入一個 String?
  • ? 還是拆分成多個獨立 Key(如 user:1001:nameuser:1001:age)?
  • ? 或者……使用 Hash 結(jié)構(gòu)

答案是:優(yōu)先考慮 Hash!

Redis 的 Hash 類型專為“字段-值”映射設(shè)計,特別適合存儲對象。
配合 Spring Data Redis 的 opsForHash(),你可以:
? 節(jié)省內(nèi)存(相比多個 String Key)
? 支持單字段更新/查詢(避免全量讀寫)
? 原子性操作(線程安全)
? 天然支持對象模型

本文將帶你全面掌握 Spring Data Redis 中 Hash 結(jié)構(gòu)的操作技巧與最佳實踐!

二、Hash vs 其他存儲方式對比

方式內(nèi)存占用更新粒度可讀性適用場景
Hash? 低(共享 Key)? 字段級? 高用戶資料、商品信息、配置項
JSON String? 整體? 高不常更新的完整對象
多 String Key? 高(每個 Key 有元信息開銷)? 字段級? 高極簡場景,不推薦

?? 官方建議:當(dāng)對象字段數(shù) ≤ 500 且單字段值 < 64KB 時,Hash 是最優(yōu)解

三、核心 API:opsForHash() 詳解

在 Spring Data Redis 中,無論使用 RedisTemplate 還是 StringRedisTemplate,都通過 opsForHash() 操作 Hash。

?? 強烈建議:使用 StringRedisTemplate + Hash,Key 和 Field 都為字符串,杜絕亂碼!

1. 注入模板(零配置)

@Autowired
private StringRedisTemplate stringRedisTemplate;

2. 常用操作速查表

操作方法示例
存單個字段put(K key, HK hashKey, HV value)put("user:1001", "name", "張三")
存多個字段putAll(K key, Map<HK, HV> map)putAll("user:1001", userMap)
取單個字段get(K key, HK hashKey)get("user:1001", "email")
取所有字段entries(K key)entries("user:1001") → Map<String, String>
取所有 fieldkeys(K key)keys("user:1001") → Set<String>
取所有 valuevalues(K key)values("user:1001") → List<String>
刪除字段delete(K key, Object... hashKeys)delete("user:1001", "avatar")
判斷字段存在hasKey(K key, Object hashKey)hasKey("user:1001", "phone")
獲取字段數(shù)量size(K key)size("user:1001")

四、實戰(zhàn)案例:用戶資料管理

場景:存儲和更新用戶基本信息

1. 定義實體類(僅用于業(yè)務(wù)層)

public class User {
    private String id;
    private String name;
    private String email;
    private Integer age;
    // getter/setter...
}

2. Hash 操作工具類

@Component
public class UserRedisService {
    @Autowired
    private StringRedisTemplate redisTemplate;
    private static final String USER_HASH_PREFIX = "user:";
    // 保存用戶(全量覆蓋)
    public void saveUser(User user) {
        String key = USER_HASH_PREFIX + user.getId();
        Map<String, String> userMap = new HashMap<>();
        userMap.put("name", user.getName());
        userMap.put("email", user.getEmail());
        userMap.put("age", String.valueOf(user.getAge()));
        redisTemplate.opsForHash().putAll(key, userMap);
        // 設(shè)置過期時間(可選)
        redisTemplate.expire(key, 2, TimeUnit.HOURS);
    }
    // 更新單個字段(如修改郵箱)
    public void updateEmail(String userId, String newEmail) {
        redisTemplate.opsForHash().put(USER_HASH_PREFIX + userId, "email", newEmail);
    }
    // 獲取用戶完整信息
    public User getUser(String userId) {
        String key = USER_HASH_PREFIX + userId;
        Map<Object, Object> entries = redisTemplate.opsForHash().entries(key);
        if (entries.isEmpty()) {
            return null; // 緩存未命中
        }
        User user = new User();
        user.setId(userId);
        user.setName((String) entries.get("name"));
        user.setEmail((String) entries.get("email"));
        user.setAge(Integer.parseInt((String) entries.get("age")));
        return user;
    }
    // 獲取單個字段(如只查用戶名)
    public String getUserName(String userId) {
        return (String) redisTemplate.opsForHash().get(USER_HASH_PREFIX + userId, "name");
    }
    // 刪除用戶
    public void deleteUser(String userId) {
        redisTemplate.delete(USER_HASH_PREFIX + userId);
    }
}

優(yōu)勢體現(xiàn)

  • 更新郵箱時,無需讀取整個用戶對象
  • 查詢用戶名時,網(wǎng)絡(luò)傳輸量最小
  • 內(nèi)存占用比多個 String Key 少 30%+(實測)

五、高級技巧:批量操作與管道

1. 批量獲取多個用戶的某個字段

// 獲取多個用戶的姓名
List<String> userIds = Arrays.asList("1001", "1002", "1003");
List<String> names = userIds.stream()
    .map(id -> (String) redisTemplate.opsForHash().get("user:" + id, "name"))
    .collect(Collectors.toList());

?? 注意:這是多次網(wǎng)絡(luò)請求,高并發(fā)下可能成為瓶頸。

2. 使用 Pipeline 優(yōu)化批量操作(需 RedisTemplate)

@Autowired
private RedisTemplate<String, String> redisTemplate; // 注意類型
public List<String> getNamesInPipeline(List<String> userIds) {
    return redisTemplate.executePipelined((RedisCallback<String>) connection -> {
        for (String id : userIds) {
            connection.hGet(("user:" + id).getBytes(), "name".getBytes());
        }
        return null;
    });
}

?? 性能提升:1000 次操作從 200ms 降至 10ms!

六、避坑指南:常見問題與解決方案

? 坑 1:Field 或 Value 出現(xiàn)亂碼

原因:使用了默認(rèn)的 RedisTemplate(JDK 序列化)
解決始終使用 StringRedisTemplate 操作 Hash

? 坑 2:數(shù)字字段反序列化失敗

// 錯誤:直接強轉(zhuǎn)
Integer age = (Integer) redisTemplate.opsForHash().get("user:1001", "age"); // ClassCastException!

正確做法:存為 String,取時手動轉(zhuǎn)換

String ageStr = (String) redisTemplate.opsForHash().get("user:1001", "age");
Integer age = Integer.valueOf(ageStr);

? 坑 3:Hash 過大導(dǎo)致阻塞

風(fēng)險:單個 Hash 超過 10,000 個字段,HGETALL 會阻塞 Redis
建議

  • 單 Hash 字段數(shù) ≤ 1000
  • 超大對象拆分為多個 Hash(如 user:1001:baseuser:1001:profile

七、Hash 適用場景總結(jié)

場景說明
用戶資料name, email, avatar, settings...
商品信息title, price, stock, category...
配置中心系統(tǒng)開關(guān)、參數(shù)配置
會話狀態(tài)用戶登錄態(tài)的部分屬性
列表/集合數(shù)據(jù)如訂單列表 → 應(yīng)用 List 或 ZSet
全文內(nèi)容如文章正文 → 用 String

八、結(jié)語

到此這篇關(guān)于SpringData Redis中Hash結(jié)構(gòu)操作方法的文章就介紹到這了,更多相關(guān)SpringData Redis Hash結(jié)構(gòu)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Spring Security 安全框架應(yīng)用原理解析

    Spring Security 安全框架應(yīng)用原理解析

    這篇文章主要介紹了Spring Security 安全框架應(yīng)用,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-07-07
  • 淺談servlet3異步原理與實踐

    淺談servlet3異步原理與實踐

    本篇文章主要介紹了servlet3異步原理與實踐,詳細(xì)的介紹了servlet和異步的流程使用,具有一定的參考價值,有興趣的可以了解一下
    2017-10-10
  • Java如何使用itext向PDF插入數(shù)據(jù)和圖片

    Java如何使用itext向PDF插入數(shù)據(jù)和圖片

    最近項目中使用到Java實現(xiàn)寫入PDF文件,這篇文章主要給大家介紹了關(guān)于Java如何使用itext向PDF插入數(shù)據(jù)和圖片的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-01-01
  • 深入解讀Java代碼組織中的package包結(jié)構(gòu)

    深入解讀Java代碼組織中的package包結(jié)構(gòu)

    這篇文章主要介紹了Java代碼組織中的package包結(jié)構(gòu),是Java入門學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下
    2016-03-03
  • Java?多線程并發(fā)?ReentrantReadWriteLock詳情

    Java?多線程并發(fā)?ReentrantReadWriteLock詳情

    這篇文章主要介紹了Java多線程并發(fā)ReentrantReadWriteLock詳情,ReentrantReadWriteLock可重入讀寫鎖。實際使用場景中,我們需要處理的操作本質(zhì)上是讀與寫,更多相關(guān)資料,感興趣的小伙伴可以參考一下下面文章內(nèi)容
    2022-06-06
  • Javaweb會話跟蹤技術(shù)Cookie和Session的具體使用

    Javaweb會話跟蹤技術(shù)Cookie和Session的具體使用

    本文主要介紹了Javaweb會話跟蹤技術(shù)Cookie&Session的具體使用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-07-07
  • Spring框架基于注解開發(fā)CRUD詳解

    Spring框架基于注解開發(fā)CRUD詳解

    這篇文章主要為大家詳細(xì)介紹了Spring框架基于注解開發(fā)CRUD,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-08-08
  • Java前端Layer.open.btn驗證無效解決方法

    Java前端Layer.open.btn驗證無效解決方法

    在本篇文章里我們給大家整理了一篇關(guān)于Java前端Layer.open.btn驗證無效解決方法以及實例代碼,需要的朋友們可以參考學(xué)習(xí)下。
    2019-09-09
  • java 中復(fù)合機制的實例詳解

    java 中復(fù)合機制的實例詳解

    這篇文章主要介紹了java 中復(fù)合機制的實例詳解的相關(guān)資料,希望通過本文大家能了解繼承和復(fù)合的區(qū)別并應(yīng)用復(fù)合這種機制,需要的朋友可以參考下
    2017-09-09
  • Java中的Object類詳細(xì)解讀

    Java中的Object類詳細(xì)解讀

    這篇文章主要介紹了Java中的Object類詳細(xì)解讀,java.lang.Object是類層次結(jié)構(gòu)的根類,即所有其它類的父類,每個類都使用 Object 作為超類,需要的朋友可以參考下
    2023-11-11

最新評論

永年县| 新营市| 鄂托克前旗| 乐山市| 蕲春县| 顺平县| 南召县| 全州县| 彰武县| 洮南市| 高安市| 惠安县| 泗水县| 绵竹市| 甘泉县| 沽源县| 西乌珠穆沁旗| 余姚市| 丰台区| 普兰店市| 嘉定区| 台北市| 图木舒克市| 浏阳市| 长海县| 茶陵县| 新营市| 上饶县| 黔东| 依安县| 乌拉特后旗| 张北县| 嘉兴市| 双流县| 宣汉县| 苏尼特左旗| 桓仁| 德化县| 满城县| 清新县| 白玉县|