当前位置:网站首页>Pratique - Distributed ID commander

Pratique - Distributed ID commander

2022-01-15 02:28:41 Danny... Idea

Après de nombreuses séries d'entretiens,Kobayashi est finalement entré dans le Groupe infrastructure d'une société Internet,Kobayashi travaille actuellement dans l'entreprise en utilisant des groupes d'architecture pour étudier la distributionidGénérateur,J'a i regardé sa mise en œuvre interne il y a un moment,Il a été constaté qu'il y avait encore des irrégularités dans la conception architecturale.Mais aussi parce qu'il s'applique au scénario d'affaires actuel,Donc il n'y a pas eu beaucoup d'optimisation,Voici quelques notes techniques pertinentes.

Contexte de la recherche et du développement

Dans les services distribués,Divers scénarios d'affaires complexes nécessitent une identification uniqueid,Par exemple, les commandes,Flux de paiement,Scénarios d'affaires tels que chat et communication.Surtout dans un scénario de sous - base et de sous - table,DistribuéidLes générateurs sont utilisés plus fréquemment.Donc distribuéidLes composants doivent être conçus pour supporter les caractéristiques suivantes:

1.Propriétés uniques au niveau mondial

C'est mieux compris,Il n'y a pas beaucoup d'explications ici.

2.Propriétés incrémentales des composants

Ça pourrait être chacun.idLes deux peuvent avoir des caractéristiques incrémentales ou des caractéristiques incrémentales à l'intérieur d'un intervalle de support.

3.Sécurité

Quelque chose d'important.idSi vous êtes accidentellement exposé à un environnement extranet,C'est très dangereux de ne pas avoir pris de précautions de sécurité.Par exemple, les commandesidSi seulement le format avec la date plus le nombre de commandes est généré,Par exemple,:2020111100001Représentation2020Année11Mois11Première commande de,Donc si la paire rivale obtient

2020111100999C'estid,Selon le temps de génération de la commande, on peut déduire l'ordre approximatif du nombre de commandes générées par l'entreprise à une date donnée.

4.Élevéqps

Distribuéid Les composants de construction sont principalement utilisés qpsÉlevé, Par conséquent, au début de la conception, il devrait être capable de supporter des qpsRequête, En même temps, les caractéristiques de latence du réseau doivent être réduites autant que possible .

5.Haute disponibilité

En raison de la distributionid Le constructeur est un service public qui doit supporter l'utilisation conjointe de plusieurs appelants de service , Une fois l'effondrement survenu, les conséquences sont inimaginables. , Risque d'effondrement important des secteurs d'activité , Il est donc particulièrement important de tenir compte de la disponibilité élevée .

Distribution courante dans l'industrie id Générer des comparaisons de scénarios

uuid

javaMise en œuvre dans le programmeuuidCode:

String result = UUID.randomUUID().toString();
System.out.println(result);

Le format généré est le suivant :

b0b2197d-bc8c-4fab-ad73-2b54e11b0869

uuid Le format est en fait - Les symboles sont divisés en cinq modules , Principalement divisé en 8-4-4-4-12 Une chaîne de caractères . Mais ce format de chaîne est très important pour les entreprises Internet MySQL La base de données n'est pas conviviale , Surtout quand on utilise le idEn tant qu'Index,uuidTrop long, Les données volumineuses peuvent causer b+ Augmentation de la fréquence de fission des noeuds foliaires dans les arbres , Et la comparaison d'index nécessite une comparaison de caractères , La perte de performance est également élevée , Le programme devrait être abandonné .
Kobayashi a fait des recherches sur Internet et a trouvé uuid Les principaux composants de :

  • Date et heure actuelles
  • Nombre aléatoire
  • MachineMACAdresse( Capable de garantir les caractéristiques uniques des machines dans le monde entier )

Algorithme flocon de neige

SnowFlake- Oui.TwitterUn algorithme utilisé par l'entreprise,L'objectif est de produire un système distribué unique à l'échelle mondiale avec une tendance croissanteID.

Photos

Expliquer un peu le sens de certains algorithmes de flocons de neige :

Le premier est généralement 0, Il n'y a pas de signification particulière pour l'utilisation ,Parce que1 Habituellement exprimé sous forme de complément .

Intermédiaire41 Bit est utilisé pour stocker le temps ,41 La longueur du BIT est suffisante pour 69 La durée des années .

10bit Utilisé pour identifier la machine elle - même id, Cela signifie que la machine elle - même n'est pas disponible idLa différence entre.

Enfin12Bitsbit Utilisé pour représenter un numéro de série dans une milliseconde ,12Bits(bit)Le plus grand nombre entier positif qui peut être représenté est4096-1=4095, Donc ça veut dire qu'il peut être généré simultanément en une milliseconde 4095- Oui.id.

La position de l'horodatage et la position du numéro de série ne peuvent pas encore être ajustées au hasard , Doit être une caractéristique pour assurer une augmentation progressive .

Les avantages

Caractéristiques qui garantissent une augmentation progressive ,id A un sens clair ,Facile à comprendre.

Points faibles

Mais dépend du temps système de la machine elle - même , Une fois que le temps système de la machine a changé , Il est possible qu'il y ait duplication dans un environnement de concurrence élevée id Risque généré .

Certains scénarios d'affaires s'attendent à ce que id Ajouter un préfixe spécial de nom de règle d'affaires

Par exemple, SMS id:

sms_108678123

Les billets de tombola id:

coupon_12908123

Doit être modifié sur la base de cet algorithme ,Appui à la mise en œuvreidInjection“Gènes”Cette caractéristique de.

mongodbClé primaire pouridIdées de conception

En faitmongodb Il y a aussi l'utilisation de la clé primaire id Injectez un peu “Gènes” Ce genre de réflexion sur les points essentiels :

mongodb Il n'y a pas de id.

Photos

_id Est identifié de façon unique key,valueEn général, nous définissonsobjectidObjet.

objectid Il contient un horodatage ,Hostip, Numéro de processus , Autonum

Photos

Après avoir étudié ces options , Puis Xiao Lin a commencé à développer une plate - forme dédiée à son entreprise idGénérateur.

Auto - étude des principales idées de conception

MySQLConfigurationidRègles de construction, Tirez dans le cache local pour former une section locale id, Ce qui réduit le risque de dbVisites.

Prise en charge de la configuration du cluster idGénérateur, Capable de supporter des qps Accès et meilleure extensibilité .

Photos

Le tableau de configuration est présenté ci - dessous :

Photos

Construction de montressql:

CREATE TABLE `t_id_builder_config` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `des` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'Description',
  `init_num` bigint(13) DEFAULT NULL COMMENT 'id Valeur de départ ',
  `current_threshold` bigint(16) DEFAULT NULL COMMENT 'En coursid Seuil de la phase ',
  `step` int(8) DEFAULT NULL COMMENT 'id Incrémental Interval ',
  `biz_code` varchar(60) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT ' Code du préfixe d'entreprise , S'il n'y en a pas, il n'est pas porté à son retour. ',
  `version` int(11) NOT NULL DEFAULT '0' COMMENT ' Numéro de version de la serrure optimiste ',
  `is_seq` smallint(2) NOT NULL DEFAULT '0' COMMENT 'idAugmentation continue,0 - Oui. 1 Non, pas du tout.',
  `create_time` datetime DEFAULT CURRENT_TIMESTAMP,
  `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

Quelques points de conception de base :

Lorsqu'il y a plusieurs demandes d'accès en même temps mysqlAccèsid Comment prévenir les problèmes de concurrence lors de la configuration ?

Ici, j'ai adoptéfor update Lire en ajoutant une serrure , En même temps, les informations de ligne sont mises à jour avec version Le champ d'information du numéro de version empêche les mises à jour en double .

Supposons que la mise à jour échoue ,Il y aura aussicas Pour réessayer , Interruption directe après retry plus d'un certain nombre de fois .

Pourquoi ne pas introduire redis Agir comme une serrure distribuée pour empêcher la modification simultanée des opérations de la base de données ?

Vous ne voulez pas rendre ce composant trop encombrant , Réduire la dépendance du système à l'égard des tiers

Supposons que local id Ce n'est pas fini , Il s'avère que le serveur est actuellement en panne ,Comment prévenir?

La configuration de la table doit être mise à jour chaque fois que le service démarre , Retirer le dernier lot id Rassemblez - vous localement , Pour ne pas apparaître et avant id La question du conflit .

Localid Comment juger dans la collection id Avez - vous déjà utilisé ?

S'il s'agit d'un incrément continu id, Cette étape peut être ignorée ,Parce que localementid Chaque fois qu'on l'obtient, c'est plus qu'avant. idPlus gros.. Mais si c'est une section tirée id Un retour aléatoire après votre arrivée locale nécessite l'ajout de bitset Comme filtre . Pour les id,Alors ça correspond àbitSet As1. Si l'intervalle retourné au hasard id Il a été occupé plusieurs fois , Après avoir dépassé une certaine fréquence, vous devez tirer à nouveau idAu niveau local.

Photos

Comment définir le Code de représentation de l'état de la machine non connectée ?

Les paramètres pertinents peuvent être configurés dans le script de démarrage :

-DidBuilder.index=1001

Configurer,Et à traversSystem.getProperty(“idBuilder.index”)Pour obtenir.

Idées de code de base :

Conception de l'interface:

package com.qiyu.tech.id.builder.service;
/** * @Author idea * @Date created in 11:16 Après - midi 2020/12/17 */
public interface IdBuilderService {
    
    /** *  Générer unique en fonction de la longueur de l'étape locale id( Augmentation de l'intervalle ) * * @return */
    Long unionId(int code);
    /** * PourunionId Algorithme optimisé pour ( Augmentation de la continuité ) * * @param code * @return */
    Long unionSeqId(int code);
    /** *  Générer une auto - augmentation avec un préfixe d'entreprise id( Augmentation de l'intervalle ) * * @param code * @return */
    String unionIdStr(int code);
    /** *  Générer une auto - augmentation avec un préfixe d'entreprise id( Augmentation de la continuité ) * * @param code * @return */
    String unionSeqIdStr(int code);
}

Réalisation concrète:

package com.qiyu.tech.id.builder.service.impl;
import com.qiyu.tech.id.builder.bean.IdBuilderPO;
import com.qiyu.tech.id.builder.bean.LocalSeqId;
import com.qiyu.tech.id.builder.dao.IdBuilderMapper;
import com.qiyu.tech.id.builder.service.IdBuilderService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.management.RuntimeErrorException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import static com.qiyu.tech.id.builder.constants.IdTypeConstants.*;
/** * @Author idea * @Date created in 11:18 Après - midi 2020/12/17 */
@Service
@Slf4j
public class IdBuilderServiceImpl implements IdBuilderService, InitializingBean {
    
    private static ConcurrentHashMap<Integer, BitSet> bitSetMap = new ConcurrentHashMap<>();
    private static Map<Integer, IdBuilderPO> idBuilderNotSeqMap;
    private static Map<Integer, IdBuilderPO> idBuilderSeqMap;
    private static Map<Integer, LocalSeqId> localSeqMap;
    private static Map<Integer, Boolean> newBuilderMap;
    private final static Object monitor = new Object();
    @Resource
    private IdBuilderMapper idBuilderMapper;
  
    private int idBuilderIndex;
    @Override
    public Long unionId(int code) {
    
        // Compte tenu des problèmes de mise à niveau des serrures , Utilisation dans des scénarios de concurrence élevée synchronizedPlus quecasMieux.
        synchronized (monitor) {
    
            IdBuilderPO idBuilderPO = idBuilderNotSeqMap.get(code);
            if (idBuilderPO == null) {
    
                return null;
            }
            boolean isNew = newBuilderMap.get(code);
            if (isNew) {
    
                // Prévention de l'apparition id Problème d'interruption du réseau du générateur 
                IdBuilderPO newIdBuilderPO = this.refreshIdBuilderConfig(idBuilderPO);
                if (newIdBuilderPO == null) {
    
                    log.error("[unionId] refreshIdBuilderConfigUne exception s'est produite");
                    return null;
                }
                idBuilderPO.setCurrentThreshold(newIdBuilderPO.getCurrentThreshold());
                newBuilderMap.put(code, false);
            }
            long initNum = idBuilderPO.getCurrentThreshold();
            int step = idBuilderPO.getStep();
            int randomIndex = RandomUtils.nextInt((int) initNum, (int) initNum + step);
            BitSet bitSet = bitSetMap.get(code);
            if (bitSet == null) {
    
                bitSet = new BitSet();
                bitSetMap.put(code, bitSet);
            }
            Long id;
            int countTime = 0;
            while (true) {
    
                boolean indexExist = bitSet.get(randomIndex);
                countTime++;
                if (!indexExist) {
    
                    bitSet.set(randomIndex);
                    id = Long.valueOf(randomIndex);
                    break;
                }
                // Si le nombre de retraits est supérieur à 0.75 Vous devez récupérer le nouveau idSection  Après le test   Boucle 10 millions de fois fonction aléatoire ,16gb En mémoire , Il a fallu environ 124msGauche et droite
                if (countTime >= step * 0.75) {
    
                    // L'expansion nécessite une modification de la configuration de la table 
                    IdBuilderPO newIdBuilderPO = this.updateIdBuilderConfig(idBuilderPO);
                    if (newIdBuilderPO == null) {
    
                        log.error("Retry plus de100 Le temps n'a pas été mis à jour depuis l'augmentation idConfiguration réussie");
                        return null;
                    }
                    initNum = newIdBuilderPO.getCurrentThreshold();
                    step = newIdBuilderPO.getStep();
                    idBuilderPO.setCurrentThreshold(initNum);
                    bitSet.clear();
                    log.info("[unionId] Expansion de la capacitéIdBuilder,new idBuilderPO is {}",idBuilderPO);
                }
                randomIndex = RandomUtils.nextInt((int) initNum, (int) initNum + step);
            }
            return id;
        }
    }
    @Override
    public Long unionSeqId(int code) {
    
        synchronized (monitor) {
    
            LocalSeqId localSeqId = localSeqMap.get(code);
            IdBuilderPO idBuilderPO = idBuilderSeqMap.get(code);
            if (idBuilderPO == null || localSeqId == null) {
    
                log.error("[unionSeqId] code Mauvais paramètre,code is {}", code);
                return null;
            }
            boolean isNew = newBuilderMap.get(code);
            long result = localSeqId.getCurrentId();
            localSeqId.setCurrentId(result + 1);
            if (isNew) {
    
                // Prévention de l'apparition id Problème d'interruption du réseau du générateur 
                IdBuilderPO updateIdBuilderPO = this.refreshIdBuilderConfig(idBuilderPO);
                if (updateIdBuilderPO == null) {
    
                    log.error("[unionSeqId] refreshIdBuilderConfigUne exception s'est produite");
                    return null;
                }
                newBuilderMap.put(code, false);
                localSeqId.setCurrentId(updateIdBuilderPO.getCurrentThreshold());
                localSeqId.setNextUpdateId(updateIdBuilderPO.getCurrentThreshold() + updateIdBuilderPO.getStep());
            }
            // Besoin de mettre à jour les étapes locales 
            if (localSeqId.getCurrentId() >= localSeqId.getNextUpdateId()) {
    
                IdBuilderPO newIdBuilderPO = this.updateIdBuilderConfig(idBuilderPO);
                if (newIdBuilderPO == null) {
    
                    log.error("[unionSeqId] updateIdBuilderConfigUne exception s'est produite");
                    return null;
                }
                idBuilderPO.setCurrentThreshold(newIdBuilderPO.getCurrentThreshold());
                localSeqId.setCurrentId(newIdBuilderPO.getCurrentThreshold());
                localSeqId.setNextUpdateId(newIdBuilderPO.getCurrentThreshold() + newIdBuilderPO.getStep());
                log.info("[unionSeqId] Expansion de la capacitéIdBuilder,new localSeqId is {}",localSeqId);
            }
            return result;
        }
    }
    /** * Rafraîchirid Configuration du générateur  * * @param idBuilderPO */
    private IdBuilderPO refreshIdBuilderConfig(IdBuilderPO idBuilderPO) {
    
        IdBuilderPO updateResult = this.updateIdBuilderConfig(idBuilderPO);
        if (updateResult == null) {
    
            log.error(" Exception à la mise à jour de la configuration de la base de données ,idBuilderPO is {}", idBuilderPO);
            throw new RuntimeErrorException(new Error(" Exception à la mise à jour de la configuration de la base de données ,idBuilderPO is " + idBuilderPO.toString()));
        }
        return updateResult;
    }
    /** *  Considérez l'environnement distribué   Cas où plusieurs demandes mettent à jour simultanément la même ligne de données  * * @param idBuilderPO * @return */
    private IdBuilderPO updateIdBuilderConfig(IdBuilderPO idBuilderPO) {
    
        int updateResult = -1;
        // Supposons qu'une exception de réseau se produise pendant le retry ,Alors, utilisezcas Il faut tenir compte de la sortie.   Mise à jour dans des cas extrêmes 100Une fois
        for (int i = 0; i < 100; i++) {
    
            IdBuilderPO newIdBuilderPO = idBuilderMapper.selectOneForUpdate(idBuilderPO.getId());
            updateResult = idBuilderMapper.updateCurrentThreshold(newIdBuilderPO.getCurrentThreshold() + newIdBuilderPO.getStep(), newIdBuilderPO.getId(), newIdBuilderPO.getVersion());
            if (updateResult > 0) {
    
                return newIdBuilderPO;
            }
        }
        return null;
    }
    @Override
    public String unionIdStr(int code) {
    
        long id = this.unionId(code);
        IdBuilderPO idBuilderPO = idBuilderNotSeqMap.get(code);
        return idBuilderPO.getBizCode() + idBuilderIndex + id;
    }
    @Override
    public String unionSeqIdStr(int code) {
    
        long id = this.unionSeqId(code);
        IdBuilderPO idBuilderPO = idBuilderSeqMap.get(code);
        return idBuilderPO.getBizCode() + idBuilderIndex + id;
    }
    @Override
    public void afterPropertiesSet() {
    
        List<IdBuilderPO> idBuilderPOS = idBuilderMapper.selectAll();
        idBuilderNotSeqMap = new ConcurrentHashMap<>(idBuilderPOS.size());
        newBuilderMap = new ConcurrentHashMap<>(idBuilderPOS.size());
        idBuilderSeqMap = new ConcurrentHashMap<>(idBuilderPOS.size());
        localSeqMap = new ConcurrentHashMap<>(0);
        // Chaque fois que je redémarre , Il est nécessaire d'utiliser l'intervalle précédent idTout abandonner, Utiliser un nouvel intervalle de pas 
        for (IdBuilderPO idBuilderPO : idBuilderPOS) {
    
            if (idBuilderPO.getIsSeq() == NEED_SEQ) {
    
                idBuilderSeqMap.put(idBuilderPO.getId(), idBuilderPO);
                LocalSeqId localSeqId = new LocalSeqId();
                localSeqId.setNextUpdateId(idBuilderPO.getCurrentThreshold() + idBuilderPO.getStep());
                localSeqId.setCurrentId(idBuilderPO.getCurrentThreshold());
                localSeqMap.put(idBuilderPO.getId(), localSeqId);
            } else {
    
                idBuilderNotSeqMap.put(idBuilderPO.getId(), idBuilderPO);
            }
            newBuilderMap.put(idBuilderPO.getId(), true);
        }
        this.idBuilderIndex= Integer.parseInt(System.getProperty("idBuilder.index"));
    }
}

Conception au niveau de la base de données :

package com.qiyu.tech.id.builder.dao;
import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.qiyu.tech.id.builder.bean.IdBuilderPO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import java.util.List;
/** * @Author idea * @Date created in 10:17 Matin 2020/12/17 */
@Mapper
public interface IdBuilderMapper extends BaseMapper<IdBuilderPO> {
    
    @Select("select * from t_id_builder_config")
    List<IdBuilderPO> selectAll();
    @Select("select * from t_id_builder_config where id=#{id} limit 1 for update")
    IdBuilderPO selectOneForUpdate(@Param("id") int id);
    @Update("UPDATE t_id_builder_config set current_threshold=#{currentThreshold},version=version+1 where id=#{id} and version=#{version}")
    Integer updateCurrentThreshold(@Param("currentThreshold") long currentThreshold,@Param("id") int id,@Param("version") int version);
}

Je n'ai posté qu'une partie du Code de base ,httpEtrpc La partie accès est en fait similaire , Peut être personnalisé pour répondre à vos besoins .

En bas, je posterai sur controllerCode partiel:

package com.qiyu.tech.id.builder.controller;
import com.qiyu.tech.id.builder.service.IdBuilderService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/** * @Author idea * @Date created in 4:27 Après - midi 2020/12/17 */
@RestController
@RequestMapping(value = "id-builder")
public class IdBuilderController {
    
    @Resource
    private IdBuilderService idBuilderService;
  
    @GetMapping("increase-id")
    public Long increaseId(int code){
    
        long result = idBuilderService.unionId(code);
        System.out.println(result);
        return result;
    }
    @GetMapping("increase-seq-id")
    public Long increaseSeqId(int code){
    
        long result = idBuilderService.unionSeqId(code);
        System.out.println(result);
        return result;
    }
    @GetMapping("increase-seq-id-str")
    public String unionSeqIdStr(int code){
    
        String result = idBuilderService.unionSeqIdStr(code);
        System.out.println(result);
        return result;
    }
    @GetMapping("increase-id-str")
    public String unionIdStr(int code){
    
        String result = idBuilderService.unionIdStr(code);
        System.out.println(result);
        return result;
    }
}

application.ymlProfil

mybatis-plus:
  configuration:
    map-underscore-to-camel-case: true
server:
  port: 8082
  tomcat:
    max-threads: 500
    max-connections: 5000

Attention à la nécessité de combiner la configuration réelle de la machine nginx Le nombre de Threads simultanés et tomcat Paramètres d'accès simultanés pour .

Classe de démarrage:

ps:À l'intérieur.db La configuration d'accès est celle qui prend son propre Encapsulation dbOutils, En fait, l'essence et SpringBootConfiguration directejdbcC'est pareil,Peut être ignoré

package com.qiyu.tech.id.builder;
import com.qiyu.datasource.annotation.AppDataSource;
import com.qiyu.datasource.enums.DatasourceConfigEnum;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/** * @Author idea * @Date created in 11:16 Après - midi 2020/12/17 */
@SpringBootApplication(scanBasePackages = "com.qiyu.*")
@AppDataSource(datasourceType = {
    DatasourceConfigEnum.PROD_DB},defaultType = DatasourceConfigEnum.PROD_DB)
public class IdBuilderApplication {
    
    public static void main(String[] args) {
    
        SpringApplication.run(IdBuilderApplication.class,args);
        System.out.println("========== IdBuilderApplication started! =========");
    }
}

Phase d'essai:

En emballant le service et en le déployant sur la machine , Exécuter plusieurs services en même temps ,AdoptionnginxConfigurer l'équilibrage de charge, Demande à une machine qui ne fonctionne pas .

Voici quelques - uns des paramètres de configuration pertinents que j'ai effectués moi - même :

Photos

Après le début de l'essai de pression , La console d'arrière - plan Imprime les paramètres de série pertinents :

Photos

Quand nous avons besoin de machines d'amplification , La nouvelle machine ne dictera pas la machine originale idImpact, Peut supporter une meilleure expansion .

Chaque fois qu'on tire sur un local id Les segments doivent être conçus de manière à ce qu'ils soient meilleurs plusieurs fois ?

Ici, nous allons commencer par le local id Le paragraphe est abrégé en segment.

Sur la base d'expériences passées , D'habitude, c'est l'espoir id Le distributeur peut réduire la quantité de MySQLNombre de visite pour, En même temps, le contrôle doit être effectué en fonction de la capacité d'exploitation et d'entretien réelle du Ministère .

Supposons que nous MySQLC'est adopté1Seigneur.2 De la façon dont , Quand un noeud esclave est suspendu , Il faut environ 1Les minutes,Alors la nôtresegment Doit au moins être conçu pour les heures de pointe QPS * 60 * 1 * 4 , D'autres facteurs doivent être pris en considération lors de l'examen périodique , .Par exemple, certains problèmes de nervosité du réseau causés par la commutation de nouveaux noeuds, etc , Cela garantit que même si MySQLIl y a eu un problème,Localsegment Peut également être temporairement soutenu pendant un certain temps .

La conception doit être améliorée

Les lacunes de la conception du système sont les suivantes: ,Au niveau localid Une requête de base de données est nécessaire lorsque vous êtes sur le point de manquer , Donc cette clé ralentit le temps de réponse du système , Il est donc possible de tirer ici avec une configuration de mise à jour asynchrone id L'idée de . C'est - à - dire, être local id Il ne reste plus que 15% Quand il sera disponible , Vous pouvez ouvrir un fil asynchrone pour tirer idLa liste est là..

Photos

版权声明
本文为[Danny... Idea]所创,转载请带上原文链接,感谢
https://chowdera.com/2022/01/202201080559031486.html

随机推荐