如何將Redis記憶體使用量降低一半? - DEV

banq發表於2020-06-13

在本文中,我將嘗試解釋如何將資料佔用的儲存空間減少50%以上。
我們的2.5GB Redis ElastiCache幾乎快滿了,如果以某種方式達到其極限,我們的系統將開始出現故障。Redis可能會成為瓶頸。

基礎設定:
使用最新版本的Spring Boot,有兩個主要依賴項- Spring Boot Web和Spring Data Reactive Redis,Spring Data Reactive Redis將用於連線和使用Redis的內部應用程式。從本質上講,Redis依賴項預設使用Lettuce Redis客戶端,並且受最新版本的Spring Boot支援。

完整的程式碼可以在我的Github上找到redis-util

降低記憶體使用量使用MessagePack,您需要一種“轉換”機制。如果翻譯是專家,並且將您的英語翻譯成儘可能少的單詞怎麼辦?MessagePack工作原理是一樣的!將需要在pom.xml檔案中新增兩個以上的依賴項。

<dependency>
        <groupId>org.msgpack</groupId>
        <artifactId>msgpack-core</artifactId>
        <version>0.8.20</version>
    </dependency>
    <dependency>
        <groupId>org.msgpack</groupId>
        <artifactId>jackson-dataformat-msgpack</artifactId>
        <version>0.8.20</version>
    </dependency>


我們建立了一個名為控制器MsgPackController:

class MsgPackRedisSerializer<T> implements RedisSerializer<T> {
    public static final Charset DEFAULT_CHARSET;
    private final JavaType javaType;
    private ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory())
            .registerModules(new Jdk8Module(), new JavaTimeModule())
            .configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, true)
            .configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false)
            .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
            .setSerializationInclusion(JsonInclude.Include.NON_NULL);

    public MsgPackRedisSerializer(Class<T> type) {
        this.javaType = JavaTypeHandler.getJavaType(type);
    }

    public T deserialize(@Nullable byte[] bytes) throws SerializationException {
        if (bytes == null || bytes.length == 0) {
            return null;
        } else {
            try {
                return this.objectMapper.readValue(bytes, 0, bytes.length, this.javaType);
            } catch (Exception ex) {
                throw new SerializationException("Could not read MsgPack JSON: " + ex.getMessage(), ex);
            }
        }
    }

    public byte[] serialize(@Nullable Object value) throws SerializationException {
        if (value == null) {
            return new byte[0];
        } else {
            try {
                return this.objectMapper.writeValueAsBytes(value);
            } catch (Exception ex) {
                throw new SerializationException("Could not write MsgPack JSON: " + ex.getMessage(), ex);
            }
        }
    }

    static {
        DEFAULT_CHARSET = StandardCharsets.UTF_8;
    }

}


例項MessagePackFactory被傳遞到中ObjectMapper。這將充當Redis和我們的Spring Boot應用程式之間資料的二進位制格式和字串格式之間的橋樑。
測試: 比較dataset.bytes當前記憶體與先前記錄的記憶體。15976位元組對32840位元組,已經減少了近50%!

但是,等等,我們可以進一步減少它。壓縮!Snappy
之後的第一個問題是:壓縮和解壓縮需要時間。這對生產有害嗎?Snappy也有答案。

它不旨在最大程度地壓縮,也不旨在與任何其他壓縮庫相容。相反,它的目標是非常高的速度和合理的壓縮。

使用Snappy就像在中新增依賴項一樣簡單pom.xml,並且幾行程式碼更改。只需Snappy.compress在序列化和Snappy.decompress反序列化時新增即可。

<dependency>
        <groupId>org.xerial.snappy</groupId>
        <artifactId>snappy-java</artifactId>
        <version>1.1.7.3</version>
    </dependency>


清理和重組資料,並利用上述技術,我們將記憶體使用量從2GB降低到了不到500MB。

相關文章