압축 Redis 의 문자열 대상 작업

배경
Redis 캐 시 문자열 이 너무 클 때 문제 가 있 습 니 다.10KB 를 넘 지 않 는 것 이 가장 좋 고,최대 1MB 를 넘 으 면 안 된다.
캐 시 설정 이 몇 개 있 습 니 다.수천 개의 flink 작업 이 호출 되 었 습 니 다.각 작업 은 5 분 에 한 번 명중 하고 크기 는 5KB 에서 6MB 가 다 르 기 때문에 압축 이 필요 합 니 다.
첫 번 째,gzip 사용

/**
 *   gzip     
 */
public static String compress(String str) {
    if (str == null || str.length() == 0) {
        return str;
    }
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    GZIPOutputStream gzip = null;
    try {
        gzip = new GZIPOutputStream(out);
        gzip.write(str.getBytes());
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (gzip != null) {
            try {
                gzip.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    return new sun.misc.BASE64Encoder().encode(out.toByteArray());
}
 
/**
 *   gzip   
 */
public static String uncompress(String compressedStr) {
    if (compressedStr == null || compressedStr.length() == 0) {
        return compressedStr;
    }
 
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    ByteArrayInputStream in = null;
    GZIPInputStream ginzip = null;
    byte[] compressed = null;
    String decompressed = null;
    try {
        compressed = new sun.misc.BASE64Decoder().decodeBuffer(compressedStr);
        in = new ByteArrayInputStream(compressed);
        ginzip = new GZIPInputStream(in);
        byte[] buffer = new byte[1024];
        int offset = -1;
        while ((offset = ginzip.read(buffer)) != -1) {
            out.write(buffer, 0, offset);
        }
        decompressed = out.toString();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (ginzip != null) {
            try {
                ginzip.close();
            } catch (IOException e) {
            }
        }
        if (in != null) {
            try {
                in.close();
            } catch (IOException e) {
            }
        }
        if (out != null) {
            try {
                out.close();
            } catch (IOException e) {
            }
        }
    }
    return decompressed;
}
두 번 째,Zstd 사용

        <!-- https://mvnrepository.com/artifact/com.github.luben/zstd-jni -->
        <dependency>
            <groupId>com.github.luben</groupId>
            <artifactId>zstd-jni</artifactId>
            <version>1.4.5-6</version>
        </dependency>

public class ConfigCacheUtil {
    private static ZstdDictCompress compressDict;
    private static ZstdDictDecompress decompressDict;
    private static final Integer LEVEL = 5;
    public static void train() throws IOException {
        //        
        String dictContent = FileUtils.readFileToString(new File("/Users/yangguang/vscode/text/cache.json"),
            StandardCharsets.UTF_8);
        byte[] dictBytes = dictContent.getBytes(StandardCharsets.UTF_8);
        compressDict = new ZstdDictCompress(dictBytes, LEVEL);
        decompressDict = new ZstdDictDecompress(dictBytes);
    }
    public static void main(String[] args) throws IOException {
        String read = FileUtils.readFileToString(new File("/Users/yangguang/vscode/text/cache.json"));
        ConfigCacheUtil.testGzip(read);
        System.out.println("");
        ConfigCacheUtil.test(read.getBytes());
        System.out.println("");
        ConfigCacheUtil.testByTrain(read.getBytes());
    }
    public static void testGzip(String str) {
        logger.info("    : {}", str.length());
        //     
        long compressBeginTime = System.currentTimeMillis();
        String compressed = ConfigCacheUtil.compress(str);
        long compressEndTime = System.currentTimeMillis();
        logger.info("    : {}", compressEndTime - compressBeginTime);
        logger.info("    : {}", compressed.length());
        //     
        long decompressBeginTime = System.currentTimeMillis();
        //   3                   
        String decompressed = ConfigCacheUtil.uncompress(compressed);
        long decompressEndTime = System.currentTimeMillis();
        logger.info("    : {}", decompressEndTime - decompressBeginTime);
        logger.info("    : {}", decompressed.length());
    }
    
    public static void test(byte[] bytes) {
        logger.info("    : {}", bytes.length);
        //     
        long compressBeginTime = System.currentTimeMillis();
        byte[] compressed = Zstd.compress(bytes);
        long compressEndTime = System.currentTimeMillis();
        logger.info("    : {}", compressEndTime - compressBeginTime);
        logger.info("    : {}", compressed.length);
        //     
        long decompressBeginTime = System.currentTimeMillis();
        //   3                   
        byte[] decompressed = Zstd.decompress(compressed, 20 * 1024 * 1024 * 8);
        long decompressEndTime = System.currentTimeMillis();
        logger.info("    : {}", decompressEndTime - decompressBeginTime);
        logger.info("    : {}", decompressed.length);
    }
    public static void testByTrain(byte[] bytes) throws IOException {
        ConfigCacheUtil.train();
        logger.info("    : {}", bytes.length);
        //     
        long compressBeginTime = System.currentTimeMillis();
        byte[] compressed = Zstd.compress(bytes, compressDict);
        long compressEndTime = System.currentTimeMillis();
        logger.info("    : {}", compressEndTime - compressBeginTime);
        logger.info("    : {}", compressed.length);
        //     
        long decompressBeginTime = System.currentTimeMillis();
        //   3                   
        byte[] decompressed = Zstd.decompress(compressed, decompressDict, 20 * 1024 * 1024 * 8);
        long decompressEndTime = System.currentTimeMillis();
        logger.info("    : {}", decompressEndTime - decompressBeginTime);
        logger.info("    : {}", decompressed.length);
        compressDict.toString();
    }
}
출력
5KB
2020-09-08 22:42:48 INFO ConfigCacheUtil:157-초기 데이터:5541
2020-09-08 22:42:48 INFO ConfigCacheUtil:163-압축 소요 시간:2
2020-09-08 22:42:48 INFO ConfigCacheUtil:164-데이터 크기:1236
2020-09-08 22:42:48 INFO ConfigCacheUtil:171-스트레스 해소 소요 시간:2
2020-09-08 22:42:48 INFO ConfigCacheUtil:172-데이터 크기:5541
2020-09-08 22:42:48 INFO ConfigCacheUtil:176-초기 데이터:5541
2020-09-08 22:42:48 INFO ConfigCacheUtil:182-압축 소요 시간:523
2020-09-08 22:42:48 INFO ConfigCacheUtil:183-데이터 크기:972
2020-09-08 22:42:48 INFO ConfigCacheUtil:190-스트레스 해소 소요 시간:85
2020-09-08 22:42:48 INFO ConfigCacheUtil:191-데이터 크기:5541
2020-09-08 22:42:48 INFO ConfigCacheUtil:196-초기 데이터:5541
2020-09-08 22:42:48 INFO ConfigCacheUtil:202-압축 소요 시간:1
2020-09-08 22:42:48 INFO ConfigCacheUtil:203-데이터 크기:919
2020-09-08 22:42:48 INFO ConfigCacheUtil:210-스트레스 해소 소요 시간:22
2020-09-08 22:42:48 INFO ConfigCacheUtil:111-데이터 크기:5541
6MB
2020-09-08 22:44:06 INFO ConfigCacheUtil:158-초기 데이터:5719269
2020-09-08 22:44:06 INFO ConfigCacheUtil:164-압축 소요 시간:129
2020-09-08 22:44:06 INFO ConfigCacheUtil:165-데이터 크기:330090
2020-09-08 22:44:06 INFO ConfigCacheUtil:172-스트레스 해소 소요 시간:69
2020-09-08 22:44:06 INFO ConfigCacheUtil:173-데이터 크기:5719269
2020-09-08 22:44:06 INFO ConfigCacheUtil:177-초기 데이터:5874139
2020-09-08 22:44:06 INFO ConfigCacheUtil:183-압축 소요 시간:265
2020-09-08 22:44:06 INFO ConfigCacheUtil:184-데이터 크기:201722
2020-09-08 22:44:06 INFO ConfigCacheUtil:191-스트레스 해소 소요 시간:81
2020-09-08 22:44:06 INFO ConfigCacheUtil:192-데이터 크기:5874139
2020-09-08 22:44:06 INFO ConfigCacheUtil:197-초기 데이터:5874139
2020-09-08 22:44:06 INFO ConfigCacheUtil:203-압축 소요 시간:42
2020-09-08 22:44:06 INFO ConfigCacheUtil:204-데이터 크기:115423
2020-09-08 22:44:07 INFO ConfigCacheUtil:111-스트레스 해소 소요 시간:49
2020-09-08 22:44:07 INFO ConfigCacheUtil:212-데이터 크기:5874139
Redis 압축 목록
압축 목록(ziplist)은 목록 키 와 해시 키 의 바 텀 구현 중 하나 입 니 다.하나의 목록 키 가 소량의 목록 항목 만 포함 하고 모든 목록 항목 이 작은 정수 값 이거 나 길이 가 짧 은 문자열 일 때 Redis 는 압축 목록 을 사용 하여 목록 키 의 바 텀 으로 이 루어 집 니 다.
압축 목록 이 실 현 된 목록 키 를 살 펴 보 겠 습 니 다.

목록 키 에는 1,3,5,10086 과 같은 작은 정수 와'hello','World'와 같은 짧 은 문자열 이 포함 되 어 있 습 니 다.
압축 목록 에서 이 루어 진 해시 키 를 다시 보 세 요:

압축 목록 은 Redis 가 메모리 절약 을 위해 개발 한 것 으로 일련의 특수 인 코딩 된 연속 메모리 블록 으로 구 성 된 순서 형 데이터 구조 이다.
하나의 압축 목록 은 여러 노드 를 포함 할 수 있 으 며,각 노드 는 하나의 바이트 배열 이나 하나의 정수 치 를 저장 할 수 있다.

압축 목록 의 예 시 를 보십시오.

다섯 개의 노드 를 포함 하 는 압축 목록 을 보십시오.

노드 의 encoding 속성 은 노드 의 content 속성 이 저장 한 데이터 의 유형 과 길 이 를 기록 합 니 다.
노드 의 content 속성 은 노드 의 값 을 저장 하 는 것 을 책임 집 니 다.노드 값 은 바이트 배열 이나 정수 일 수 있 습 니 다.값 의 유형 과 길 이 는 노드 의 encoding 속성 에 의 해 결 정 됩 니 다.

연쇄 업데이트:
각 노드 의 previousentry_length 속성 은 모두 이전 노드 의 길 이 를 기록 합 니 다.그러면 현재 한 노드 의 길 이 는 254 이하 에서 254 이상으로 변 할 때 본 노드 의 저장 전 노드 의 길이 의 previousentry_length 는 1 바이트 에서 5 바이트 로 바 뀌 어야 합 니 다.
그럼 뒤에 노드 의 previousentry_length 속성 도 업데이트 가능 합 니 다.하지만 연쇄 업데이트 확률 은 크 지 않다.
요약:

이상 은 개인 적 인 경험 이 므 로 여러분 에 게 참고 가 되 기 를 바 랍 니 다.여러분 들 도 저 희 를 많이 응원 해 주시 기 바 랍 니 다.

좋은 웹페이지 즐겨찾기