Maison  >  Article  >  base de données  >  Comment optimiser l'espace de cache Redis

Comment optimiser l'espace de cache Redis

PHPz
PHPzavant
2023-05-27 23:44:061197parcourir

Paramètre de la scène

1. Nous devons stocker POJO dans le cache. La classe est définie comme suit

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){         
        //具体的数据类型会丢失,需要做处理
    }
}

Utilisez JSON pour sérialiser. directement, imprimez

length=284

**, **Cette méthode est la méthode la plus simple et la méthode la plus couramment utilisée. Les données spécifiques sont les suivantes : {"applyAmount":200.11,"bizInfo":"XX", "checkTime": "2023-02-02", "investisseur": "ABCD", "otherTime": "2023-04-10 17:45:17.717", "preCheckStatus": "TRAITEMENT", "testQueryTime": 2023- 04-10 17:45:17.717","testStatus":"SUCCESS","type":"Y","userAmount":1000.00,"userPin":"ABCDEFGHIJ","userRate":0.002}

Nous avons constaté que ce qui précède contient beaucoup de données inutiles et qu'il n'est pas nécessaire de stocker les noms d'attributs.

Amélioration 1-Supprimez le nom de l'attribut

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");

En sélectionnant la structure du tableau au lieu de la structure de l'objet, le nom de l'attribut est supprimé et l'impression

length=144

réduit la taille des données de 50 %. comme suit : ["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"]

Nous avons constaté qu'il n'est pas nécessaire de stocker null Le format de l'heure est sérialisé dans une chaîne. Les résultats de sérialisation déraisonnables conduisent à des données. expansion, nous devrions donc choisir de meilleurs outils de sérialisation.

Amélioration 2-Utilisez de meilleurs outils de sérialisation

System.out.println(JSON.toJSONString(pojo).length());

Choisissez de meilleurs outils de sérialisation pour obtenir une compression de champ et un format de données raisonnable, imprimez **longueur=92, **l'espace est réduit de 40 % par rapport à l'étape précédente.

Il s'agit d'une donnée binaire. Redis doit être exploité en binaire. Après avoir converti le binaire en chaîne, imprimez-le comme suit : ��SUCCESS�ABCDEFGHIJ�ABCD� �j�6���XX� �j� 6�� ��?`bM����@i � �Q�Y�2023-02-02�PROCESSING

En suivant cette idée et en creusant plus profondément, nous avons découvert que nous pouvions sélectionner manuellement le type de données, Pour obtenir des effets d'optimisation plus extrêmes et choisir d'utiliser des types de données plus petits, d'autres améliorations seront réalisées.

Amélioration 3 - Types de données optimisés

Dans le cas d'utilisation ci-dessus, les trois champs testStatus, preCheckStatus et investisseurs sont en fait des types de chaînes énumérés si des types de données plus simples peuvent être utilisés (tels que byte ou int, etc.) Le remplacement de la chaîne peut encore économiser de l'espace. Vous pouvez utiliser le type Long au lieu d'une chaîne pour représenter checkTime, afin que l'outil de sérialisation génère moins d'octets.

System.out.println(JSON.toJSONString(pojo.toValueArray()).length());

Après un ajustement manuel, un type de données plus petit a été utilisé à la place du type String, impressionlength=69

Amélioration 4-Considérez la compression ZIP

En plus des points ci-dessus, vous pouvez également envisager d'utiliser le ZIP La méthode de compression obtient une taille plus petite. Lorsque le contenu est volumineux ou répétitif, l'effet de la compression ZIP est évident. Si le contenu stocké est un tableau de TestPOJO, la compression ZIP peut être adaptée.

Pour les fichiers de moins de 30 octets, la compression ZIP peut augmenter la taille du fichier mais ne peut pas nécessairement la réduire. Dans le cas de contenus moins répétitifs, aucune amélioration significative ne peut être obtenue. Et il y a une surcharge du processeur. Après l'optimisation ci-dessus, la compression ZIP n'est plus une option obligatoire. Des tests basés sur des données réelles sont nécessaires pour déterminer l'effet de la compression ZIP.

Enfin implémenté

Les étapes d'amélioration ci-dessus reflètent les idées d'optimisation, mais le processus de désérialisation entraînera la perte de types, ce qui est plus lourd à gérer, nous devons donc également considérer la question de la désérialisation.

Lorsque l'objet de cache est prédéfini, nous pouvons traiter complètement chaque champ manuellement, donc en combat réel, il est recommandé d'utiliser la sérialisation manuelle pour atteindre l'objectif ci-dessus, obtenir un contrôle raffiné et obtenir le meilleur effet de compression et une surcharge de performances minimale. Vous pouvez vous référer au code d'implémentation msgpack suivant. Voici le code de test. Veuillez emballer vous-même de meilleurs outils tels que Packer et UnPacker :

//我们仍然选取JSON格式,但使用了第三方序列化工具
System.out.println(new ObjectMapper(new MessagePackFactory()).writeValueAsBytes(pojo.toValueArray()).length);
public Object[] toValueArray(){
    Object[] array = {toInt(testStatus), userPin, toInt(investor), testQueryTime,
    createTime, bizInfo, otherTime, userAmount,
    userRate, applyAmount, type, toLong(checkTime), toInt(preTestStatus)};
    return array;
}

Extension de scénario

Supposons que nous stockons les données de 200 millions d'utilisateurs, et chaque utilisateur contient Il y a 40 champs, la longueur de la clé du champ est de 6 octets et les champs sont gérés séparément.

Normalement, nous penserons à la structure de hachage, et la structure de hachage stocke les informations clés, qui occuperont des ressources supplémentaires. La clé de champ est une donnée inutile. Selon les idées ci-dessus, vous pouvez utiliser une liste au lieu d'une structure de hachage. Grâce au test de l'outil officiel Redis, l'utilisation de la structure de liste nécessite 144 Go d'espace, tandis que l'utilisation de la structure de hachage nécessite 245 Go d'espace** (Lorsque plus de 50 % des attributs sont vides, un test est nécessaire pour voir si c'est le cas. toujours applicable)**

Dans le cas ci-dessus, nous avons pris plusieurs mesures très simples. Quelques lignes de code simples peuvent réduire l'espace de plus de 70 % dans des scénarios avec de grandes quantités de données et des exigences de performances élevées. , il est fortement recommandé de. :

• Utilisez des tableaux au lieu d'objets (si un grand nombre de champs sont vides, vous devez coopérer avec des outils de sérialisation pour compresser les valeurs nulles)

• Utilisez la compression ZIP

• Utilisez une liste au lieu d'une structure de hachage (si un grand nombre de champs sont vides, un test et une comparaison sont nécessaires)

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer