毕业设计之mysql+主从复制+keepalived
环境介绍
mysql_VIP:192.168.111.123
mysql_M!:192.168.111.151
mysql_M2:192.168.111.152
安装mysql可以查看
两个数据库都需要设置主从复制使用的账号和权限
mysql> grant replication slave on *.* to bbs_slave@'192.168.111.%' identified by 'salve2004';
Query OK, 0 rows affected, 1 warning (0.16 sec)
mysql> flush privileges;
注意:其中relication slave是权限 bbs_slave 是账号名字
主库开启二进制日志和设置server_id
主要加入这些
#开启二进制日志并指定位置
log-bin=/data/mysql/logs/mysql-bin
#设置id
server-id=1
重启主库服务器;
[root@mysql.quan.bbs ~]$service mysqld restart
Shutting down MySQL.. SUCCESS!
Starting MySQL.. SUCCESS!
查看master状态:
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 | 1058 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
上面的File Position是后面需要用到的
导出以存在的数据并复制到从库(这里只列出一库)
[root@mysql.quan.bbs data]$mysqldump -u root -p --all-databases >/tmp/2020.02.20.sql
Enter password:
[root@mysql.quan.bbs data]$scp -P 20042 /tmp/2020.02.20.sql apps@192.168.111.153:/tmp
apps@192.168.111.153's password:
2020.02.20.sql 100% 3136KB 3.1MB/s 00:00
两个从库都需要设置的
导入接受到的数据文件:
[root@mysql.bktwo.quan.bbs tmp]$mysql -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 10
Server version: 5.7.29-log Source distribution Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> source /tmp/2020.02.20.sql
修改配置文件:
主要加入这些
#开启二进制日志并指定位置
log-bin=/data/mysql/logs/mysql-bin
#设置id
server-id=33 #不能和master重复
重启服务器:
[root@mysql.bkone.quan.bbs data]$service mysqld restart
登陆数据库设置master信息:
建议先确保slave是停止的(stop slave)
mysql> change master to
-> master_host='192.168.111.151',
-> master_user='bbs_slave',
-> master_password='slave2004',
-> master_port=3306,
-> master_log_file='mysql-bin.000001',
-> master_log_pos=1058;
Query OK, 0 rows affected, 2 warnings (0.01 sec)
注意:有些数据是主库拿到的,master_log_file master_log_pos
启动slave并查看状态:
mysql> start slave;
Query OK, 0 rows affected (0.10 sec)
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.111.151
Master_User: bbs_slave
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000003
Read_Master_Log_Pos: 154
Relay_Log_File: mysql-relay-bin.000002
Relay_Log_Pos: 320
Relay_Master_Log_File: mysql-bin.000003
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 154
Relay_Log_Space: 527
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 1
Master_UUID: ad0e3900-4a82-11ea-927e-005056370631
Master_Info_File: /data/mysql/data/master.info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
Master_Retry_Count: 86400
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set:
Executed_Gtid_Set:
Auto_Position: 0
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:
1 row in set (0.00 sec)
测试就主库创建一个数据库,去从库查看有无同步即可
按照上面的使M1和M2达到互为主从同步
配置keepalived高可用
M1 M2都需要安装
[root@mysql.bkone.quan.bbs ~]$yum install keepalived -y
先修改M1的配置文件:
[root@mysql.quan.bbs ~]$vim /etc/keepalived/keepalived.conf global_defs {
router_id MYSQL_MM # 标识
vrrp_skip_check_adv_addr
vrrp_strict # 严格执行 VRRP 协议规范
vrrp_garp_interval 0
vrrp_gna_interval 0
} vrrp_script check_mysql {
script "/bin/sh /etc/keepalived/keepalived_mysql_check.sh" # 检查脚本
interval 10 # 检查周期
} vrrp_instance MYSQL_MM {
state BACKUP # 都设为 BACKUP,避免起来后抢占
interface eth0 # 网卡名称,根据实际情况填写
virtual_router_id 222 # 用来区分 VRRP 组播的标记,取值 0-255
priority 100
advert_int 1
nopreempt # 设为非抢占
authentication {
auth_type PASS
auth_pass 1111
} virtual_ipaddress {
192.168.111.123
} # Slave 节点可以注释下面检查脚本,Slave 没有必要一直检查
track_script {
check_mysql
}
}
M2的配置文件: 主要修改
virtual_router_id nopreempt priority
global_defs {
router_id MYSQL_MM # 标识
vrrp_skip_check_adv_addr
vrrp_strict # 严格执行 VRRP 协议规范
vrrp_garp_interval 0
vrrp_gna_interval 0
} vrrp_script check_mysql {
script "/bin/sh /etc/keepalived/keepalived_mysql_check.sh" # 检查脚本
interval 10 # 检查周期
} vrrp_instance MYSQL_MM {
state BACKUP # 都设为 BACKUP,避免起来后抢占
interface eth0 # 网卡名称,根据实际情况填写
virtual_router_id 223 # 用来区分 VRRP 组播的标记,取值 0-255
priority 99
advert_int 1
# nopreempt # 设为非抢占
authentication {
auth_type PASS
auth_pass 1111
} virtual_ipaddress {
192.168.111.123
} # Slave 节点可以注释下面检查脚本,Slave 没有必要一直检查
track_script {
check_mysql
}
}
M1 M2都需要编写检测脚本:
#!/bin/bash
counter=$(netstat -an|grep "LISTEN"|grep "3306"|wc -l) if [ "${counter}" -eq 0 ]; then
/etc/init.d/keepalived stop
fi
测试:
#M1未关闭
[root@mysql.quan.bbs ~]$mysql -u bbs_slave -h 192.168.111.123 -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 648
Server version: 5.7.29-log Source distribution Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> show variables like 'hostname';
+---------------+----------------+
| Variable_name | Value |
+---------------+----------------+
| hostname | mysql.quan.bbs |
+---------------+----------------+
1 row in set (0.00 sec) mysql> exit
Bye
#M1关闭
[root@mysql.quan.bbs ~]$service mysqld stop
Shutting down MySQL........... SUCCESS!
[root@mysql.quan.bbs ~]$mysql -u bbs_slave -h 192.168.111.123 -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 105
Server version: 5.7.29-log Source distribution Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> show variables like 'hostname';
+---------------+----------------------+
| Variable_name | Value |
+---------------+----------------------+
| hostname | mysql.bkone.quan.bbs |
+---------------+----------------------+
1 row in set (0.01 sec) mysql> exit
Bye
#M1 重新开始
[root@mysql.quan.bbs ~]$service mysqld start
Starting MySQL. SUCCESS!
[root@mysql.quan.bbs ~]$mysql -u bbs_slave -h 192.168.111.123 -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 107
Server version: 5.7.29-log Source distribution Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> show variables like 'hostname';
+---------------+----------------------+
| Variable_name | Value |
+---------------+----------------------+
| hostname | mysql.bkone.quan.bbs |
+---------------+----------------------+
1 row in set (0.00 sec)
原理解析:
】双主KeepAlived
【4.0】概念
MySQL的高可用方案有很多,比如Cluster、MMM、MHA、DRBD,以及Oracle官方推出的Fabric等,这些方案各有优劣,但都比较复杂,安装配置有一定难度,对线上库实施动静太大。就我们的具体情况而言,并不需要这么复杂的环境,实施简单、对现有架构影响最小、能迅速解决问题的方案才是最适合的。比如我们现在只是配置了MySQL Replication,加上如Keepalived这样的高可用软件,就能实现我们的需求。
MySQL架构为Master/Slave,当Master故障时,虚IP漂移到Slave上提供服务,简单环境如图1所示。在这种架构中,故障自动切换以后,需要采取手动操作的方式与新的Master进行复制。当然也可以设置为Active-Passive模式下的双Master复制。
利用KeepAlived实现故障转移(功能上类似于MSSQL的镜像,形式上类似于windows的故障转移群集)
【4.1】keepalived 简介
(4.1.1)起源
keepalived软件起初是专门为了LVS负载均衡软件设计的,用来管理并监控LVS集群系统中各个服务节点的状态,后台又加入了可以实现高可用的VRRP功能。(VRRP:全称 virtual router redundancy protocol,虚拟路由冗余协议)
因此Keepalived除了能够管理LVS软件外,还可以作为其他服务(如:Nginx/Haproxy/Mysql)的高可用解决方案软件;
(4.1.2)实现与组成
keepalived 软件主要是通过VRRP协议实现高可用功能的。
VRRP是 virtual route redundancyProtocol(虚拟路由器荣誉协议)的缩写,VRRP出现的目的就是为了解决静态路由单点故障问题,它能够保证当个别节点宕机时,整个网络可以不间断的运行。
(4.1.3)常见运作场景
一个web服务器至少有2台PC运行Keepalived,一台作为主服务器(master),一台作为备份服务器(Backup),但是对外表现为一个虚拟IP,在Keepalived服务政策工作时,主Master节点会不断地向备节点发送(多播的方式,组播地址为224.0.0.18)心跳消息,用以告诉备节点自己还活着。
当主Master节点发生故障时,就无法发送心跳消息,备节点也就因此无法继续监测到来自主Master节点的心跳,于是调用自身接管程序,接管主Master节点的IP资源及服务。
而当主Master节点恢复时,备Backup节点又会释放主节点故障时自身接管的IP资源及服务,恢复到原来的备用角色。(抢占模式)(也可以设置成非抢占模式,让其保持主,而不释放资源给原主,具体见4.1.7)
所以,keepAlived,一方面具有配置管理LVS的功能,同时还具有对LVS下面节点进行健康检查的功能,另一方面也可以实现系统网络服务的高可用功能,而且Keepalived是可以工作在网络的 Layer3,4&7,即网络层(IP层),传输层(TCP层),及应用层,再后面就直接在很多场景下代替了原始的LVS软件方案。
(4.1.4)keepalived服务的三个重要功能
(1)管理LVS负载均衡软件
(2)实现LVS集群节点的健康检查
(3)作为系统网络服务的高可用性(failover)
(4.1.5)Keepalived服务的工作原理
Keepalived服务对之间通过VRRP进行通信的,VRRP是通过竞选机制来确定主备的(有点像故障转移群集中的投票仲裁形式),主的优先级高于备,因此工作时主会优先获得所有的资源,备节点处于等待状态,当主挂了的时候,备节点就会接管主节点的资源,然后顶替主节点对外服务。
在Keepalived服务对之间,只有作为主的服务器会一直发送VRRP广播包,告诉备它还活着,此时备不会抢占主,当主不可用(也就是备没有受到VRRP广播包信息),就会启动相关服务接管资源,保证业务的连续性,接管速度最快可以小于1秒。
(4.1.6)keepalived 的三个核心模块
分别是core/check/vrrp
core:keepalived的核心,负责主进程的启动、维护以及全局配置文件的加载和解析。
check:负责健康检查,包括常见的各种检查方式。
vrrp:是用来实现VRRP协议的;(VRRP:全称 virtual router redundancy protocol,虚拟路由冗余协议)
(4.1.7)什么是VRRP?
VRRP,全称 virtual router redundancy protocol,虚拟路由冗余协议。
VRRP的出现就是为了解决静态路由的单点故障问题,VRRP是通过一种竞选机制来将路由的任务交给某台VRRP路由器的。
(1)VRRP是怎么解决通信问题的?
在现实的网络环境中,两台需要通信的主机(end-host)大多数情况下并没有直接地物理连接。对于这样的情况,它们之间的路由怎么选择?通常有两种方法解决如何选定到达目的主机的下一跳路由问题:
使用动态路由协议,如RIP、OSPF等。
配置静态路由。
很明显,在主机上配置动态路由,因为管理、维护成本以及是否支持等诸多问题是不切实际的。那么配置静态路由就变得很流行。
实际上,这种方式一直沿用至今。但是,路由器,或者说默认网关(default gateway)却经常成为单故障点。就算配置了多个静态路由,却因为必须重启网络才能生效而变得不实用。
VRRP(虚拟路由冗余协议,Virtual Router Redundancy Protocol)的目的就是为了解决静态路由单点故障问题。
它通过一种竞选(election)协议动态地将路由任务交给LAN中虚拟路由器中的某台VRRP路由器。这里有两个关键名词:VRRP路由器和虚拟路由器。
VRRP路由器:VRRP路由器就是一台路由器,只不过上面运行了VRRPD程序来实现VRRP协议而已,是物理的路由器。一台VRRP路由器可以位于多个虚拟路由器中。
虚拟路由器:所谓虚拟,就是说并不是实际存在的,是一个逻辑而不是物理的路由器。
虚拟路由器通常由多台VRRP路由器通过某种方式组成,就好像将这些物理路由器都丢到一个池里面去,整个池对外看起来就像是一台路由器,但其实内部有多台。虚拟路由器的标识称为VRID。
在一个VRRP虚拟路由中,有多台物理的VRRP路由器,但是这多台物理路由并不同时工作,而是由一台称为master的负责路由工作,其它的都是backup。
master并非一成不变,VRRP协议让每个VRRP路由器参与竞选,最终获胜的就是master。master有一些特权,比如拥有虚拟路由器的IP地址,我们的主机就是用这个IP地址作为静态路由的。
拥有特权的master要负责转发发送给网关地址的包和响应ARP请求。
(2)VRRP的工作机制
VRRP通过竞选协议来实现虚拟路由器的功能,所有的协议报文都是通过IP多播(multicast)包形式发送的,多播地址为224.0.0.18。虚拟路由器由VRID(范围0-255)和一组IP地址组成,对外表现为一个众所周知的MAC地址:00-00-5E-00-01-{VRID}。所以,在一个虚拟路由器中,不管谁是master,对外都是相同的MAC和IP(称之为VIP)。客户端主机并不需要因为master的改变而修改自己的路由配置,对它们来说,这种主从的切换是透明的。
在一个虚拟路由器中,只有作为master的VRRP路由器会一直发送VRRP广告包(VRRP Advertisement Message),backup不会抢占master,除非它的优先级更高。
当master不可用时,backup收不到广告包,多台backup中优先级最高的这台会抢占为master。这种抢占是非常快速的(<1秒),以保证服务的连续性。出于安全性考虑,VRRP包使用了加密协议进行加密
(3)keepalived的实现模式
Keepalived通过组播(默认)、单播(自定义),实现keepalived主备推选,工作模式分为抢占和非抢占。
《1》抢占模式
主服务器正常工作时,虚拟IP会在主上,备不提供服务,当主服务优先级低于备的时候,备会自动抢占虚拟IP,这时,主提供服务,备提供服务。
也就是说,抢占模式下,不分主备,只管优先级。
不管 keepalived.conf 里的 state 配置成 master 还是 backup ,只看谁的priority 优先级高, priority 优先级高的那一个,在故障恢复后,会自动将VIP资源再次抢回来。
《2》非抢占模式
这种方式通过参数nopreempt(一般设置在advert_int 的那一行下面)来控制。不管priority优先级,只要master机器发生故障,VIP资源就会被切换到backup上。
并且,当master机器恢复后,也不会将VIP资源抢回来。除非Backup机器发生故障,才能自动把VIP等资源切换会主库。
nopreempt 这个参数只能用户state为backup的情况,所以在配置的时候要把master和backup的state都设置成backup,这样才会实现keepalived的非抢占模式!
也就是说
a)当state状态一个为master,一个为backup的时候,加不加nopreempt 这个参数都是一样的效果。
即都是根据priority优先级来决定谁抢占VIP资源,属于抢占模式!
b)当state状态都设置成backup,如果不配置nopreempt参数。
也是根据priority优先级来决定谁抢占VIP资源,属于抢占模式!
c)当state状态都设置成backup,如果配置了 nopreempt 参数,那么久不会去考虑priority优先级了。
是非抢占模式! 即只有VIP当前所在机器发生故障,另一台机器才能接管VIP。 不考虑优先级问题。
【4.2】Keepalived在MySQL上有什么作用?
mysql双主复制,即互为Master-Slave(只有一个Master提供写操作),可以实现数据库服务器的热备。
但一个Master宕机后不能实现动态切换,使用Keepalived,可以通过虚拟IP,实现双主对外的统一接口以及自动检查、失败切换机制,从而实现MySQL数据库的高可用方案。
《1》架构1:主备集群架构(双主HA+keepalived)
方案:mysql 双主 或者 主从+keepalived 主从自动切换
服务器:2台PC
优点:架构简单,节省资源
缺点:无法线性扩展,主从失败后需要手动恢复主从架构
毕业设计之mysql+主从复制+keepalived的更多相关文章
- Dubbo入门到精通学习笔记(二十):MyCat在MySQL主从复制的基础上实现读写分离、MyCat 集群部署(HAProxy + MyCat)、MyCat 高可用负载均衡集群Keepalived
文章目录 MyCat在MySQL主从复制的基础上实现读写分离 一.环境 二.依赖课程 三.MyCat 介绍 ( MyCat 官网:http://mycat.org.cn/ ) 四.MyCat 的安装 ...
- Lvs+keepalived+mysql(主从复制)
1.准备环境 操作系统:centos 6.5 2台机器主机名为node53.node54 Mysql Lvs keepalived node2 Y Y Y node3 Y Y Y ...
- 浅谈mysql主从复制的高可用解决方案
1.熟悉几个组件(部分摘自网络)1.1.drbd —— DRBD(Distributed Replicated Block Device),DRBD号称是 "网络 RAID" ...
- mysql主从复制以及读写分离
之前我们已经对LNMP平台的Nginx做过了负载均衡以及高可用的部署,今天我们就通过一些技术来提升数据的高可用以及数据库性能的提升. 一.mysql主从复制 首先我们先来看一下主从复制能够解决什么问题 ...
- MySQL 主从复制详解
读写分离的意思是,写入的时候向 a 服务器写入,而读出的时候从 b c d 甚至更多的服务器读出:这样的架构适合于读多写少的应用,最典型的就是火车购票系统,一般我们买票的时候要先查询好多次,包括车次啊 ...
- MySQL主从复制解决数据库单点问题
一.单个数据库服务器的缺点 数据库服务器存在单点问题: 数据库服务器资源无法满足增长的读写请求: 高峰时数据库连接数经常超过上限. 二.如何解决单点问题 增加额外的数据库服务器,组建数据库集群: 同一 ...
- 高可用架构篇--MyCat在MySQL主从复制基础上实现读写分离
实战操作可参考:http://www.roncoo.com/course/view/3117ffd4c74b4a51a998f9276740dcfb 一.环境 操作系统:CentOS-6.6-x86_ ...
- MySQL MHA+Keepalived
一.MHA的简单介绍MHA是由perl语言编写的,用外挂脚本的方式实现mysql主从复制的高可用性.MHA可以自动检测mysql是否宕机,如果宕机,在10-30s内完成new master的选举,应用 ...
- MySQL主从复制(Master-Slave)实践
MySQL数据库自身提供的主从复制功能可以方便的实现数据的多处自动备份,实现数据库的拓展.多个数据备份不仅可以加强数据的安全性,通过实现读写分离还能进一步提升数据库的负载性能. 下图就描述了一个多个数 ...
随机推荐
- Java:动态代理小记
Java:动态代理小记 对 Java 中的 动态代理,做一个微不足道的小小小小记 概述 动态代理:当想要给实现了某个接口的类中的方法,加一些额外的处理.比如说加日志,加事务等.可以给这个类创建一个代理 ...
- 技术博客--微信小程序canvas实现图片编辑
技术博客--微信小程序canvas实现图片编辑 我们的这个小程序不仅仅是想给用户提供一个保存和查找的平台,还希望能给用户一个展示自己创意的舞台,因此我们实现了图片的编辑部分.我们对对图片的编辑集成了很 ...
- Request failed with status code 500以及自引用循环Self referencing loop detected for property ‘xx‘ with type
错误Error: Request failed with status code 500 ,调试前端没问题,后端也没问题,还报错"连接超时" 在Network中找到错误Self r ...
- redis5集群搭建步骤
通常情况下为了redis的高可用,我们一般不会使用redis的单实例去运行,一般都会搭建一个 redis 的集群去运行.此处记录一下 redis5 以后 cluster 集群的搭建. 一.需求 red ...
- elf文件--基于《ctf竞赛权威指南pwn篇》
1.ELF概念: ELF(Executable and Linkable Format),即"可执行可链接格式",最初由UNIX系统实验室作为应用程序二进制接口(Applicati ...
- 云效Flow如何实现阿里云ECS多环境发布
一.背景 云效Flow基于标签功能实现阿里云ECS多环境发布,在软件开发和部署过程中,我们的软件往往需要在不同的运行环境中运行,例如:开发人员本地开发环境.测试团队的测试环境.还有类生产环境和生产环境 ...
- ARM 链接配置.lds文件学习<转>
本文由Jacky原创,来自http://blog.chinaunix.net/u1/58780/showart.php?id=462971 对于.lds文件,它定义了整个程序编译之后的连接过程,决定了 ...
- C++中gSOAP的使用
目录 SOAP简介 gSOAP 准备工作 头文件 构建客户端应用程序 生成soap源码 建立客户端项目 构建服务端应用程序 生成SOAP源码 建立服务端项目 打印报文 SOAP测试 项目源码 本文主要 ...
- 记一次CTF比赛过程与解题思路-MISC部分
前言 最近好久没更新博客和公众号了,有朋友问是不是在憋大招,但我不好意思说其实是因为最近一段时间太懒了,一直在当咸鱼- 意识到很久没更新这个问题,我是想写点什么的,但好像一直当咸鱼也没啥可分享的,最近 ...
- 【编译原理】LL1文法语法分析器
上篇文章[编译原理]语法分析--自上向下分析 分析了LL1语法,文章最后说给出栗子,现在补上去. 说明: 这个语法分析器是利用LL1分析方法实现的. 预测分析表和终结符以及非终结符都是针对一个特定文法 ...