>  기사  >  데이터 베이스  >  Redis 캐시 공간을 최적화하는 방법

Redis 캐시 공간을 최적화하는 방법

PHPz
PHPz앞으로
2023-05-27 23:44:061156검색

Scene 설정

1. POJO를 캐시에 저장해야 합니다. 클래스는 다음과 같이 정의됩니다.

public class TestPOJO implements Serializable {
    private String testStatus;
    private String userPin;
    private String investor;
    private Date testQueryTime;
    private Date createTime;
    private String bizInfo;
    private Date otherTime;
    private BigDecimal userAmount;
    private BigDecimal userRate;
    private BigDecimal applyAmount;
    private String type;
    private String checkTime;
    private String preTestStatus;
    
    public Object[] toValueArray(){
        Object[] array = {testStatus, userPin, investor, testQueryTime,
                createTime, bizInfo, otherTime, userAmount,
                userRate, applyAmount, type, checkTime, preTestStatus};
        return array;
    }
    
    public CreditRecord fromValueArray(Object[] valueArray){         
        //具体的数据类型会丢失,需要做处理
    }
}

2. 다음 예제를 테스트 데이터로 사용하세요

TestPOJO pojo = new TestPOJO();
pojo.setApplyAmount(new BigDecimal("200.11"));
pojo.setBizInfo("XX");
pojo.setUserAmount(new BigDecimal("1000.00"));
pojo.setTestStatus("SUCCESS");
pojo.setCheckTime("2023-02-02");
pojo.setInvestor("ABCD");
pojo.setUserRate(new BigDecimal("0.002"));
pojo.setTestQueryTime(new Date());
pojo.setOtherTime(new Date());
pojo.setPreTestStatus("PROCESSING");
pojo.setUserPin("ABCDEFGHIJ");
pojo.setType("Y");

JSON을 사용하여 직렬화합니다. direct , print length=284

**, **이 방법은 가장 간단한 방법이며 가장 일반적으로 사용되는 방법입니다. 구체적인 데이터는 다음과 같습니다:

{"applyAmount":200.11,"bizInfo":"XX", "checkTime":"2023-02-02","투자자":"ABCD","otherTime":"2023-04-10 17:45:17.717","preCheckStatus":"PROCESSING","testQueryTime":" 2023- 04-10 17:45:17.717","testStatus":"SUCCESS","type":"Y","userAmount":1000.00,"userPin":"ABCDEFGHIJ","userRate":0.002}

우리는 위의 내용에 쓸모없는 데이터가 많이 포함되어 있으며 속성 이름을 저장할 필요가 없다는 것을 발견했습니다.

개선 1 - 속성 이름 제거

System.out.println(JSON.toJSONString(pojo).length());
객체 구조 대신 배열 구조를 선택하여 속성 이름을 제거하고, length=144

를 인쇄하면 데이터 크기가 50% 줄어듭니다. 다음과 같습니다:

["SUCCESS ","ABCDEFGHIJ","ABCD","2023-04-10 17:45:17.717",null,"XX","2023-04-10 17:45:17.717", 1000.00,0.002,200.11,"Y","2023-02-02","PROCESSING"]

시간 형식이 문자열로 직렬화되어 데이터가 발생하는 것을 발견했습니다. 확장되므로 더 나은 직렬화 도구를 사용해야 합니다.

개선 2 - 더 나은 직렬화 도구 사용

System.out.println(JSON.toJSONString(pojo.toValueArray()).length());
필드 압축 및 합리적인 데이터 형식을 달성하기 위해 더 나은 직렬화 도구를 선택하고, 인쇄 **길이=92, **공간이 이전 단계에 비해 40% 감소합니다.

이것은 Redis가 바이너리로 작동되어야 하는 바이너리 데이터 조각입니다. 바이너리를 문자열로 변환한 후 다음과 같이 인쇄합니다:

��SUCCESS�ABCDEFGHIJ�ABCD� �j�6���XX� �j� 6�� ��?`bM����@i � �Q�Y�2023-02-02�PROCESSING

이 아이디어에 따라 더 깊이 파고들어 데이터 유형을 수동으로 선택할 수 있다는 사실을 발견했습니다. 보다 극단적인 최적화 효과를 달성하고 더 작은 데이터 유형을 사용하도록 선택하면 추가 개선이 달성됩니다.

개선 3 - 최적화된 데이터 유형

위의 사용 사례에서 testStatus, preCheckStatus 및Investor의 세 필드는 실제로 열거된 문자열 유형입니다(예: byte 또는 int 등). 문자열을 교체하면 공간을 더욱 절약할 수 있습니다. 문자열 대신 Long 유형을 사용하여 checkTime을 나타낼 수 있으므로 직렬화 도구가 더 적은 바이트를 출력합니다.
//我们仍然选取JSON格式,但使用了第三方序列化工具
System.out.println(new ObjectMapper(new MessagePackFactory()).writeValueAsBytes(pojo.toValueArray()).length);

수동 조정 후 String 형식 대신 더 작은 데이터 형식을 사용하여 인쇄

length=69

개선 4-ZIP 압축 고려

위 사항 외에도 The ZIP 사용을 고려할 수 있습니다. 압축 방법은 더 작은 크기를 얻습니다. 콘텐츠가 크거나 반복적인 경우 ZIP 압축의 효과가 분명합니다. 저장된 콘텐츠가 TestPOJO의 배열인 경우 ZIP 압축이 적합할 수 있습니다.

30바이트보다 작은 파일의 경우 ZIP 압축을 사용하면 파일 크기가 늘어날 수 있지만 반드시 파일 크기가 줄어들지는 않습니다. 덜 반복적인 콘텐츠의 경우에는 큰 개선 효과를 얻을 수 없습니다. 그리고 CPU 오버헤드도 있습니다.

위의 최적화 후에는 ZIP 압축이 더 이상 필수 옵션이 아닙니다. ZIP 압축 효과를 확인하려면 실제 데이터를 기반으로 한 테스트가 필요합니다.

최종 구현됨

위의 개선 단계는 최적화 아이디어를 반영하지만 역직렬화 과정에서 유형 손실이 발생하여 처리하기가 더 번거롭기 때문에 역직렬화 문제도 고려해야 합니다.

캐시 객체가 미리 정의되면 각 필드를 수동으로 완전히 처리할 수 있으므로 실제 전투에서는 위의 목적을 달성하고 정교한 제어를 달성하며 최고의 압축 효과와 최소 성능 오버헤드를 달성하기 위해 수동 직렬화를 사용하는 것이 좋습니다.

다음 msgpack 구현 코드를 참조할 수 있습니다. 다음은 테스트 코드입니다. 더 나은 Packer 및 UnPacker 도구를 직접 패키징하세요.

public Object[] toValueArray(){
    Object[] array = {toInt(testStatus), userPin, toInt(investor), testQueryTime,
    createTime, bizInfo, otherTime, userAmount,
    userRate, applyAmount, type, toLong(checkTime), toInt(preTestStatus)};
    return array;
}
<dependency>    
    <groupId>org.msgpack</groupId>    
    <artifactId>msgpack-core</artifactId>    
    <version>0.9.3</version>
</dependency>

Scenario 확장

우리가 2억 명의 사용자에 대한 데이터를 저장한다고 가정합니다. user contain 40개의 필드가 있고, 필드 키의 길이는 6바이트이며, 필드를 별도로 관리합니다.

일반적으로 해시 구조를 생각하게 되는데, 해시 구조에는 추가 리소스를 차지하게 되는 키 정보가 저장됩니다. 위의 아이디어에 따르면 해시 구조 대신 목록을 사용할 수 있습니다.

Redis 공식 툴 테스트를 통해 리스트 구조를 사용하면 144G의 공간이 필요하고, 해시 구조를 사용하면 245G의 공간이 필요합니다** (속성이 50% 이상 비어 있으면 여전히 적용 가능한지 테스트해야 함) )**

위의 경우에는 간단한 코드 몇 줄만으로 공간을 70% 이상 줄일 수 있습니다. 의 적극 권장됩니다. :Redis 캐시 공간을 최적화하는 방법

• 객체 대신 배열을 사용하세요(많은 수의 필드가 비어 있으면 직렬화 도구를 사용하여 null을 압축해야 함)

• 더 나은 직렬화 도구를 사용하세요.

• ZIP 압축 사용

• 해시 구조 대신 목록 사용(비어 있는 필드가 많은 경우 테스트 및 비교 필요)

위 내용은 Redis 캐시 공간을 최적화하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 yisu.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제