如何分段存储Redis键值对

说明:本文介绍针对一个value过长的键值对,如何分段存储;

场景

当我们需要存入一个String类型的键值对到Redis中,如下:

(缓存接口)

public interface CacheService {

    /**
     * 添加一个字符串键值对
     * @param key 键
     * @param value 值
     */
    void setString(String key, String value);
}

(Redis实现)

import com.hezy.service.CacheService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

@Service
public class RedisServiceImpl implements CacheService {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;


    @Override
    public void setString(String key, String value) {
        redisTemplate.opsForValue().set(key, value);
    }
}

(使用)

import com.hezy.service.impl.RedisServiceImpl;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class RedisServiceImplTest {

    @Autowired
    private RedisServiceImpl redisService;

    @Test
    public void test1() {
        String key = "content";
        String value = "这是一段分非常大非常大的字符串…………………………非常大";
        redisService.setString(key, value);
    }
}

(查看Redis)

在这里插入图片描述

有时候,我们存入的字符串可能过长,过大,有可能来自于一个大对象的序列化。这时候存入的key-value,会造成value过大,会触发一些预警。

可以采用我下面这种分段存储的方法。

优化

思路:将字符串分段,每一段生成一个key,然后将这些分段key再用Redis的List类型存储;获取时就先获取这些分段key,再循环去get对应的字符串,拼接起来就是完整的字符串。

如下:分段存,增加一个参数,设置每段字符串的长度

(缓存接口)

    /**
     * 分段存储
     * @param key 键
     * @param value 值
     * @param chunkSize 每个分段大小
     */
    void setStrSub(String key, String value, int chunkSize);

(Redis实现)

    @Override
    public void setStrSub(String key, String value, int chunkSize) {
        // 将value,按照length,分成多个部分
        int totalChunks = (int) Math.ceil((double) value.length() / chunkSize);
        // 定义一个分段数据key集合
        List<String> subKeys = new ArrayList<>(totalChunks);
        // 将字符串分成多段
        for (int i = 0; i < totalChunks; i++) {
            // 计算分段起止位置
            int startIndex = i * chunkSize;
            int endIndex = Math.min(startIndex + chunkSize, value.length());
            // 获取对应分段数据
            String chunkValue = value.substring(startIndex, endIndex);
            // 拼接分段key
            String subKey = key + "_" + i;
            // 存储分段数据
            setString(subKey, chunkValue);
            // 将分段key添加到集合
            subKeys.add(subKey);
        }
        // 分段key添加到集合
        setList(key, subKeys);
    }

(添加一个集合到Redis)

    @Override
    public void setList(String key, List value) {
        redisTemplate.opsForList().rightPushAll(key, value);
    }

启动,测试

    @Test
    public void test2() {
        String key = "content";
        String value = "这是一段分非常大非常大的字符串…………………………非常大";
        redisService.setStrSub(key, value, 5);
    }

查看Redis

在这里插入图片描述

在这里插入图片描述

然后,要取数据,也很简单;

(缓存接口)

    /**
     * 获取字符串(分段)
     * @param key
     * @return
     */
    String getStrSub(String key);

(Redis实现)

    @Override
    public String getStrSub(String key) {
        // 先把分段key获取出来
        List<String> list = getList(key);
        // 字符串拼接,用StringBuilder,线程安全
        StringBuilder stringBuilder = new StringBuilder();
        for (String subKey : list) {
            String subValue = getString(subKey);
            // 这里要跳过null,不然最后输出会把null转为字符串
            if (subValue == null) {
                continue;
            }
            stringBuilder.append(subValue);
        }
        // 如果没有数据,返回null
        return "".contentEquals(stringBuilder) ? null : stringBuilder.toString();
    }

(Redis获取一个List)

    @Override
    public List getList(String key) {
        return redisTemplate.opsForList().range(key, 0, -1);
    }

(使用)

    @Test
    public void test3() {
        String content = redisService.getStrSub("content");
        System.out.println(content);
    }

(打印)

在这里插入图片描述

总结

本文介绍了Redis分段存储一个大键值对(String)的一种方式,看下来,实现并不复杂。使用上也可以很方便,可以考虑把分段的存取和普通的存取都兼容起来,这样对于使用者,只需要加一个参数(分段大小)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

何中应

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值