『互联网架构』软件架构-mysql主从(二)

通俗来讲,如果对数据库的读和写都在同一个数据库服务器中操作,业务系统性能会降低。 为了提升业务系统性能,优化用户体验,可以通过做主从复制(读写分离)来减轻主数据库的负载。 而且如果主数据库宕机,可快速将业务系统切换到从数据库上,可避免数据丢失。源码:https://github.com/limingios/netFuture

为什么要主从同步

  1. 实时灾备,用于故障切换
  2. 读写负载均衡
  3. 定时任务专用
  4. 开发人员查看

了解原理

下面这个图,就是主从同步的原理。

  1. webapp(就是java的应用程序)往主库mysqld内进行写。
    1.1 丢到mysql的data节点
    1.2 数据的语句丢到binlogs里(开启主从同步一定要开启binlogs)除了select查询语句都不在记录啦。
    1.3 主节点mysqld有个过滤器 ,可以指定那些数据库生成对应的binlogs。那些需要实时同步,那些不需要。
    1.4 binlogs 如果一直生成最后硬盘会不会爆掉,不会的可以设置binlogs的有效期,指定什么之前自动失效,它就会自动删除。
  2. 从库生成两个线程,一个I/O线程,一个SQL线程。
    2.1 i/o线程去请求主库 的binlog,并将得到的binlog日志写到relay log(中继日志) 文件中。
    2.2 relay log 被sql thread读又生成了binlog 和 data
    2.3 主库会生成一个 log dump 线程,用来给从库 i/o线程传binlog。
    2.4 slave里面的生成的binlog (可以打开,或者关闭)可以被另外的slave 进行读取。形成一个链式的。
  3. 同步的原理,binlog有个节点(position)当主从不一致的时候,slave 就要去拿了数据了。

问题及解决方法

mysql主从复制存在的问题:

  1. 主库宕机后,数据可能丢失
  2. 从库只有一个sql Thread,主库写压力大,复制很可能延时

解决

  • 半同步复制—解决数据丢失的问题(主节点插入前一条语句的时候,binlogs已经达到了slave的relay binlog)
  1. 5.5集成到mysql,以插件的形式存在,需要单独安装
  2. 确保事务提交后binlog至少传输到一个从库
  3. 不保证从库应用完这个事务的binlog
  4. 性能有一定的降低,响应时间会更长
  5. 网络异常或从库宕机,卡住主库,直到超时或从库恢复
  • 问题:当slave挂了时候,master一直通信,可能导致整个系统都蹦了
    解决方案:
  1. master等待通知的超时时间是10秒,如果10秒slave同步的标识还没到,我该继续插入到本地的master的data就插入。
  2. 但是很多公司都是设置1秒,因为很多公司99%的没问题的,但是1秒这1%,就有问题了。这个设置根据业务来。架构师的水平和经验了。

一致性和同步时间本身就是双刃剑,没有完全的通用解决方案,只能通过业务和性能综合考量选择最优解。
master和slave节点享受一致性的时候,比喻下:master是皇帝,下面很多的slave皇子,但是slave中肯定有一名是太子,当master驾崩了,其中一个太子就变成皇帝了。

互联网主流的主从的方案


  1. 一主一从,小公司使用比较多,并没有进行读写分离,slave节点主要是热备的。出现问题很快的恢复。记得当初有个同事无意中删除了一个很重要的表的数据,可能删除了20多条,导致半月都没好过,数据一致性的问题一直在解决。手工一条一条的找到。
  2. 一主多从,小公司使用比较多,一般情况下都是一个master节点三到4个slave的节点, 3个slave节点中其中一个是太子,可以保证数据的一致性,
  3. 双主,比较变态,一般用不到,写性能非常高的时候可能会用双主,mysql是允许,北京的写在一个库,上海的写在一个库,说实话不推荐。
  4. 级联同步,一个master一个slave(太子)节点多个slave节点,一个master如果下面不是级联的既要做读又要做写,还要做同步,master的节点压力很大。级联就是让其中一个slave做同步,给master节点的压力减少了,也达到了主从同步的问题。这个也有问题,如果太子挂掉了,后面的皇子没有领头羊了都变成单机了。
  5. 主主从,也就是2个主互访的,用后面的主来同步slave,但是如果后面的master挂掉的话,后面的slave也和级联同步的情况一致也尴尬了。
  6. 环形多主,非常变态,一定不推荐。写的并发是超级超级高的,没办法才这样玩,全国31省,31个master,每个省一个master,如果其中一个master挂掉,整个环形歇菜了。master下面也可以加入slave,估计超大型的才会用到。但是目前也不会这么用了。

介绍主流的一主多从的方案

如何实现,master就负责写,slave就负责读,需要一个负载均衡的解决方案。这里说下atlas。场景如果在商城生成一个订单,立马就要读这个订单,按照传统的方案我应该读slave库,但是这时候slave还没完成同步。这是不是很尴尬,解决方案就是atlas,如果你生成了订单在master,立马需要读的话,只需要在sql语句中加入一个注解,就可以直接去master里面读了。

Atlas是由 Qihoo 360公司Web平台部基础架构团队开发维护的一个基于MySQL协议的数据中间层项目。它在MySQL官方推出的MySQL-Proxy 0.8.2版本的基础上,修改了大量bug,添加了很多功能特性。目前该项目在360公司内部得到了广泛应用,很多MySQL业务已经接入了Atlas平台,每天承载的读写请求数达几十亿条。同时,有超过50家公司在生产环境中部署了Atlas,超过800人已加入了我们的开发者交流群,并且这些数字还在不断增加。
Atlas官方链接: https://github.com/Qihoo360/Atlas/blob/master/README_ZH.md
Atlas下载链接: https://github.com/Qihoo360/Atlas/releases

vagrant生成虚拟机

通过源码生成3个虚拟机,准备工作。vagrant已经安装了 对应的docker。用docker安装nexus就是为了避免环境变量,用户赋权等复杂的操作。对于vagrant的如何安装不用的系统不一样可以参看
mac 安装vgarant :https://idig8.com/2018/07/29/docker-zhongji-07/
window安装vgaranthttps://idig8.com/2018/07/29/docker-zhongji-08/

系统类型 IP地址 节点角色 CPU Memory Hostname
Centos7 192.168.66.101 atlas-proxy 2 2G atlas-proxy
Centos7 192.168.66.102 master 2 2G master
Centos7 192.168.66.103 slave 2 2G slave
  • 三台机器window/mac开通远程登录root用户下
su -
# 密码
vagrant
#设置 PasswordAuthentication yes
vi /etc/ssh/sshd_config
sudo systemctl restart sshd

  • 关闭、禁用防火墙(让所有机器之间都可以通过任意端口建立连接)

实际生产的环境,根据实际开通指定端口

systemctl stop firewalld
systemctl disable firewalld
#查看状态
systemctl status firewalld

102(master),103(slave)配置

拉取镜像

 docker pull mysql:5.7

102(master)配置

  • 配置目录
mkdir -p /usr/local/mysqlData/master/cnf
mkdir -p /usr/local/mysqlData/master/data
cd /usr/local/mysqlData/master/cnf
vi mysql.cnf

  • 配置mysql.cnf
[mysqld]
pid-file    = /var/run/mysqld/mysqld.pid
socket    = /var/run/mysqld/mysqld.sock
datadir    = /var/lib/mysql

symbolic-links=0

character-set-server = utf8   
#skip-networking  
innodb_print_all_deadlocks = 1
max_connections = 2000  
max_connect_errors = 6000  
open_files_limit = 65535  
table_open_cache = 128   
max_allowed_packet = 4M  
binlog_cache_size = 1M  
max_heap_table_size = 8M  
tmp_table_size = 16M  
  
read_buffer_size = 2M  
read_rnd_buffer_size = 8M  
sort_buffer_size = 8M  
join_buffer_size = 28M  
key_buffer_size = 4M  
  
thread_cache_size = 8  
  
query_cache_type = 1  
query_cache_size = 8M  
query_cache_limit = 2M  
  
ft_min_word_len = 4  
  
log-bin = mysql-bin
server-id = 1
binlog_format = mixed  
 
performance_schema = 0  
explicit_defaults_for_timestamp  
  
#lower_case_table_names = 1  
  
interactive_timeout = 28800  
wait_timeout = 28800  

# Recommended in standard MySQL setup  
  
sql_mode=NO_ENGINE_SUBSTITUTION,NO_AUTO_CREATE_USER,STRICT_TRANS_TABLES   
  
[mysqldump]  
quick  
max_allowed_packet = 16M  
  
[myisamchk]
key_buffer_size = 8M
sort_buffer_size = 8M
read_buffer = 4M
write_buffer = 4M
  • 启动容器
docker images
docker run -itd -p 3306:3306 --name master \
-v  /usr/local/mysqlData/master/cnf:/etc/mysql/conf.d \
-v /usr/local/mysqlData/master/data:/var/lib/mysql  \
-e MYSQL_ROOT_PASSWORD=masterpwd ae6b78bedf88
docker container ls

  • 进入容器开启远程访问
docker container ls
docker exec -it e2ca4d3cd633 /bin/bash
mysql -uroot -pmasterpwd
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'masterpwd' WITH GRANT OPTION;
GRANT REPLICATION SLAVE ON *.* to 'reader'@'%' identified by 'readerpwd';
FLUSH PRIVILEGES;
show master status;

103(slave)配置

  • 配置目录
mkdir -p /usr/local/mysqlData/slave/cnf
mkdir -p /usr/local/mysqlData/slave/data
cd /usr/local/mysqlData/slave/cnf
vi mysql.cnf

  • 配置mysql.cnf
[mysqld]
pid-file    = /var/run/mysqld/mysqld.pid
socket    = /var/run/mysqld/mysqld.sock
datadir    = /var/lib/mysql

symbolic-links=0

character-set-server = utf8   
#skip-networking  
innodb_print_all_deadlocks = 1
max_connections = 2000  
max_connect_errors = 6000  
open_files_limit = 65535  
table_open_cache = 128   
max_allowed_packet = 4M  
binlog_cache_size = 1M  
max_heap_table_size = 8M  
tmp_table_size = 16M  
  
read_buffer_size = 2M  
read_rnd_buffer_size = 8M  
sort_buffer_size = 8M  
join_buffer_size = 28M  
key_buffer_size = 4M  
  
thread_cache_size = 8  
  
query_cache_type = 1  
query_cache_size = 8M  
query_cache_limit = 2M  
  
ft_min_word_len = 4  
  
log-bin = mysql-bin
server-id = 2
binlog_format = mixed  
 
performance_schema = 0  
explicit_defaults_for_timestamp  
  
#lower_case_table_names = 1  
  
interactive_timeout = 28800  
wait_timeout = 28800  

# Recommended in standard MySQL setup  
  
sql_mode=NO_ENGINE_SUBSTITUTION,NO_AUTO_CREATE_USER,STRICT_TRANS_TABLES   
  
[mysqldump]  
quick  
max_allowed_packet = 16M  
  
[myisamchk]
key_buffer_size = 8M
sort_buffer_size = 8M
read_buffer = 4M
write_buffer = 4M
  • 启动容器
docker images
docker run -itd -p 3307:3306 --name slave1 \
-v /usr/local/mysqlData/slave/cnf:/etc/mysql/conf.d \
-v /usr/local/mysqlData/slave/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=slavepwd ae6b78bedf88
docker container ls

  • 进入容器开启远程访问

创建远程连接用户,并赋予查询数据库,以及查询的权限,可以用于读写分离。

docker container ls
docker exec -it c380d2b5f6cf /bin/bash
mysql -uroot -pslavepwd
grant SHOW DATABASES,SELECT on *.* to 'slave'@'%' identified by 'slavepwd';
FLUSH PRIVILEGES;

进入102master的mysql容器

查看主库 show master status

 show master status

进入103slave的mysql容器

配置主从,刚才102的status的postion=889 这里也要配置成一致的。
master_log_file 也需要跟主库保持一致


change master to master_host='192.168.66.102',master_user='reader',master_password='readerpwd',master_log_file='mysql-bin.000003',master_log_pos=889;

#启动主从
start slave;
show slave status\G

创建一个数据库自动同步完成

Atlas 代理配置(需要才用,不需要上边就足够了)

如果你想使用Atlas代理,就需要102的mysql密码 和103的mysql密码保持一致,原因是360好久不维护了,提问里面有人遇见过用多个pwds的时候直接出现乱码。103(slave)配置(配置目录,配置mysql.cnf 还是保持不变)

  • 重新删除103的slave的mysql创建新的
cd /usr/local/mysqlData/slave/data
rm -rf *
docker ps
docker rm -f c380d2b5f6cf
#这里的slave103的密码跟master102的密码一致
docker run -itd -p 3307:3306 --name slave1 \
-v /usr/local/mysqlData/slave/cnf:/etc/mysql/conf.d \
-v /usr/local/mysqlData/slave/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=masterpwd ae6b78bedf88   
docker ps      

  • 修改数据库权限
docker ps
docker exec -it e698f50d7ece /bin/bash
mysql -uroot -pmasterpwd

  • 102 进入mysql查看position
#一定要记牢了,slave同步的时候要用,如果不一致就无法同步啦
show master status;
 
  • 103 进入容器同步
docker ps
docker exec -it  6djasdad /bin/bash
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'masterpwd' WITH GRANT OPTION;
FLUSH PRIVILEGES;

change master to master_host='192.168.66.102',master_user='root',master_password='masterpwd',master_log_file='mysql-bin.000003',master_log_pos=1047;
#启动主从
start slave;
show slave status\G

在slave主机上这2个都为yes才算配置成功。

  • 进入101 主机开始配置代理
wget https://github.com/Qihoo360/Atlas/releases/download/2.2.1/Atlas-2.2.1.el6.x86_64.rpm
rpm -ivh Atlas-2.2.1.el6.x86_64.rpm 

  • 密码加密,配置文件需要
cd /usr/local/mysql-proxy/
cd bin
./encrypt masterpwd
#下面就需要这个密码 test.cnf里面需要
XYx4FmVBYrXmTh762ogNww==

  • 配置atlas文件
vi /usr/local/mysql-proxy/conf/test.cnf

这里pwds 对应的密码 就是上一步生成的,log-level设置成了debug目的好测试。sql-log=REALTIME可以查看sql的走向。

[mysql-proxy]

#带#号的为非必需的配置项目

#管理接口的用户名
admin-username = user

#管理接口的密码
admin-password = pwd

#Atlas后端连接的MySQL主库的IP和端口,可设置多项,用逗号分隔
proxy-backend-addresses = 192.168.66.102:3306

#Atlas后端连接的MySQL从库的IP和端口,@后面的数字代表权重,用来作负载均衡,若省略则默认为1,可设置多项,用逗号分隔
proxy-read-only-backend-addresses = 192.168.66.103:3307@1

#用户名与其对应的加密过的MySQL密码,密码使用PREFIX/bin目录下的加密程序encrypt加密,下行的user1和user2为示例,将其替换为你的MySQL的用户名和加密密码!
pwds = root:XYx4FmVBYrXmTh762ogNww==

#设置Atlas的运行方式,设为true时为守护进程方式,设为false时为前台方式,一般开发调试时设为false,线上运行时设为true,true后面不能有空格。
daemon = true

#设置Atlas的运行方式,设为true时Atlas会启动两个进程,一个为monitor,一个为worker,monitor在worker意外退出后会自动将其重启,设为false时只有worker,没有monitor,一般开发调试时设为false,线上运行时设为true,true后面不能有空格。
keepalive = true

#工作线程数,对Atlas的性能有很大影响,可根据情况适当设置
event-threads = 8

#日志级别,分为message、warning、critical、error、debug五个级别
log-level = debug

#日志存放的路径
log-path = /usr/local/mysql-proxy/log

#SQL日志的开关,可设置为OFF、ON、REALTIME,OFF代表不记录SQL日志,ON代表记录SQL日志,REALTIME代表记录SQL日志且实时写入磁盘,默认为OFF
sql-log = REALTIME

#慢日志输出设置。当设置了该参数时,则日志只输出执行时间超过sql-log-slow(单位:ms)的日志记录。不设置该参数则输出全部日志。
#sql-log-slow = 10

#实例名称,用于同一台机器上多个Atlas实例间的区分
#instance = test

#Atlas监听的工作接口IP和端口
proxy-address = 0.0.0.0:1234

#Atlas监听的管理接口IP和端口
admin-address = 0.0.0.0:2345

#分表设置,此例中person为库名,mt为表名,id为分表字段,3为子表数量,可设置多项,以逗号分隔,若不分表则不需要设置该项
#tables = person.mt.id.3

#默认字符集,设置该项后客户端不再需要执行SET NAMES语句
#charset = utf8

#允许连接Atlas的客户端的IP,可以是精确IP,也可以是IP段,以逗号分隔,若不设置该项则允许所有IP连接,否则只允许列表中的IP连接
#client-ips = 127.0.0.1, 192.168.1

#Atlas前面挂接的LVS的物理网卡的IP(注意不是虚IP),若有LVS且设置了client-ips则此项必须设置,否则可以不设置
#lvs-ips = 192.168.1.1

  • 启动atlas
cd /usr/local/mysql-proxy/bin/
# test 配置文件的名称 start 启动,stop 停止
./mysql-proxyd test start

监听端口默认是1234,我没修改,如果需要修改直接改test.cnf

  • 查看日志准备测试
cd /usr/local/mysql-proxy/log
tail -f sql_test.log

终于搞定了这个图

另外说一点,之前遇见的一个坑,当在项目中使用框架mybatis连数据库时,却都直接去主库读写数据了。偏偏添加了事务@Transactional
解决办法在方法上加@Transactional(propagation=Propagation.NOT_SUPPORTED)即可。

PS:其实很多公司都是通过代理的方式来管理主从数据库的。它可以有选择控制从哪个数据库走。感觉挺爽的,102走的是insert,103走的是select。

热门文章

暂无图片
编程学习 ·

Nginx系列(7):Nginx高并发初探

目录1、场景设置 — NGINX进程模型二、为什么框架如此重要?三、NGINX是如何运作的呢?四、NGINX内部工作进程五、NGINX是一个真正的大师六、更新配置文件升级NGINX七、结语原文出处:https://www.cnblogs.com/dz11/p/10215089.htmlNGINX 在网络应用中表现超群,在于其独特的设…
暂无图片
编程学习 ·

获取电脑ip地址的代码工具类

获取ip地址的工具类 import javax.servlet.http.HttpServletRequest;import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.util.StringUtils; import org.springframework.web.context.request.RequestContextHolder; import org.springfram…
暂无图片
编程学习 ·

Vue的路由/页面缓存及子组件刷新问题

文章目录需求说明分析及解决路由缓存页面组件刷新 需求说明 1、部分路由需要做缓存 2、单页面中部分组件需要重新渲染,比如:对表格进行新增、删除、修改等之后需要刷新页面中的部分组件keep-alive <keep-alive>包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们…
暂无图片
编程学习 ·

去掉无用节点

using UnityEngine; using UnityEditor; using System.Collections.Generic; using System.Text; using System.Text.RegularExpressions; using UnityEditorInternal;// 美术在导出模型时,有很多挂点是没有用的。但有些挂点却是有用的,跟美术沟通,有用挂点的名字。// 再使用…
暂无图片
编程学习 ·

Centos7x破解密码

办法一 1、开机启动部分1)开机e 选择第一行 e 2)找到Linux16所在行 ***.UTF8后面添加 rd.break console=tty0 3)ctrl + X2、启动到内核部分1)挂载/sysroot目录 #mount -o remount,rw /sysroot 2)切换到/sysroot目录 #chroot /sysroot 3)修改root密码 #echo passwo…
暂无图片
编程学习 ·

使用ftrace分析函数性能

0. 背景 ftrace的功能非常强大,可以在系统的各个关键点上采集数据用以追踪系统的运行情况。既支持预设的静态插桩点(trace event),也支持每个函数的动态插桩(function tracer)。还可以利用动态插桩来测量函数的执行时间(function graph tracer)。关于ftrace的详细操作和原理分…
暂无图片
编程学习 ·

SQL函数

SQL拥有很多可用于计数和计算的内建函数。SQL Aggregat函数计算从列中取得的值,返回一个单一的值。有用的Aggregate函数如下:AVG() - 返回平均值COUNT() - 返回行数FIRST() - 返回第一个记录的值LAST() - 返回最后一个记录的值MAX() - 返回最大值MIN() - 返回最小值SUM() - 返…
暂无图片
编程学习 ·

2020李宏毅学习笔记——33.Network Compression(2_6)

3.为什么要pruning? 首先有一个问题:既然最后要得到一个小的network,那为什么不直接在数据集上训练小(有local minima的问题)的模型,而是先训练大模型?解释一:模型越大,越容易在数据集上找到一个局部最优解,而小模型比较难训练,有时甚至无法收敛。 解释二:2018年的…
暂无图片
编程学习 ·

Kubernetes中的数据卷

文章目录Volume1.1 emptyDir1.2 configMap1.3 hostPath1.4 local1.5 persistentVolumeClaim (PVC)1.6 projected Volume容器中的文件在磁盘上是临时存放的,这给容器中运行的特殊应用程序带来一些问题。 首先,当容器崩溃时,kubelet 将重新启动容器,容器中的文件将会丢失——…
暂无图片
编程学习 ·

解决 java “错误:编码GBK 的不可映射字符”

今天一个学弟遇到这样的问题,如下图所示。 看到这样的问题,我的思考是: 1.首先是使用javac -version查看环境变量是否正确 2.然后查看编译路径是否存在中文 3.查看代码本身是否有中英文符号混淆 4.右击dos窗口,查看其属性中的编码集是否是utf-8 代码本身没问题,可以在exli…
暂无图片
编程学习 ·

WWDC20 苹果发布会

iphone上的ios14亮点不多 主要是桌面小组件 分类app显示 画中画 还有小程序 来电小窗提示和siri ui更新与更加智能 还有汽车智能钥匙 不用带钥匙只需要nfc就可以打开车门与开车 首款支持的汽车是 宝马5系ipad上的ipadOS14 拥有ios14的的全部更新 更加方便的ui以及全局搜索 也…
暂无图片
编程学习 ·

free_spirit(在栈上爆破一个可以被free的fake_chunk)

free_spirit(在栈上爆破一个可以被free的fake_chunk)首先检查一下程序的保护机制然后,我们用IDA分析一下,功能3存在8字节溢出,将会把v7下面的buf指针覆盖掉,而覆盖了buf指针,就能实现任意地址写。那么,我们劫持函数栈返回地址为one_gadget即可,为了绕过结尾对buf的检查…
暂无图片
编程学习 ·

firewalld管理方式

1.firewalld的开启 systemctl stop iptables systemctl disable iptables systemctl mask iptables systemctl unmask firewalld systemctl enable --now firewalld2.关于firewalld的域trusted 接受所有的网络连接home 用于家庭网络,允许接受ssh mdns ipp-client samba-clie…
暂无图片
编程学习 ·

Java语言基础(二)变量和数据类型

Java语言基础(二)二、变量和数据类型2.1 变量的基本概念2.2 变量的声明和使用2.3 变量使用是注意事项2.4 标识符的命名规则(笔试)关键字2.5 变量输入输出的案例实现2.6 变量输入输出案例的优化和手册介绍2.7 数据类型的分类2.8 常用的进制2.9 十进制与二进制之间的转换(1)正…
暂无图片
编程学习 ·

JavaScript之组合式继承

继承的概念 面向对象的三大特征:封装,继承,多态 封装: 将复杂的操作包裹起来,进行隐藏,简单化,安全化 继承: 拿来主义,自己没有,把别人的拿过来,让其成为自己的 JavaScript中有两种继承模型: 1.原型式继承 2.组合式继承 组合式继承就是将其他对象中的成员添加到自己…
暂无图片
编程学习 ·

SOLR_8.2_学习、使用、计划、思想、项目实践

文章目录一、项目安装部署:1.1、下载地址:1.2、解压1.3、启动1.4、浏览器访问二、项目部分配置2.1、创建核心文件夹(可以理解为数据库)2.2、将配置文件copy到meta_db中2.3、创建核心三、创建document(表)添加Field(字段)四、导入数据 documents五、查询数据5.1、查询全…
暂无图片
编程学习 ·

深入javascript计划六:深入浅出异步

什么是进程?进程是一个具有一定独立功能的程序关于某个数据集合的一次运行活动。它是操作系统动态执行的基本单元,在传统的操作系统中,进程既是基本的分配单元,也是基本的执行单元。通俗来讲就是:一个进程就是一个程序的运行实例(详细解释就是,启动一个程序的时候,操作…