CentOS 7.6安装配置MySQL 5.7 GTID双主复制+Keepalived实现高可用

栏目: 数据库 · Mysql · 发布时间: 6年前

一、 相关概念介绍:

1、 GTID 简介:

GTID Global Transaction ID ,全局事务 ID ,是一个已提交事务的编号,并且是一个全局唯一的编号。 MySQL 5.6 版本之后在主从复制类型上新增了 GTID 复制。通过 GTID 保证了每个在 master 节点上提交的事务在集群中有一个唯一的 ID ,这种方式强化了数据库的主从一致性、故障恢复及容错能力。

2、 GTID 工作原理:

GTID 用于在 binlog 中唯一标识一个事务。当事务提交时, MySQL 在写 binlog 时,会先写一个特殊的 binlog event ,类型为 GTID_Event ,指定下一个事务的 GTID ,然后再写事务的 binlog 。主从同步时 GTID_Event 和事务的 binlog 都会传递到 slave 节点, slave 节点在执行时也用同样的 GTID binlog ,这样主从同步后,就可通过 GTID 确定 slave 节点同步到的位置了。 GTID 使用 master_auto_position=1 代替了基于 master_log_file master_log_pos 的主从复制构建方式。

CentOS 7.6安装配置 <a href='https://www.codercto.com/topics/18746.html'>MySQL</a>  5.7 GTID双主复制+Keepalived实现高可用

3、 GTID 组成: GTID=server_uuid:transaction_id

(1) server_uuid MySQL 实例的唯一标识,每台主机的 server_uuid 都不同( 128 位),保存在数据目录下的 auto.cnf 文件中。 MySQL 第一次启动时创建 auto.cnf 文件,并生成 server_uuid ,之后 MySQL 再次启动时不会重复生成 server_uuid ,而是使用 auto.cnf 中的 server_uuid

(2) transaction_id :事务提交时由系统顺序分配的一个不会重复的序列号,代表了该实例上已经提交的事务数量,一般来说随着事务提交递增。

备注:使用 server_uuid:transaction_id 共同组成一个 GTID 的好处是,由于 server_uuid 唯一,即使一个集群内多个节点同时写入,也不会造成 GTID 冲突。

4、 GTID 使用限制:

(1) 不支持 create table ... select 语句

(2) 不支持针对临时表的操作,即 create | drop temporary table

(3)不 支持非事务存储引擎(如: MyISAM

(4) 不支持 sql_slave_skip_counter

5、 Keepalived 简介:

Keepalived VRRP 协议的软件实现,原生设计是为了高可用 IPVS 服务,可以实现如下功能:

(1) 基于 VRRP 协议完成地址流动

(2) VIP 地址所在的 IPVS 集群节点生成 IPVS 规则(在配置文件中预先定义)

(3) IPVS 集群的各 RS 做健康状态检测

(4) 基于脚本调用接口,通过执行脚本完成脚本中定义的功能,进而影响集群事务

Keepalived 官网: https://www.keepalived.org/

6、 Keepalived 架构图:

CentOS 7.6安装配置MySQL 5.7 GTID双主复制+Keepalived实现高可用

Keepalived 启动后,会生成 WatchDog Checkers VRRP 三个工作进程:

(1) WatchDog :负责监控 Checkers VRRP 进程

(2) Checkers :负责检测主机健康状态

(3) VRRP :负责当 master 节点上的服务不可用时,可通过 VRRP 将其切换到 backup 节点上

7、 VRRP 协议简介:

VRRP Virtual Router Redundancy Protocol ,虚拟路由冗余协议。 VRRP 是一种路由容错协议,也可称为备份路由协议。一个局域网内的所有主机都设置缺省路由,当网内主机发出的目的地址不在本网段时,报文将被通过缺省路由发往外部路由器,从而实现了主机与外部网络的通信。当缺省路由器 down 掉(即端口关闭)后,内部主机将无法与外部通信,如果路由器设置了 VRRP ,虚拟路由将启用备份路由器,从而实现全网通信。

8、 VRRP 相关术语简介:

(1) 虚拟路由器:由一个 master 路由器和多个 backup 路由器组成,主机将虚拟路由器当作默认网关

(2) VRID :虚拟路由器标识,有相同 VRID 的一组路由器构成一个虚拟路由器,取值范围为 0~255

(3) master 路由器:虚拟路由器中承担报文转发任务的路由器

(4) backup 路由器: master 路由器出现故障时,能代替 master 路由器工作的路由器

(5) 虚拟 IP 地址:虚拟路由器的 IP 地址,一个虚拟路由器可以拥有一个或多个 IP 地址

(6) 虚拟 MAC 地址:一个虚拟路由器拥有一个虚拟 MAC 地址,虚拟 MAC 地址的格式为 00-00-5E-00-01-{VRID} ,通常情况下,虚拟路由器回应 ARP 请求使用的是虚拟 MAC 地址,只有虚拟路由器做特殊配置时,才回应接口的真实 MAC 地址

(7) 优先级: VRRP 根据优先级来确定虚拟路由器中每台路由器的地位,取值范围为 0~255 ,数值越小表示优先级越低,数值越大表示优先级越高,当数值为 0 时,表示当前 master 节点放弃持有 VIP ,当数值为 255 时,表示当前 master 节点的优先级最高且已持有 VIP ,所以 VRRP 的优先级可选取值范围为 1~254

(8) 非抢占模式:如果 backup 路由器工作在非抢占模式下,则只要 master 路由器没有出现故障, backup 路由器即使随后被配置了更高的优先级也不会成为 master 路由器

(9) 抢占模式:如果 backup 路由器工作在抢占模式下,当它收到 VRRP 报文后,会将自己的优先级与通告报文中的优先级进行比较,如果自己的优先级比当前的 master 路由器的优先级高,就会主动抢占成为 master 路由器,否则将保持 backup 状态

9、 VRRP 工作流程:

(1) 虚拟路由器中的路由器根据优先级选举出 master master 路由器通过发送免费 ARP 报文,将自己的虚拟 MAC 地址通知给与它连接的设备或主机,从而承担报文转发任务;

(2) master 路由器周期性发送 VRRP 报文,以公布其配置信息(优先级等)和工作状态;

(3) 如果 master 路由器出现故障,虚拟路由器中的 backup 路由器将根据优先级重新选举出新的 master

(4) 虚拟路由器状态切换时, master 路由器由一台设备切换为另一台设备,新的 master 路由器只是简单地发送一个携带虚拟路由器的 MAC 地址和虚拟 IP 地址信息的免费 ARP 报文,这样就可以更新与它连接的主机或设备中的 ARP 相关信息。网络中的主机感知不到 master 路由器已经切换为另一台设备。

备注: backup 路由器的优先级高于 master 路由器时,由 backup 路由器的工作模式(抢占模式和非抢占模式)决定是否重新选举 master

二、 准备工作(如未特殊说明,在两个节点中分别执行如下操作):

1、 演示环境:

IP

操作系统

主机名

角色

软件包版本

安装方式

192.168.1.145

CentOS   7.6 x86_64

node1

master

Percona   Server 5.7.26-29-log

Keepalived 1.3.5-8

yum

192.168.1.146

CentOS   7.6 x86_64

node2

backup

Percona   Server 5.7.26-29-log

Keepalived 1.3.5-8

yum

备注: VIP 192.168.1.130

2、 集群架构:

CentOS 7.6安装配置MySQL 5.7 GTID双主复制+Keepalived实现高可用

3、 关闭 SELinux firewalld

4、配置 epel

5、 配置 percona 源:

# yum -y install https://repo.percona.com/yum/percona-release-latest.noarch.rpm

# yum repolist

# yum list | grep -i percona

6、 配置节点时间同步

7、 配置主机名

8、 配置 /etc/hosts 文件:

# vim /etc/hosts

192.168.1.145 node1

192.168.1.146 node2

三、 安装配置 Percona Server ,实现 GTID 双主复制(如未特殊说明,在两个节点中分别执行如下操作):

1、 安装 Percona Server # yum -y install Percona-Server-server-57

2、 修改 MySQL 配置文件:

# mv /etc/my.cnf /etc/my.cnf.bak

# update-alternatives --install /etc/my.cnf my.cnf "/etc/percona-server.cnf" 200

# vim /etc/percona-server.conf.d/mysqld.cnf

master 节点:

[mysqld]

port=3306

socket=/var/lib/mysql/mysql.sock

datadir=/var/lib/mysql

pid-file=/var/run/mysqld/mysqld.pid

log-error=/var/log/mysqld.log

lower_case_table_names=1

character_set_server=utf8mb4

collation_server=utf8mb4_general_ci

innodb_file_per_table=1

skip_name_resolve=1

slow_query_log=1

slow_query_log_file=mysql-slow.log

symbolic-links=0

explicit_defaults_for_timestamp=1

log_bin=mysql-bin

log_bin_index=mysql-bin.index

relay_log=relay-log

relay_ log_index=relay-log.index

sync_binlog=1

innodb_flush_log_at_trx_commit=1

binlog_format=row

gtid_mode=on

enforce_gtid_consistency=on

server_id=1

备注:

(1) backup 节点的 server_id=2

(2) MySQL 5.7 版本开始, gtid_mode 支持动态修改,可取值为:

a、 off :不支持 GTID 事务,生成的是匿名事务, slave 节点也只能应用匿名事务

b、 off_permissive :生成的是匿名事务, slave 节点可以应用匿名事务和 GTID 事务

c、 on_permissive :生成的是 GTID 事务, slave 节点可以应用匿名事务和 GTID 事务(此步骤操作完成后, master 节点的二进制日志就会变成 GTID 模式)

d、 on :支持 GTID 事务,生成的是 GTID 事务, slave 节点也只能应用 GTID 事务

注意:在生产环境中,可能有把传统复制改为 GTID 复制模式的需求, gtid_mode 虽然支持动态修改,但不支持跳跃式修改,比如从 on_permissive 修改为 off 是不可以的

(3) enforce_gtid_consistency 主要用于不让违反 GTID 的操作执行,可取值为:

a、 off :允许所有操作

b、 on :不允许有违反 GTID 的操作,且报错

c、 warn MySQL 5.7 版本新增,允许所有操作,但是违反 GTID 的操作会提示警告

(4) MySQL 5.6 版本中使用 GTID 复制模式,必须要开启参数 log_slave_updates=1 ,但在 MySQL 5.7 版本中使用 gtid_executed 系统表记录已经执行的 GTID 集合信息,所以就不用开启参数 log_slave_updates=1 ,开启的意义是把 relay log 中的日志内容再次记录到 slave 节点的本地 binlog

3、 初始化 MySQL 数据: # mysqld --initialize --user=mysql

备注:确保初始化前 /var/lib/mysql 目录为空,初始化完成后会在此目录中生成各类文件

4、 启动 MySQL 服务:

# systemctl start mysqld.service

# ss -tunlp | grep mysqld

# systemctl enable mysqld.service

# systemctl status mysqld.service

5、 查看 root@localhost 用户的初始密码: # grep password /var/log/mysqld.log

6、 配置 MySQL 安全向导: # mysql_secure_installation

7、 创建具有复制权限的用户:

master 节点:

# mysql -uroot -p

mysql> create user 'repluser1'@'192.168.1.%' identified by '123456';

mysql> grant replication slave on *.* to 'repluser1'@'192.168.1.%';

mysql> flush privileges;

mysql> show global variables like 'server_uuid';

备注:

(1) backup 节点创建的复制用户为 repluser2@192.168.1.% ,不能与 master 节点中的用户重名

(2) 内容和 /var/lib/mysql/auto.cnf 文件中 server-uuid 的值一致

8、 backup 节点使用具有复制权限的用户 repluser1 连接至 master 节点,并启动复制线程:

mysql> change master to master_host='192.168.1.145',master_user='repluser1',master_password='123456',master_port=3306, master_auto_position=1;

mysql> start slave;

备注:

(1) start slave 等同于分别执行 start slave io_thread start slave sql_thread

(2) stop slave 表示停止主从复制线程

(3) 重启 slave 节点所在的主机,复制线程会自动启动

mysql> show slave status\G

CentOS 7.6安装配置MySQL 5.7 GTID双主复制+Keepalived实现高可用

CentOS 7.6安装配置MySQL 5.7 GTID双主复制+Keepalived实现高可用

CentOS 7.6安装配置MySQL 5.7 GTID双主复制+Keepalived实现高可用

备注:

(1)只 有当 Slave_IO_Running Slave_SQL_Running 的值都为 Yes 时,复制线程才算启动成功

(2) Seconds_Behind_master 的值为 0 ,说明 backup 节点没有落后于 master 节点

(3) 复制时的详细信息记录在 backup 节点的错误日志 /var/log/mysqld.log

(4) backup 节点 start slave 时,会计算 show slave status Retrieved_Gtid_Set Executed_Gtid_Set 的并集,然后将此 GTID 并集发送给 master 节点。 master 节点会使用 backup 节点请求的 GTID 集合和 master 节点自身的 gtid_executed 比较,把 backup 节点 GTID 集合里缺失的事务全部发送给 backup 节点。如果 backup 节点缺失的 GTID 已经被 master 节点清除,则 backup 节点会提示 1236 错误, I/O 线程中断。

9、 master 节点使用具有复制权限的用户 repluser2 连接至 backup 节点,并启动复制线程:

mysql> change master to master_host='192.168.1.146',master_user='repluser2',master_password='123456',master_port=3306, master_auto_position=1;

mysql> start slave;

mysql> show slave status\G

CentOS 7.6安装配置MySQL 5.7 GTID双主复制+Keepalived实现高可用

CentOS 7.6安装配置MySQL 5.7 GTID双主复制+Keepalived实现高可用

CentOS 7.6安装配置MySQL 5.7 GTID双主复制+Keepalived实现高可用

10、 查看 GTID 相关信息:

mysql> show master status\G

master 节点:

CentOS 7.6安装配置MySQL 5.7 GTID双主复制+Keepalived实现高可用

backup 节点:

CentOS 7.6安装配置MySQL 5.7 GTID双主复制+Keepalived实现高可用

mysql> show slave hosts;

master 节点:

CentOS 7.6安装配置MySQL 5.7 GTID双主复制+Keepalived实现高可用

backup 节点:

CentOS 7.6安装配置MySQL 5.7 GTID双主复制+Keepalived实现高可用

mysql> show slave status\G

mysql> show global variables like '%gtid%';

master 节点:

CentOS 7.6安装配置MySQL 5.7 GTID双主复制+Keepalived实现高可用

backup 节点:

CentOS 7.6安装配置MySQL 5.7 GTID双主复制+Keepalived实现高可用

备注:

(1) gtid_executed :当前实例上已经执行过的 GTID 集合,实际上包含了所有记录到 binlog 中的事务。如果 set sql_log_bin=0 ,执行的事务不会生成 binlog 事件,也不会记录到 gtid_executed 中。执行 reset master 可以将变量 @@global.gtid_executed 清空。

(2) gtid_owned :当前实例正在执行中的 GTID ,以及对应的线程 ID

(3) gtid_purged :记录当前实例执行过,但已被清除的 GTID 集合。 gtid_purged gtid_executed 的子集。只有 gtid_executed 为空时才能手动设置 gtid_purged 变量,此时会将 gtid_executed 更新为和 gtid_purged 相同的值。

mysql> show variables like '%gtid%';

master 节点:

CentOS 7.6安装配置MySQL 5.7 GTID双主复制+Keepalived实现高可用

backup 节点:

CentOS 7.6安装配置MySQL 5.7 GTID双主复制+Keepalived实现高可用

备注: gtid_next session 会话级别的变量,如何产生下一个 GTID ,可取值为

(1) automatic :默认取值,在每次事务提交时自动生成新的 GTID ,它从当前已执行的 GTID 集合(即 gtid_executed )中,找一个大于 0 的、未使用的 transaction_id 最小值作为下个事务的 GTID ,同时在 binlog 的实际更新事务事件前插入一条 set gtid_next 事件,所以即使是同一个 server_uuid ,也不能通过 transaction_id 的大小来判断事务的顺序。

(2) anonymous :执行事务不会产生 GTID

(3) 显示指定 GTID :可以指定任意合法的 GTID ,但不能是当前 gtid_executed 中已经包含的 GTID

mysql> show processlist;

master 节点:

CentOS 7.6安装配置MySQL 5.7 GTID双主复制+Keepalived实现高可用

backup 节点:

CentOS 7.6安装配置MySQL 5.7 GTID双主复制+Keepalived实现高可用

11、 master 节点创建测试数据:

mysql> create database db;

mysql> use db;

mysql> create table tb(id int unsigned auto_increment primary key not null,age int not null);

mysql> desc tb;

mysql> insert into tb(age) values(35),(40);

mysql> select * from tb;

CentOS 7.6安装配置MySQL 5.7 GTID双主复制+Keepalived实现高可用

12、 backup 节点查看测试数据:

mysql> show databases like 'db';

CentOS 7.6安装配置MySQL 5.7 GTID双主复制+Keepalived实现高可用

mysql> select * from db.tb;

CentOS 7.6安装配置MySQL 5.7 GTID双主复制+Keepalived实现高可用

13、 backup 节点创建测试数据:

mysql> insert into db.tb(age) values(60),(80);

mysql> select * from db.tb;

CentOS 7.6安装配置MySQL 5.7 GTID双主复制+Keepalived实现高可用

14、 master 节点查看测试数据:

mysql> select * from db.tb;

CentOS 7.6安装配置MySQL 5.7 GTID双主复制+Keepalived实现高可用

四、 安装配置 Keepalived ,实现 MySQL 高可用(如未特殊说明,在两个节点中分别执行如下操作):

1、 安装 Keepalived # yum -y install keepalived

2、 定义检测 MySQL 服务的脚本:

# vim /etc/keepalived/chk_mysqld.sh

#!/bin/bash

n=$(ps -C mysqld --no-headers | wc -l)

if [ $n -eq 0 ]; then

systemctl stop keepalived.service

fi

# chmod +x /etc/keepalived/chk_mysqld.sh

# bash -n /etc/keepalived/chk_mysqld.sh

备注:通过 Keepalived 自带的服务监控功能和自定义脚本实现 MySQL 故障自动转移

3、 master 节点配置 Keepalived

# cd /etc/keepalived

# mv keepalived.conf{,.bak}

# openssl rand -base64 7 --> IDDf1j+yfw==

# vim keepalived.conf

global_defs {

notification_email {

root@localhost

}

notification_email_from node1@localhost

smtp_server 127.0.0.1

smtp_connect_timeout 30

router_id node1

vrrp_mcast_group4 224.1.100.88

}

vrrp_script chk_mysqld {

script "/etc/keepalived/chk_mysqld.sh"

interval 10

}

vrrp_instance VI_1 {

state BACKUP

nopreempt

interface ens160

virtual_router_id 50

priority 100

advert_int 5

authentication {

auth_type PASS

auth_pass IDDf1j+yfw==

}

virtual_ipaddress {

192.168.1.130

}

track_script {

chk_mysqld

}

}

备注:常用指令说明

(1) notification_email :收件箱

(2) notification_email_from :发件箱

(3) vrrp_mcast_group4 VRRP 多播地址,必须为 D 类地址,即可用 IP 范围为 224.0.0.0~239.255.255.255

(4) script :自定义检查脚本路径

(5) interval :自定义检查脚本的执行时间间隔,单位为秒

(6) vrrp_instance :配置虚拟路由器实例

(7) state MASTER BACKUP ,当前节点在此虚拟路由器上的初始状态,只能有一个为 MASTER ,其余的都应该为 BACKUP ,此处都需要配置为 BACKUP

(8) nopreempt :定义工作模式为非抢占模式,默认为抢占模式

(9) preempt_delay :抢占模式下,节点上线后触发新选举操作的延迟时长,单位为秒

(10) interface :绑定当前虚拟路由器使用的物理接口

(11) virtual_router_id :当前虚拟路由器的唯一标识,取值范围为 0~255 ,两个节点必须一致

(12)p riority :当前主机在此虚拟路由器中的优先级,取值范围为 0~255

(13) advert_int VRRP 通告心跳信息和优先级信息的时间间隔,单位为秒

(14) auth_type :认证类型

(15) auth_pass :认证密码,两个节点必须一致

(16) virtual_ipaddress VIP 地址

(17) 可通过命令 # man keepalived.conf 查看 keepalived.conf 配置文件的详细帮助文档

4、 backup 节点配置 Keepalived

# cd /etc/keepalived

# mv keepalived.conf{,.bak}

# vim keepalived.conf

global_defs {

notification_email {

root@localhost

}

notification_email_from node2@localhost

smtp_server 127.0.0.1

smtp_connect_timeout 30

router_id node2

vrrp_mcast_group4 224.1.100.88

}

vrrp_script chk_mysqld {

script "/etc/keepalived/chk_mysqld.sh"

interval 10

}

vrrp_instance VI_1 {

state BACKUP

nopreempt

interface ens160

virtual_router_id 50

priority 98

advert_int 5

authentication {

auth_type PASS

auth_pass IDDf1j+yfw==

}

virtual_ipaddress {

192.168.1.130

}

track_script {

chk_mysqld

}

}

备注: master backup 节点配置 Keepalived 时,要注意两个节点的 state 都要采用 BACKUP 状态,而且都是 nopreempt 非抢占模式,通过优先级决定哪个节点为 master 节点,避免出现冲突,发生脑裂现象

5、 master 节点启动 Keepalived 服务,并查看 VIP 信息:

# systemctl start keepalived.service

# systemctl enable keepalived.service

# systemctl status keepalived.service

# tail -f /var/log/messages

备注:从 Keepalived 启动完成之后的日志中可以得出, VRRP_Instance(VI_1) 首先变成 BACKUP 状态,由于 192.168.1.145 主机上的优先级高,状态会从 BACKUP 升级为 MASTER ,且 chk_mysqld 脚本执行成功, VIP 已经绑定在 master 节点的 ens160 网卡上

# ip a l

CentOS 7.6安装配置MySQL 5.7 GTID双主复制+Keepalived实现高可用

6、 backup 节点启动 Keepalived 服务:

# systemctl start keepalived.service

# systemctl enable keepalived.service

# systemctl status keepalived.service

# tail -f /var/log/messages

备注:从 Keepalived 启动完成之后的日志中可以得出, VRRP_Instance(VI_1) 变成 BACKUP 状态,时刻准备接管 master 节点上的 MySQL 服务,且 chk_mysqld 脚本执行成功,但并没有绑定 VIP

# ip a l

CentOS 7.6安装配置MySQL 5.7 GTID双主复制+Keepalived实现高可用

7、 测试使用 VIP 连接 master 节点:

(1) 在任意一台主机上安装 MySQL 客户端(此处为 192.168.1.144 ): # yum -y install mariadb

(2) master backup 任意一个节点中创建登录用户 root@192.168.1.% ,并赋予权限:

mysql> create user 'root'@'192.168.1.%' identified by '123456';

mysql> grant all on *.* to 'root'@'192.168.1.%';

mysql> flush privileges;

(3) 192.168.1.144 主机上使用 VIP 连接 master 节点,并使用 status 命令查看当前数据库状态:

# mysql -uroot -p -h192.168.1.130

CentOS 7.6安装配置MySQL 5.7 GTID双主复制+Keepalived实现高可用

8、 测试高可用:

(1) master 节点模拟 MySQL 服务宕机: # systemctl stop mysqld.service

(2) master 节点查看 Keepalived 服务、日志及 VIP 信息:

# systemctl status keepalived.service  # tail -f /var/log/messages  # ip a l

CentOS 7.6安装配置MySQL 5.7 GTID双主复制+Keepalived实现高可用

备注: master 节点已经自动停止 Keepalived 服务,且 VIP 没有绑定在 master 节点的 ens160 网卡上

(3) backup 节点查看 Keepalived 服务、日志及 VIP 信息:

# systemctl status keepalived.service  # tail -f /var/log/messages  # ip a l

CentOS 7.6安装配置MySQL 5.7 GTID双主复制+Keepalived实现高可用

备注: backup 节点的 Keepalived 已经变成 MASTER 状态,且 VIP 漂移至 backup 节点的 ens160 网卡上

(4) 192.168.1.144 主机上使用 VIP 连接 master 节点,并使用 status 命令查看当前数据库状态:

# mysql -uroot -p -h192.168.1.130

CentOS 7.6安装配置MySQL 5.7 GTID双主复制+Keepalived实现高可用

备注:客户端没有受到任何影响,依旧可以使用 VIP 连接已经变成 MASTER 状态的 backup 节点

(5) master 节点启动 MySQL 服务: # systemctl start mysqld.service

(6) master 节点启动 Keepalived 服务: # systemctl start keepalived.service

备注: master 节点的 Keepalived 已经变成 BACKUP 状态,且 chk_mysqld 脚本执行成功,但由于是非抢占模式,所以 VIP 依旧绑定在 backup 节点的 ens160 网卡上


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Out of their Minds

Out of their Minds

Dennis Shasha、Cathy Lazere / Springer / 1998-07-02 / USD 16.00

This best-selling book is now available in an inexpensive softcover format. Imagine living during the Renaissance and being able to interview that eras greatest scientists about their inspirations, di......一起来看看 《Out of their Minds》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

SHA 加密
SHA 加密

SHA 加密工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具