Maison > base de données > Redis > le corps du texte

Explication détaillée de l'architecture de réplication maître-esclave dans Redis

青灯夜游
Libérer: 2021-03-30 10:43:23
avant
2080 Les gens l'ont consulté

Cet article vous présente l'architecture de réplication maître-esclave dans Redis. Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer. J'espère qu'il sera utile à tout le monde.

Explication détaillée de l'architecture de réplication maître-esclave dans Redis

La haute disponibilité a deux significations : l'une est d'éviter autant que possible la perte de données et l'autre est de fournir des services autant que possible. AOF et RDB garantissent que la persistance des données n'est pas perdue autant que possible, tandis que la réplication maître-esclave consiste à ajouter des copies et à enregistrer une donnée sur plusieurs instances. Même si une instance tombe en panne, d’autres instances peuvent toujours fournir des services.

Cet article vous donne principalement une compréhension globale de l'architecture de réplication maître-esclave, l'une des solutions technologiques à haute disponibilité Redis.

Cet article est hardcore. Il est recommandé de le récupérer et de le savourer lentement, je pense que les lecteurs auront une amélioration qualitative. S'il y a des erreurs, merci de les corriger, merci.

[Recommandations associées : Tutoriel vidéo Redis]

Points de connaissances de base

Explication détaillée de larchitecture de réplication maître-esclave dans Redis

Message d'ouverture

Problème = Opportunité. Lorsque vous rencontrez des problèmes, vous êtes réellement heureux intérieurement. Des problèmes plus importants signifient de plus grandes opportunités.

Tout a un prix, chaque gain doit être une perte, et chaque perte doit être un gain, nous n'avons donc pas à nous soucier de beaucoup de choses, nous devons juste réfléchir clairement à ce que nous voulons faire. et ce que nous sommes prêts à payer pour cela. Payez le prix, puis allez-y et faites-le !

1. Présentation de la réplication maître-esclave

65 Brother : Avec RDB et AOF, vous n'avez plus peur de la perte de données due aux temps d'arrêt. , mais l'instance Redis Comment obtenir une haute disponibilité lorsque la machine est en panne ?

Puisqu'une machine est en panne et ne peut pas fournir de service, qu'en est-il des autres machines ? Est-ce que cela peut être résolu ? Redis fournit un mode maître-esclave, qui copie une copie redondante des données sur d'autres serveurs Redis via la réplication maître-esclave.

Le premier est appelé nœud maître (maître), et le second est appelé nœud esclave (esclave) ; la réplication des données est unidirectionnelle et ne peut se faire que du nœud maître vers le nœud esclave.

Par défaut, chaque serveur Redis est un nœud maître ; et un nœud maître peut avoir plusieurs nœuds esclaves (ou aucun nœud esclave), mais un nœud esclave ne peut avoir qu'un seul nœud maître.

65 Brother : Comment assurer la cohérence des données entre maître et esclave ?

Afin d'assurer la cohérence des données du réplica, l'architecture maître-esclave adopte une méthode de séparation lecture-écriture.

  • Opération de lecture : peut être exécutée à la fois par les bibliothèques maître et esclave ;
  • Opération d'écriture : la bibliothèque maître l'exécute en premier, puis synchronise l'opération d'écriture avec la bibliothèque esclave ;

Explication détaillée de larchitecture de réplication maître-esclave dans Redis

65 Frère : Pourquoi faut-il séparer la lecture et l'écriture ?

Nous pouvons supposer que les bibliothèques maître et esclave peuvent exécuter des instructions d'écriture. Si les mêmes données sont modifiées plusieurs fois et que chaque modification est envoyée à une instance maître-esclave différente, les données de copie de l'instance seront copiées. être incohérent.

Si pour assurer la cohérence des données, Redis a besoin de verrouiller et de coordonner la modification de plusieurs instances, Redis ne le fera naturellement pas !

65 Brother : La réplication maître-esclave a-t-elle d'autres fonctions ?
  • Récupération après panne : lorsque le nœud maître tombe en panne, d'autres nœuds peuvent toujours fournir des services

  • Équilibrage de charge : le nœud maître fournit des services d'écriture ; , et le nœud esclave Fournir des services de lecture et partager la pression ;

  • Pierre angulaire de la haute disponibilité : C'est la base de la mise en œuvre de Sentinel et du cluster, et la pierre angulaire de la haute disponibilité.

2. Configurer la réplication maître-esclave

L'activation de la réplication maître-esclave est entièrement initiée depuis le nœud esclave et ne nous oblige pas à tout faire sur le nœud maître.

65 Brother : Comment construire une architecture de réplication maître-esclave ?

La relation entre la base de données maître et la base de données esclave peut être formée via la commande replicaof (slaveof était utilisée avant Redis 5.0).

Activer la réplication maître-esclave sur le nœud esclave Il existe trois manières :

  • Fichier de configuration

    Ajouter replicaof <masterip> <masterport></masterport></masterip> au fichier de configuration de. le serveur esclave

  • Commande de démarrage

    commande de démarrage redis-server suivie de l'ajout de --replicaof <masterip> <masterport></masterport></masterip>

  • Commande client

    Après avoir démarré plusieurs instances Redis, exécutez la commande directement via le client : replicaof <masterip> <masterport></masterport></masterip>, l'instance Redis devient alors un nœud esclave.

Par exemple, en supposant qu'il existe l'instance 1 (172.16.88.1), l'instance 2 (172.16.88.2) et l'instance 3 (172.16.88.3), exécutez ce qui suit sur l'instance 2 et l'instance 3 respectivement, l'instance 2 et l'instance 3 deviennent les bibliothèques esclaves de l'instance 1, et l'instance 1 devient le maître.

replicaof 172.16.88.1 6379
Copier après la connexion

3. Principe de réplication maître-esclave

Une fois que le mode bibliothèque maître-esclave adopte la séparation lecture-écriture, toutes les opérations d'écriture de données ne seront effectuées que sur la bibliothèque maître, et il n'est pas nécessaire de coordonner trois exemples.

Une fois que la base de données maître dispose des dernières données, elle sera synchronisée avec la base de données esclave, afin que les données des bases de données maître et esclave soient cohérentes.

65 Brother : Comment s'effectue la synchronisation de la base de données maître-esclave ? Les données de la base de données maître sont-elles transmises immédiatement à la base de données esclave ou sont-elles synchronisées par lots ? Comment synchroniser en fonctionnement normal ? Si le réseau entre les bibliothèques maître et esclave est déconnecté, les données resteront-elles cohérentes après la reconnexion ?

65 Frère, vous avez tellement de questions. La synchronisation est divisée en trois situations :

  • La première copie complète de la base de données maître-esclave ; >

  • Synchronisation pendant le fonctionnement normal du maître et de l'esclave ;
  • Synchronisation de déconnexion et de reconnexion du réseau entre les bibliothèques maître et esclave.
La première copie complète de la base de données maître-esclave

65 Frère : J'ai tellement le vertige, synchronisons la base de données maître-esclave pour la première fois, parlons-en.

Le premier processus de copie de la bibliothèque maître-esclave peut être grossièrement divisé en trois étapes : l'étape d'établissement de la connexion (c'est-à-dire l'étape de préparation), l'étape de synchronisation des données de la bibliothèque maître vers le bibliothèque esclave, et envoi de nouvelles commandes d'écriture lors de la synchronisation à Depuis l'étape bibliothèque

allez directement à l'image, et vous aurez une perspective globale dans son ensemble, qui sera présentée en détail plus tard.

Explication détaillée de larchitecture de réplication maître-esclave dans RedisÉtablir une connexion

La fonction principale de cette étape est d'établir une connexion entre le maître et les nœuds esclaves. Préparez-vous à une synchronisation complète des données. La bibliothèque esclave établira une connexion avec la bibliothèque maître. La bibliothèque esclave exécutera replicaof et enverra la commande pync et indiquera à la bibliothèque maître que la synchronisation est sur le point d'avoir lieu. Une fois que la bibliothèque maître aura confirmé la réponse, la synchronisation entre les deux sera effectuée. les bibliothèques maître et esclave vont commencer

.

65 Brother : Comment la base de données esclave connaît-elle les informations de la base de données maître et établit-elle une connexion ?

Après avoir configuré l'IP et le port du nœud maître dans l'élément de configuration réplica du fichier de configuration du nœud esclave, le nœud esclave saura à quel nœud maître il souhaite se connecter.
Le nœud esclave gère deux champs, masterhost et masterport, qui sont utilisés pour stocker les informations IP et de port du nœud maître.

La bibliothèque esclave exécute

et envoie la commande

, indiquant que la synchronisation des données doit être effectuée. Après avoir reçu la commande, la bibliothèque maître démarre la réplication selon les paramètres. La commande contient deux paramètres :

runIDreplicaof de la bibliothèque principale et psynccopy progress offset.

runID
     : Chaque instance Redis générera automatiquement un identifiant d'identification unique lors de son démarrage. Pour la première réplication maître-esclave, le runID de la base de données principale n'est pas encore connu, et le paramètre est défini sur "?"
  • offset
  •  : La première copie est définie sur -1, indiquant la première copie, enregistrant le décalage de progression de la copie.
  • Une fois que la bibliothèque principale a reçu la commande psync, elle utilisera la commande de réponse
  • FULLRESYNC avec deux paramètres : l'ID d'exécution de la bibliothèque principale et le décalage actuel de la progression de la copie de la bibliothèque principale, et la renverra à la bibliothèque des esclaves
. Après réception de la réponse de la bibliothèque, ces deux paramètres seront enregistrés.

La réponse FULLRESYNC indique la copie complète

adoptée pour la première réplication, c'est-à-dire que la base de données maître copiera toutes les données actuelles vers la base de données esclave.

La base de données maître synchronise les données avec la base de données esclave

La deuxième phase

le maître exécute la commande

pour générer un fichier RDB et envoie le fichier vers la base de données esclave Dans le même temps, la

bibliothèque principale

ouvre un tampon de réplication pour chaque esclave afin d'enregistrer toutes les commandes d'écriture reçues à partir du moment où le fichier RDB est généré. bgsaveAprès avoir reçu le fichier RDB de la bibliothèque, enregistrez-le sur le disque, effacez les données de la base de données actuelle, puis chargez les données du fichier RDB dans la mémoire.

Envoyer une nouvelle commande d'écriture à la bibliothèque esclave

La troisième phase

Une fois que le nœud esclave a chargé le RDB, le nœud maître répliquera le données dans le tampon Envoyées au nœud esclave, l'esclave reçoit et exécute, et le nœud esclave se synchronise avec le même état que le nœud maître.

65 Brother : Lorsque la base de données maître synchronise les données avec la base de données esclave, la demande peut-elle être acceptée normalement ?

La base de données principale ne sera pas bloquée. En tant qu'homme qui n'est que rapide et incassable, comment Redis peut-il être bloqué à chaque instant.
L'opération d'écriture après la génération du fichier RDB n'est pas enregistrée dans le fichier RDB pour le moment. Afin de garantir la cohérence des données de la base de données maître-esclave, la base de données maître utilisera un tampon de réplication dans la mémoire pour. enregistrer la génération du fichier RDB toutes les opérations d'écriture ultérieures.

65 Brother : Pourquoi devons-nous effacer la base de données actuelle après avoir reçu le fichier RDB de la bibliothèque ?

Parce que la bibliothèque esclave peut enregistrer d'autres données avant de commencer la synchronisation avec la bibliothèque maître via la commande
, pour éviter l'influence entre les données maître et esclave.

Qu'est-ce que le tampon de réplication exactement ? replcaof

Un tampon créé côté maître. Les données stockées sont toutes les opérations d'écriture de données maître dans les trois périodes suivantes.
1) L'opération d'écriture pendant l'exécution du maître bgsave pour générer le RDB

2) L'opération d'écriture pendant l'envoi du maître à la transmission réseau esclave

3) le chargement du rdb par l'esclave ; Opérations d'écriture de fichiers au cours desquelles les données sont restaurées en mémoire.

Redis 和客户端通信也好,和从库通信也好,Redis 都分配一个内存 buffer 进行数据交互,客户端就是一个 client,从库也是一个 client,我们每个 client 连上 Redis 后,Redis 都会分配一个专有 client buffer,所有数据交互都是通过这个 buffer 进行的。

Master 先把数据写到这个 buffer 中,然后再通过网络发送出去,这样就完成了数据交互。

不管是主从在增量同步还是全量同步时,master 会为其分配一个 buffer ,只不过这个 buffer 专门用来传播写命令到从库,保证主从数据一致,我们通常把它叫做 replication buffer。

replication buffer 太小会引发的问题

replication buffer 由 client-output-buffer-limit slave 设置,当这个值太小会导致主从复制连接断开

1)当 master-slave 复制连接断开,master 会释放连接相关的数据。replication buffer 中的数据也就丢失了,此时主从之间重新开始复制过程。

2)还有个更严重的问题,主从复制连接断开,导致主从上出现重新执行 bgsave 和 rdb 重传操作无限循环。

当主节点数据量较大,或者主从节点之间网络延迟较大时,可能导致该缓冲区的大小超过了限制,此时主节点会断开与从节点之间的连接;

这种情况可能引起全量复制 -> replication buffer 溢出导致连接中断 -> 重连 -> 全量复制 -> replication buffer 缓冲区溢出导致连接中断……的循环。

具体详情:[top redis headaches for devops – replication buffer]
因而推荐把 replication buffer 的 hard/soft limit 设置成 512M。

config set client-output-buffer-limit "slave 536870912 536870912 0"
Copier après la connexion
65 哥:主从库复制为何不使用 AOF 呢?相比 RDB 来说,丢失的数据更少。

这个问题问的好,原因如下:

  • RDB 文件是二进制文件,网络传输 RDB 和写入磁盘的 IO 效率都要比 AOF 高。

  • 从库进行数据恢复的时候,RDB 的恢复效率也要高于 AOF。

增量复制

65 哥:主从库间的网络断了咋办?断开后要重新全量复制么?

在 Redis 2.8 之前,如果主从库在命令传播时出现了网络闪断,那么,从库就会和主库重新进行一次全量复制,开销非常大。

从 Redis 2.8 开始,网络断了之后,主从库会采用增量复制的方式继续同步。

增量复制:用于网络中断等情况后的复制,只将中断期间主节点执行的写命令发送给从节点,与全量复制相比更加高效

repl_backlog_buffer

断开重连增量复制的实现奥秘就是 repl_backlog_buffer 缓冲区,不管在什么时候 master 都会将写指令操作记录在 repl_backlog_buffer 中,因为内存有限, repl_backlog_buffer 是一个定长的环形数组,如果数组内容满了,就会从头开始覆盖前面的内容

master 使用 master_repl_offset记录自己写到的位置偏移量,slave 则使用 slave_repl_offset记录已经读取到的偏移量。

master 收到写操作,偏移量则会增加。从库持续执行同步的写指令后,在 repl_backlog_buffer 的已复制的偏移量 slave_repl_offset 也在不断增加。

正常情况下,这两个偏移量基本相等。在网络断连阶段,主库可能会收到新的写操作命令,所以 master_repl_offset会大于 slave_repl_offset

Explication détaillée de larchitecture de réplication maître-esclave dans Redis

当主从断开重连后,slave 会先发送 psync 命令给 master,同时将自己的 runIDslave_repl_offset发送给 master。

master 只需要把 master_repl_offsetslave_repl_offset之间的命令同步给从库即可。

增量复制执行流程如下图:

Explication détaillée de larchitecture de réplication maître-esclave dans Redis

65 哥:repl_backlog_buffer 太小的话从库还没读取到就被 Master 的新写操作覆盖了咋办?

我们要想办法避免这个情况,一旦被覆盖就会执行全量复制。我们可以调整 repl_backlog_size 这个参数用于控制缓冲区大小。计算公式:

repl_backlog_buffer = second * write_size_per_second
Copier après la connexion
  • second:从服务器断开重连主服务器所需的平均时间;

  • write_size_per_second:master 平均每秒产生的命令数据量大小(写命令和数据大小总和);

例如,如果主服务器平均每秒产生 1 MB 的写数据,而从服务器断线之后平均要 5 秒才能重新连接上主服务器,那么复制积压缓冲区的大小就不能低于 5 MB。

为了安全起见,可以将复制积压缓冲区的大小设为2 * second * write_size_per_second,这样可以保证绝大部分断线情况都能用部分重同步来处理。

基于长连接的命令传播

65 哥:完成全量同步后,正常运行过程如何同步呢?

当主从库完成了全量复制,它们之间就会一直维护一个网络连接,主库会通过这个连接将后续陆续收到的命令操作再同步给从库,这个过程也称为基于长连接的命令传播,使用长连接的目的就是避免频繁建立连接导致的开销。

在命令传播阶段,除了发送写命令,主从节点还维持着心跳机制:PING 和 REPLCONF ACK。

主->从:PING

每隔指定的时间,主节点会向从节点发送 PING 命令,这个 PING 命令的作用,主要是为了让从节点进行超时判断。

从->主:REPLCONF ACK

在命令传播阶段,从服务器默认会以每秒一次的频率,向主服务器发送命令:

REPLCONF ACK <replication_offset></replication_offset>
Copier après la connexion

其中 replication_offset 是从服务器当前的复制偏移量。发送 REPLCONF ACK 命令对于主从服务器有三个作用:

  • 检测主从服务器的网络连接状态。

  • 辅助实现 min-slaves 选项。

  • 检测命令丢失, 从节点发送了自身的 slave_replication_offset,主节点会用自己的 master_replication_offset 对比,如果从节点数据缺失,主节点会从 repl_backlog_buffer缓冲区中找到并推送缺失的数据。注意,offset 和 repl_backlog_buffer 缓冲区,不仅可以用于部分复制,也可以用于处理命令丢失等情形;区别在于前者是在断线重连后进行的,而后者是在主从节点没有断线的情况下进行的。

如何确定执行全量同步还是部分同步?

在 Redis 2.8 及以后,从节点可以发送 psync 命令请求同步数据,此时根据主从节点当前状态的不同,同步方式可能是全量复制部分复制。本文以 Redis 2.8 及之后的版本为例。

关键就是 psync的执行:

Explication détaillée de larchitecture de réplication maître-esclave dans Redis

  • 从节点根据当前状态,发送 psync命令给 master:

    • 如果从节点从未执行过 replicaof ,则从节点发送 psync ? -1,向主节点发送全量复制请求;
    • 如果从节点之前执行过 replicaof 则发送 psync <runid> <offset></offset></runid>, runID 是上次复制保存的主节点 runID,offset 是上次复制截至时从节点保存的复制偏移量。
  • 主节点根据接受到的psync命令和当前服务器状态,决定执行全量复制还是部分复制:

    • runID 与从节点发送的 runID 相同,且从节点发送的 slave_repl_offset 之后的数据在 repl_backlog_buffer 缓冲区中都存在,则回复 CONTINUE,表示将进行部分复制,从节点等待主节点发送其缺少的数据即可;
    • runID 与从节点发送的 runID 不同,或者从节点发送的 slave_repl_offset 之后的数据已不在主节点的 repl_backlog_buffer 缓冲区中 (在队列中被挤出了),则回复从节点 FULLRESYNC <runid> <offset></offset></runid>,表示要进行全量复制,其中 runID 表示主节点当前的 runID,offset 表示主节点当前的 offset,从节点保存这两个值,以备使用。

一个从库如果和主库断连时间过长,造成它在主库 repl_backlog_buffer 的 slave_repl_offset 位置上的数据已经被覆盖掉了,此时从库和主库间将进行全量复制。

总结下

每个从库会记录自己的 slave_repl_offset,每个从库的复制进度也不一定相同。

在和主库重连进行恢复时,从库会通过 psync 命令把自己记录的 slave_repl_offset 发给主库,主库会根据从库各自的复制进度,来决定这个从库可以进行增量复制,还是全量复制。

tampon de réplication et repl_backlog

  • tampon de réplication correspondent à chaque esclave, défini par config set client-output-buffer-limit slave .

  • repl_backlog_buffer est un tampon en anneau. Il n'y en aura qu'un dans tout le processus maître et il est commun à tous les esclaves. La taille de repl_backlog est définie par le paramètre repl-backlog-size. La taille par défaut est de 1 Mo. La taille peut être basée sur la commande générée par seconde, (le maître exécute rdb bgsave) + (le maître envoie rdb à l'esclave) + (l'esclave. charger le fichier rdb) et pour estimer la taille du tampon de backlog, la valeur repl-backlog-size n'est pas inférieure au produit des deux.

En général, replication buffer est le tampon sur la bibliothèque maître permettant au client de se connecter à la bibliothèque esclave lorsque la bibliothèque maître-esclave effectue une réplication complète, et repl_backlog_buffer is Afin de prendre en charge la réplication incrémentielle à partir de la bibliothèque esclave, un tampon dédié est utilisé pour sauvegarder en continu les opérations d'écriture sur la bibliothèque maître.

repl_backlog_buffer est un tampon dédié Une fois le serveur Redis démarré, il commence à recevoir des commandes d'opération d'écriture. Celle-ci est partagée par toutes les bibliothèques esclaves. La bibliothèque maître et la bibliothèque esclave enregistreront chacune leur propre progression de réplication. Par conséquent, lorsque différentes bibliothèques esclaves sont en cours de récupération, elles enverront leur propre progression de réplication (slave_repl_offset) à la bibliothèque maître, et la bibliothèque maître pourra se synchroniser avec elle indépendamment. .

Comme le montre la figure :

Explication détaillée de larchitecture de réplication maître-esclave dans Redis

4. Problèmes d'application maître-esclave

4.1 Le problème de la séparation en lecture et en écriture

Problème d'expiration des données

65 Frère : Dans le scénario de réplication maître-esclave, le nœud esclave supprime-t-il les données expirées ?

C'est une bonne question. Par souci de cohérence des données entre les nœuds maître et esclave, les nœuds esclaves ne supprimeront pas activement les données. Nous savons que Redis a deux stratégies de suppression :

  • Suppression paresseuse : lorsque le client interroge les données correspondantes, Redis détermine si les données ont expiré et les supprime si elles expirent.

  • Suppression régulière : Redis supprime les données expirées via des tâches planifiées.

65 Brother : Le client lira-t-il les données expirées en lisant les données du nœud esclave ?

À partir de Redis 3.2, lors de la lecture des données du nœud, déterminez d'abord si les données ont expiré. S'il expire, il ne sera pas restitué au client et les données seront supprimées.

4.2 Limite de taille de la mémoire d'une seule machine

Si la mémoire d'une seule machine Redis atteint 10 Go, le temps de synchronisation d'un nœud esclave est de l'ordre de plusieurs minutes ; s'il y a plus de nœuds esclaves, la vitesse de récupération sera plus lente. Si la charge de lecture du système est très élevée et que le nœud esclave ne peut pas fournir de services pendant cette période, cela mettra beaucoup de pression sur le système.

Si la quantité de données est trop importante, il faut trop de temps au nœud maître pour créer + enregistrer le fichier RDB pendant la phase de réplication complète, et le nœud esclave ne peut pas recevoir de données pendant une longue période, déclenchant un délai d'attente, et la synchronisation des données des nœuds maître et esclave peut également échouer Copie complète->Le délai d'attente provoque une interruption de la copie->Reconnecter->Copie complète->Le délai d'attente provoque une interruption de la copie. .. faire du vélo.

De plus, en plus de la quantité absolue de mémoire mono-machine du nœud maître, la proportion de la mémoire hôte qu'il occupe ne doit pas être trop importante : il est préférable de n'utiliser que 50 % à 65 % de la mémoire, laissant 30% - 45% La mémoire est utilisée pour exécuter la commande bgsave et créer des tampons de copie, etc.

Résumé

  • Le rôle de la réplication maître-esclave : les fichiers binaires AOF et RDB garantissent une récupération rapide des données après un temps d'arrêt et évitent la perte de données. autant que possible. Cependant, les services ne pouvaient toujours pas être fournis après un temps d'arrêt, de sorte qu'une architecture maître-esclave et une séparation lecture-écriture ont évolué.

  • Principe de la réplication maître-esclave : phase d'établissement de la connexion, phase de synchronisation des données, phase de propagation des commandes ; la phase de synchronisation des données est divisée en réplication complète et réplication partielle, là Les commandes PING et REPLCONF ACK effectuent une détection de battement de cœur l'une sur l'autre.

  • Bien que la réplication maître-esclave résolve ou atténue des problèmes tels que la redondance des données, la récupération après échec et l'équilibrage de charge en lecture, ses défauts sont toujours évidents : La récupération après échec ne peut pas être automatisée en écriture ; opérations L'équilibrage de charge ne peut pas être réalisé ; la capacité de stockage est limitée par une seule machine ; la solution à ces problèmes nécessite l'aide de Sentinel et Cluster , que je présenterai dans un article ultérieur Bienvenue pour y prêter attention.

65 Frère : Frère Ma, tes photos sont vraiment belles et le contenu est bon J'ai beaucoup gagné en suivant tes articles, je veux les collectionner, les aimer, les lire et les partager. . Laissez les développeurs les plus remarquables constater des progrès communs !

Pour plus de connaissances sur la programmation, veuillez visiter : Vidéo de programmation ! !

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!

Étiquettes associées:
source:segmentfault.com
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal