>  기사  >  데이터 베이스  >  Redis의 마스터-슬레이브 복제, 센트리, 클러스터링 이론에 대해 이야기해 보겠습니다. [자세한 설명은 그림과 텍스트로 설명]

Redis의 마스터-슬레이브 복제, 센트리, 클러스터링 이론에 대해 이야기해 보겠습니다. [자세한 설명은 그림과 텍스트로 설명]

青灯夜游
青灯夜游앞으로
2022-01-31 08:00:322583검색

이 글은 Redis의 세 가지 모드(마스터-슬레이브 복제, 센티널, 클러스터) 이론을 그림과 텍스트로 설명하는 데 도움이 되기를 바랍니다.

Redis의 마스터-슬레이브 복제, 센트리, 클러스터링 이론에 대해 이야기해 보겠습니다. [자세한 설명은 그림과 텍스트로 설명]

1. 마스터-슬레이브 복제

1. 마스터-슬레이브 동기화 사용

Redis는 지속성 기능을 통해 서버가 다시 시작되더라도 데이터가 손실되지 않도록 보장합니다. 메모리에 있는 데이터를 하드디스크에 저장하고, 다시 시작하면 하드디스크의 데이터가 로드됩니다. 그러나 데이터는 서버에 저장되어 있기 때문에 서버에 하드디스크 장애 등의 문제가 발생하면 데이터 손실도 발생합니다. . 단일 오류 지점을 방지하기 위해 일반적인 방법은 데이터베이스의 여러 복사본을 복제하여 다른 서버에 배포하는 것입니다. 그러면 한 서버에 오류가 발생하더라도 다른 서버가 계속해서 서비스를 제공할 수 있습니다. 이를 위해 redis는 한 데이터베이스의 데이터가 업데이트되면 업데이트된 데이터를 다른 데이터베이스에 자동으로 동기화할 수 있는 복제 replication 기능을 제공합니다. [관련 권장사항: Redis 동영상 튜토리얼]replication 功能,可以实现当一台数据库中的数据更新后,自动将更新的数据同步到其他数据库上。【相关推荐:Redis视频教程

  在复制的概念中,数据库分为两类,一类是主数据库 master,另一类是从数据库 slave。主数据库可以进行读写操作,当写操做导致数据变化时自动将数据同步给从数据库,而从数据库一般是只读的,并接收主数据库同步过来的数据。一个主数据库可以拥有多个从数据库,而一个从数据库只能拥有一个主数据库。

2. 主从同步原理

2.1 原理详解

Redis의 마스터-슬레이브 복제, 센트리, 클러스터링 이론에 대해 이야기해 보겠습니다. [자세한 설명은 그림과 텍스트로 설명]

  • 若启动一个 Slave 机器进程,则它会向 Master 机器发送一个 sync_command 命令,请求同步连接。

  • 无论是第一次连接还是重新连接,Master 机器都会启动一个后台进程,将数据快照(RDB)保存到数据文件中(.rdb文件),同时 Master 还会记录修改数据的所有命令并缓存在数据文件中。

  • 后台进程完成缓存操作之后,Master 机器就会向 Slave 机器发送数据文件,Slave 端机器将数据文件保存到硬盘上,然后将其加载到内存中,接着 Master 机器就会将修改数据的所有操作一并发送给 Slave 端机器。若 Slave 出现故障导致宕机,则恢复正常后会自动重新连接。

  • Master 机器收到 Slave 端机器的连接后,将其完整的数据文件发送给 Slave 端机器,如果 Master 同时收到多个 Slave发来的同步请求则 Master 会在后台启动一个进程以保存数据文件,然后将其发送给所有的 Slave 端机器,确保所有的 Slave 端机器都正常。

RDB 做全量同步,AOF 做增量同步

2.2 理论精简

Redis의 마스터-슬레이브 복제, 센트리, 클러스터링 이론에 대해 이야기해 보겠습니다. [자세한 설명은 그림과 텍스트로 설명]

slave -> master 发送 sync command 申请同步
master 主进程 -> 调用 fork() 函数 派生 RDB 子进程进行持久化 -> 生成 RDB 文件
将 RDB 文件推送给 slaves(完成全量同步)
#增量同步:使用到了 AOF 持久化(机制:将缓存数据保存到缓冲中),所以主从节点均需要开启 AOF
增量同步是通过 AOF 功能将缓存中的数据 append(追加)到缓冲中来进行 master 缓冲 -> slave 缓冲的同步
在持续性的运行过程中,也是增量持续同步的过程

2.3 最终精简版

slave -> master 发送 sync
master 使用 RDB 生成 .rdb 文件(全量同步)发送给 slaves
master 使用 AOF 将缓冲区数据同步给 slaves 缓冲区数据(增量)

二、哨兵模式

1. 哨兵的作用

哨兵的出现主要是解决了主从复制出现故障时需要人为干预的问题

哨兵模式主要功能:

集群监控:负责监控 redismaster 和 slave 进程是否正常工作
消息通知:如果某个 redis 实例有故障,那么哨兵负责发送消息作为报警通知给管理员
故障转移:如果 master node 挂掉了,会自动转移到 slave node 上
配置中心:如果故障转移发生了,通知 client 客户端新的 master 地址

  使用一个或者多个哨兵 sentinel 实例组成的系统,对 redis 节点进行监控,在主节点出现故障的情况下,能将从节点中的一个升级为主节点,进行故障转移,保证系统的可用性。

2. 哨兵原理

2.1 原理详解

Redis의 마스터-슬레이브 복제, 센트리, 클러스터링 이론에 대해 이야기해 보겠습니다. [자세한 설명은 그림과 텍스트로 설명]

  • 首先主节点的信息是配置在哨兵 sentinel 的配置文件中。

  • 哨兵节点会和配置的主节点建立起两条连接命令连接和订阅连接
    PS:redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消 息,订阅者 (sub)接收消息。

  • 哨兵会通过命令连接每 10s 发送一次 INFO 命令,通过 INFO 命令,主节点会返回自己的 run_id 和自己的从节点信息。

  • 哨兵会对这些从节点也建立两条连接命令连接和订阅连接。

  • 哨兵通过命令连接向从节点发送 INFO 命令,获取到他的一些信息:

run id(redis 服务器 id) 
role(职能)
从服务器的复制偏移量 offset
其他
  • 通过命令连接向服务器的 sentinel:hello

      복제 개념에 있어서 데이터베이스는 이는 두 가지 범주로 나누어집니다. 하나는 기본 데이터베이스 master이고 다른 하나는 슬레이브 데이터베이스 slave입니다. 마스터 데이터베이스는 읽기 및 쓰기 작업을 수행할 수 있습니다. 쓰기 작업으로 인해 데이터가 변경되면 데이터가 슬레이브 데이터베이스에 자동으로 동기화됩니다. 슬레이브 데이터베이스는 일반적으로 읽기 전용이며 마스터 데이터베이스에서 동기화된 데이터를 받습니다. 마스터 데이터베이스는 여러 슬레이브 데이터베이스를 가질 수 있고, 슬레이브 데이터베이스는 마스터 데이터베이스를 하나만 가질 수 있습니다. 🎜🎜🎜🎜2. 마스터-슬레이브 동기화 원리🎜🎜🎜🎜🎜2.1 원리에 대한 자세한 설명🎜🎜🎜여기에 이미지 설명 삽입🎜
    • 🎜슬레이브 시스템 프로세스가 시작되면 sync_command 명령을 마스터 시스템으로 보냅니다. 동기 연결을 요청합니다. 🎜
    • 🎜첫 번째 연결이든 재연결이든 마스터 머신은 데이터 스냅샷(RDB)을 데이터 파일(.rdb 파일)에 저장하기 위해 백그라운드 프로세스를 시작하고 마스터도 녹음을 수행합니다. 모든 명령에 대한 수정 데이터는 데이터 파일에 캐시됩니다. 🎜
    • 🎜백그라운드 프로세스가 캐싱 작업을 완료한 후 마스터 컴퓨터는 데이터 파일을 슬레이브 컴퓨터로 전송합니다. 슬레이브 컴퓨터는 데이터 파일을 하드 디스크에 저장한 다음 메모리에 로드합니다. 그러면 마스터 시스템에서 데이터를 수정하는 모든 작업이 슬레이브 시스템으로 전송됩니다. 슬레이브에 장애가 발생하여 다운타임이 발생하면 정상으로 돌아온 후 자동으로 다시 연결됩니다. 🎜
    • 🎜마스터 머신이 슬레이브 머신으로부터 연결을 받은 후 전체 데이터 파일을 슬레이브 머신으로 보냅니다. 마스터가 동시에 여러 슬레이브로부터 동기화 요청을 받으면 마스터는 백그라운드에서 데이터 파일을 저장하는 프로세스를 시작한 다음 모든 슬레이브 머신이 정상인지 확인하기 위해 모든 슬레이브 머신에 보냅니다. 🎜
    🎜RDB는 전체 동기화를 수행하고 AOF는 증분 동기화를 수행합니다.🎜🎜🎜2.2 이론적 단순화🎜🎜🎜여기에 이미지 설명 삽입🎜
    ####在从节点中挑选出新的主节点
    通讯正常
    优先级排序
    优先级相同时选择 offset 最大的
    
    ###将该节点设置成新的主节点SLAVEOF no one,并确保在后续的INGO命令时 该节点返回状态为master 
    ###将其他的从节点设置成从新的主节点复制,SLAVEOF命令
    ###将旧的主节点变成新的主节点的从节点
    
    PS:优缺点
    #优点:
    高可用,哨兵模式是基于主从模式的,所有主从模式的优点,哨兵模式都具有有;主从可以自动切换,系统更健壮,可用性更高
    
    #缺点:
    redis 比较难支持在线扩容,在群集容量达到上限时在线扩容会变得很复杂
    🎜🎜2.3 Final Lite Version🎜🎜
    默认将数据存储在内存/缓存中
    具有丰富的数据类型:string list hash set && order set 等
    重要数据持久化的功能,持久化的方式:AOF RDB

    🎜두 번째, 감시 모드🎜🎜 🎜🎜 1. 센트리의 역할🎜🎜🎜🎜센티넬의 출현은 주로 마스터-슬레이브 복제 실패 시 필요한 인간 개입 문제를 해결합니다.🎜🎜센티넬 모드의 주요 기능: 🎜
    LRU:淘汰策略
    1) 缓存中的数据进行随机淘汰
    2) 缓存中被设置了过期时间的数据进行随机淘汰
    3) 缓存中被设置了过期时间的数据,进行惰性删除(仅当访问到的数据过期了,才会删除)
    4) 当数据持续存储过程中内存将满,会在设置了过期时间的数据中进行近期淘汰
    
    令牌桶 + 漏桶算法:限流
    Raft:选举机制,用于选举新的主节点
    🎜  하나 이상 사용 sentinel sentinel 인스턴스로 구성된 시스템은 redis 노드를 모니터링하며, 마스터 노드에 장애가 발생하면 슬레이브 노드 중 하나를 마스터 노드로 업그레이드하여 시스템 가용성을 보장할 수 있습니다. 🎜🎜🎜🎜2. 센티넬 원리🎜🎜🎜🎜🎜2.1 원리에 대한 자세한 설명🎜🎜🎜여기에 이미지 설명 삽입🎜
    • 🎜먼저 마스터 노드 정보는 센티넬 센티널의 구성 파일에서 구성됩니다. 🎜
    • 🎜센티넬 노드는 구성된 마스터 노드와 명령 연결 및 구독 연결이라는 두 가지 연결을 설정합니다.
      PS: redis 게시 및 구독(pub/sub)은 메시지 통신 모드입니다. : 발신자(pub)가 메시지를 보내고 구독자(sub)가 메시지를 받습니다. 🎜
    • 🎜 센티넬은 명령 연결을 통해 10초마다 INFO 명령을 보냅니다. INFO 명령을 통해 마스터 노드는 자신의 run_id와 슬레이브 노드 정보를 반환합니다. 🎜
    • 🎜Sentinel은 이러한 슬레이브 노드에 대해 명령 연결과 구독 연결이라는 두 가지 연결도 설정합니다. 🎜
    • 🎜센티넬은 명령 연결을 통해 슬레이브 노드에 INFO 명령을 보내고 해당 정보 중 일부를 얻습니다. 🎜
    高热数据:命中次数高的数据
    指定提高缓存内数据的命中数,最直接的可以刷脚本,访问这些数据
    • 🎜서버로 명령 연결 sentinel:hello를 통해 채널은 자체 IP, 포트, 실행 ID, 구성(후속 투표에 사용됨) 등을 포함하는 메시지를 보냅니다. 🎜
    • 通过订阅连接对服务器的 sentinel:hello 频道做了监听,所有向该频道发送的哨兵的消息都能被接受到。

    • 解析监听到的消息,进行分析提取,就可以知道还有那些别的哨兵服务节点也在监听这些主从节点了,更新结构体将这些哨兵节点记录下来。

    • 向观察到的其他的哨兵节点建立命令连接(此时没有订阅连接)。

    2.2 原理精简

    3 个哨兵 3 个 redis

    • 三个哨兵之间建立命令连接,周期检测 “队友” 状态
    • 哨兵会向 master 节点(己在配置文件中指定)发送两条连接,分别是命令连接和订阅连接(为了周期性获取 master 节点的数据)
    • 哨兵向 master 周期性发送 info 命令,master(活着的情况下)会返回 redis-cli info replication master 节点的信息 + 从节点位置
    • 哨兵通过 master 返回的信息,再向 slaves 节点发送 info 命令,slaves 返回数据,从而哨兵集群就可以获取到 redis 所有集群信息
    • 哨兵会向服务器发送命令连接,建立自己的 hello 频道,哨兵会向这个 hello 频道建立订阅,用于哨兵之间的消息共享

    2.3 思路

    • 3 个哨兵互相监听,使用 ping 互相检测存活
    • 3 个哨兵分别向数据节点 master 发送命令连接和订阅连接(info 命令)获取数据节点信息(包含主从节点)3 个哨兵再向其他从节点发送 info ,用于获取从节点详细信息
    • 3 个哨兵之间通过 hello 频道进行消息共享

    3. 哨兵模式下的故障迁移

    • ① 主观下线
      哨兵节点会每秒一次的频率向建立了命令连接的实例发送 PING 命令,如果在 down-after-milliseconds 毫秒内没有做出有效响应包括 PONG/LOADING/MASTERDOWN 以外的响应,哨兵就会将该实例在本结构体中的状态标记为 SRI_S_DOWN 主观下线。

    • ② 客观下线
      当一个哨兵节点发现主节点处于主观下线状态是,会向其他的哨兵节点发出询问,该节点是不是已经主观下线了。如果超过配置参数 quorum 个节点认为是主观下线时,该哨兵节点就会将自己维护的结构体中该主节点标记为 SRIO DOWN 客观下线询问命令 SENTINEL is-master-down-by-addr

    • ③ master 选举
      在认为主节点客观下线的情况下,哨兵节点节点间会发起一次选举,命令为 SENTINEL is-master-down-by-addr ,只是 runid 这次会将自己的 runid 带进去,希望接受者将自己设置为主节点。如果超过半数以上的节点返回将该节点标记为 leader 的情况下,会有该 leader 对故障进行迁移。

    • ④ 故障转移

    ####在从节点中挑选出新的主节点
    通讯正常
    优先级排序
    优先级相同时选择 offset 最大的
    
    ###将该节点设置成新的主节点SLAVEOF no one,并确保在后续的INGO命令时 该节点返回状态为master 
    ###将其他的从节点设置成从新的主节点复制,SLAVEOF命令
    ###将旧的主节点变成新的主节点的从节点
    
    PS:优缺点
    #优点:
    高可用,哨兵模式是基于主从模式的,所有主从模式的优点,哨兵模式都具有有;主从可以自动切换,系统更健壮,可用性更高
    
    #缺点:
    redis 比较难支持在线扩容,在群集容量达到上限时在线扩容会变得很复杂

    三、集群

    1. redis 集群的含义

    主节点负责读写请求和集群信息的维护,从节点只进行主节点数据和状态信息的复制
    Redis의 마스터-슬레이브 복제, 센트리, 클러스터링 이론에 대해 이야기해 보겠습니다. [자세한 설명은 그림과 텍스트로 설명]

      redis 的哨兵模式基本已经可以实现高可用、读写分离,但是在这种模式每台 redis 服务器都存储相同的数据,很浪费内存资源,所以在 redis3.0 上加入了 Cluster 群集模式,实现了 redis 的分布式存储,也就是说每台 redis 节点存储着不同的内容。根据官方推荐,集群部署至少要 3 台以上的 master 节点,最好使用 3 主 3 从六个节点的模式。
      Cluster 群集由多个 redis 服务器组成的分布式网络服务群集,群集之中有多个 master 主节点,每一个主节点都可读可写,节点之间会相互通信,两两相连,redis 群集无中心节点。

    2. redis 集群的特点

    • 在 redis-Cluster 群集中,可以给每个一个主节点添加从节点,主节点和从节点直接尊循主从模型的特性,当用户需要处理更多读请求的时候,添加从节点可以扩展系统的读性能
    • redis-cluster 的故障转移:redis 群集的主机节点内置了类似 redis sentinel 的节点故障检测和自动故障转移功能,当群集中的某个主节点下线时,群集中的其他在线主节点会注意到这一点,并且对已经下线的主节点进行故障转移
    • 集群进行故障转移的方法和 redis sentinel 进行故障转移的方法基本一样,不同的是,在集群里面,故障转移是由集群中其他在线的主节点负责进行的,所以群集不必另外使用 redis sentinel

    四、分布式锁

    https://www.zhihu.com/question/300767410/answer/1749442787
      如果在一个分布式系统中,我们从数据库中读取一个数据,然后修改保存,这种情况很容易遇到并发问题。因为读取和更新保存不是一个原子操作,在并发时就会导致数据的不正确。这种场景其实并不少见,比如电商秒杀活动,库存数量的更新就会遇到。如果是单机应用,直接使用本地锁就可以避免。如果是分布式应用,本地锁派不上用场,这时就需要引入分布式锁来解决。由此可见分布式锁的目的其实很简单,就是为了保证多台服务器在执行某一段代码时保证只有一台服务器执行。

    简单来说:
      现在的业务应用通常都是微服务架构,这也意味着一个应用会部署多个进程,那么多个进程如果需要修改数据库中的同一行记录时,为了避免操作乱序导致数据错误,此时就需要引入分布式锁解决问题。

    为了保证分布式锁的可用性,至少要确保锁的实现要同时满足以下几点:

    • 互斥性。在任何时刻,保证只有一个客户端持有锁。
    • 不能出现死锁。如果在一个客户端持有锁的期间,这个客户端崩溃了,也要保证后续的其他客户端可以上锁。
    • 保证上锁和解锁都是同一个客户端。

    一般来说,实现分布式锁的方式有以下几种:

    • 使用 MySQL,基于唯一索引。
    • 使用 ZooKeeper,基于临时有序节点。
    • 使用 Redis,基于 setnx 命令。

    Redis의 마스터-슬레이브 복제, 센트리, 클러스터링 이론에 대해 이야기해 보겠습니다. [자세한 설명은 그림과 텍스트로 설명]
    对 redis 来说注意三点,对 key 的加锁,如果请求未完成对快要过期的 key 的续期,请求完成后 key 的解锁。防止并发环境下被读取的一个 key 可能被多个请求修改,造成无效操作,资源浪费的情况。

    五、redis 总结

    • redis 可以做为 mysql 的前置缓存数据库,redis 与 mysql 对接的方式需要配置线程池,需要定义后端 mysql 的位置( IP + port +sock 文件的位置)

    • redis 基础功能:用于内存/缓存的快速存储(读取)

    • 实现的方式:

    默认将数据存储在内存/缓存中
    具有丰富的数据类型:string list hash set && order set 等
    重要数据持久化的功能,持久化的方式:AOF RDB

    单线程模式 -> 速度快的原因之一:Epoll + I/O 复用(cluster 中的 slots 哈希槽可以充当数据读、取的索引)

    • redis 中的算法:
    LRU:淘汰策略
    1) 缓存中的数据进行随机淘汰
    2) 缓存中被设置了过期时间的数据进行随机淘汰
    3) 缓存中被设置了过期时间的数据,进行惰性删除(仅当访问到的数据过期了,才会删除)
    4) 当数据持续存储过程中内存将满,会在设置了过期时间的数据中进行近期淘汰
    
    令牌桶 + 漏桶算法:限流
    Raft:选举机制,用于选举新的主节点
    • redis 缓存高热数据的机制
    高热数据:命中次数高的数据
    指定提高缓存内数据的命中数,最直接的可以刷脚本,访问这些数据

    六、系统优化

    1. 单例服务器,服务器本身优化

    硬件资源选择(系统五大资源)

    • 磁盘 固态盘 SCSI(硬件磁盘阵列)
    • 服务器内存条选择(本地服务器和云服务器)
    • CPU 核数选择
    • 网络网卡(本地服务器和云服务器),需要考虑负载压力下的网络流量 QPS
    • 服务器选型(麒麟、晓龙、浪潮英信、华为、华三、戴尔(类型:刀片、塔式、机柜))

    以上需要计算费用成本,还需要考虑到该服务器上的服务在运行时消耗的性能比例(需要预留给系统一部分资源)

    服务本身环境的选择

    • 操作系统选择 Linux 发行版:centos ubuntu redhat server debian alphon mac SUSE(PS:虚拟化 KVM XEN FUFE)

    • 基于操作系统,依赖环境。选择最小化安装还是指定操作系统版本的安装 + 指定内核版本。软件是否有依赖(例如:tomcat 需要 JDK,编译需要 gcc gcc-c++ pcre …)

    • 소프트웨어 리소스 최적화 5대 로드 + 커널 최적화 (TCP 프로토콜 관련, 대기열 관련, 라우팅 및 전달, 리디렉션, 포트, 열린 파일 수, 시스템 소프트웨어 및 하드웨어 제한 등) 五大负载+内核优化(TCP协议相关、队列相关、路由转发、重定向、端口、文件打开数、系统的软硬限制等)

    2. 单例服务器应用服务本身优化

    以 redis 为例

    首先从启动读取的恢复文件来看,基于AOF需要开启 AOF功能(RDB 默认)

    • RDB 中 save M N 触发周期的选择判定,这会影响到磁盘资源的使用
    • AOF 中选择合适的 syncwrite 同步写入磁盘的策略 everysecond

    使用过程中,需要考虑到的是内存的使用量( OOM )

    • 内存淘汰策略:惰性淘汰+定期删除,禁止淘汰+定期删除。根据情况选择合适的淘汰策略(配置文件中定义)。

    持久化方向
    持久化的功能在保证数据完整性的同时,依然会持续性的对磁盘产生存储压力(压力来源于 AOF 和 RDB 生成的数据文件,AOF 和 RDB 的日志文件)。

    • 数据/日志文件的定期归档
    • 日志文件的分割(保存在日志中心)
    • 共享存储 NFS GFS fastDFS

    2. 싱글톤 서버 애플리케이션 서비스 자체 최적화
    • redis를 예로 들어

    먼저 읽기 시작한 복구 파일에서 AOF AOF(RDB 기본값)를 기반으로 기능을 활성화해야 합니다

    디스크 리소스 사용에 영향을 미치는 RDB의 저장 M N 트리거 주기 선택 및 결정

    AOF에서 디스크에 동기적으로 쓰기 위한 적절한 syncwrite 전략 선택 매초

    사용 중에 고려해야 할 것은 메모리 사용량(OOM)입니다.

    메모리 제거 전략: 지연 제거 + 일반 삭제, 금지 제거 + 일반 삭제. 상황에 따라 적절한 제거 전략(구성 파일에 정의됨)을 선택하십시오.

    지속성 방향
    데이터 무결성을 보장하는 동시에 지속성 기능은 디스크에 계속해서 스토리지 압력을 생성합니다(압력은 AOF 및 RDB에서 생성된 데이터 파일과 AOF 및 RDB 문서의 로그에서 발생함). .

    🎜🎜데이터/로그 파일의 정기적인 보관 🎜🎜로그 파일 분할(로그 센터에 저장) 🎜🎜공유 저장소 NFS GFS fastDFS🎜🎜🎜🎜redis 메인 프로세스🎜🎜🎜🎜는 가능 두 개의 Redis 기본 프로세스가 협력하여 백업 중복성을 달성하고 높은 동시성에 저항하는 능력을 향상합니다🎜🎜🎜🎜🎜🎜4. 아키텍처 최적화🎜🎜🎜🎜🎜🎜5. 데이터 흐름 방향🎜 🎜🎜🎜더 많은 프로그래밍 관련 지식을 보려면 🎜프로그래밍 입문🎜을 방문하세요! ! 🎜

위 내용은 Redis의 마스터-슬레이브 복제, 센트리, 클러스터링 이론에 대해 이야기해 보겠습니다. [자세한 설명은 그림과 텍스트로 설명]의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

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