关于数据的一些资源及文档，包含关系型数据库，非关系型数据库等
MongoDB数据导入与导出导出工具：mongoexport概念：​ mongoDB中的mongoexport工具可以把一个collection导出成JSON格式或CSV格式的文件。可以通过参数指定导出的数据项，也可以根据指定的条件导出数据。语法：mongoexport -d dbname -c collectionname -o file --type json/csv -f field ​ 参数说明： ​ -d ：数据库名 ​ -c ：collection名 ​ -o ：输出的文件名 ​ --type ： 输出的格式，默认为json ​ -f ：输出的字段，如果-type为csv，则需要加上-f "字段名" 示例： ​ sudo mongoexport -d mongotest -c users -o /home/python/Desktop/mongoDB/users.json --type json -f "_id,user_id,user_name,age,status"数据导入：mongoimport语法： mongoimport -d dbname -c collectionname --file filename --headerline --type json/csv -f field ​ 参数说明： ​ -d ：数据库名 ​ -c ：collection名 ​ --type ：导入的格式默认json ​ -f ：导入的字段名 ​ --headerline ：如果导入的格式是csv，则可以使用第一行的标题作为导入的字段 ​ --file ：要导入的文件 示例： ​ sudo mongoimport -d mongotest -c users --file /home/mongodump/articles.json --type jsonMongoDB备份与恢复MongoDB数据库备份语法： mongodump -h dbhost -d dbname -o dbdirectory ​ 参数说明： ​ -h： MongDB所在服务器地址，例如：127.0.0.1，当然也可以指定端口号：127.0.0.1:27017 ​ -d： 需要备份的数据库实例，例如：test ​ -o： 备份的数据存放位置，例如：/home/mongodump/，当然该目录需要提前建立，这个目录里面存放该数据库实例的备份数据。 2、实例： ​ sudo rm -rf /home/momgodump/ ​ sudo mkdir -p /home/momgodump ​ sudo mongodump -h 192.168.17.129:27017 -d itcast -o /home/mongodump/ ​ \-MongoDB数据库恢复语法： mongorestore -h dbhost -d dbname --dir dbdirectory ​ 参数或名： ​ -h： MongoDB所在服务器地址 ​ -d： 需要恢复的数据库实例，例如：test，当然这个名称也可以和备份时候的不一样，比如test2 ​ --dir： 备份数据所在位置，例如：/home/mongodump/itcast/ ​ --drop： 恢复的时候，先删除当前数据，然后恢复备份的数据。就是说，恢复后，备份后添加修改的数据都会被删除，慎用！ 2、实例： mongorestore -h 192.168.17.129:27017 -d itcast_restore --dir /home/mongodump/itcast/
MYSQL命令行输入密码警告问题"mysql: [Warning]"解决方案
1.1 问题显示[root@localhost ~]# mysql -uroot -p1234567 mysql: [Warning] Using a password on the command line interface can be insecure.1.2 解决方法1.2.1 方法一1、将密码写入到主配置文件中[root@localhost ~]# vim /etc/my.cnf [mysqldump] user=root password=1234567 [mysql] user=root password=12345672、直接使用命令登录，再也无需输入账号密码[root@localhost ~]# mysql Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 10 Server version: 5.7.18-log Source distribution Copyright (c) 2000, 2017, 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> 1.2.2 方法二1、自动配置MYSQL密文密码该操作会在用户家目录下生成一个隐藏文件".mylogin.cnf"，里面记录了MYSQL的密文的密码，只要配置了以后，我们也是直接使用命令登录，再也无需输入账号密码了，如果你想取消，删除此文件即可。[root@localhost ~]# mysql_config_editor set --user=root --host=localhost --port=3306 --password Enter password: 输入密码2、直接使用命令登录，再也无需输入账号密码[root@localhost ~]# mysql Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 11 Server version: 5.7.18-log Source distribution Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved Oracle is a registered trademark of Oracle Corporation and/or it 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> 1.2.3 方法三1、直接使用命令登录，屏蔽错误信息由于告警信息是标准错误，我们可以将标准错误的输出信息输出为空。[root@localhost ~]# mysql -uroot -p1234567 2>/dev/null Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 36 Server version: 5.7.18-log Source distribution Copyright (c) 2000, 2017, 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.
基于新版本 v1.6.2，centOSCLI使用HTTPAPI通过8086（默认的，可以在配置文件中修改）端口与influxDB直接交互，influx命令在所有influxDB的包中都默认包含注意：在InfluxDB当中，并没有表（table）这个概念，取而代之的是MEASUREMENTS，MEASUREMENTS的功能与传统数据库中的表一致，因此我们也可以将MEASUREMENTS称为InfluxDB中的表启动influxinflux命令在/usr/bin/influxCODE[root@test25 ~]# find / -name influx/usr/bin/influx[root@test25 ~]# 启动influxdservice influxdb startinfluxdCODE[root@test25 ~]# service influxdb start[root@test25 ~]# influx参数CODE[root@test25 ~]# influx --helpUsage of influx: -version Display the version and exit.-host 'host name' Host to connect to.-port 'port #' Port to connect to.-socket 'unix domain socket' Unix socket to connect to.-database 'database name' Database to connect to the server.-password 'password' Password to connect to the server. Leaving blank will prompt for password (--password '').-username 'username' Username to connect to the server.-ssl Use https for requests.-unsafeSsl Set this when connecting to the cluster using https and not use SSL verification.-execute 'command' Execute command and quit.-format 'json|csv|column' Format specifies the format of the server responses: json, csv, or column.-precision 'rfc3339|h|m|s|ms|u|ns' Precision specifies the format of the timestamp: rfc3339, h, m, s, ms, u or ns.-consistency 'any|one|quorum|all' Set write consistency level: any, one, quorum, or all-pretty Turns on pretty print for the json format.-import Import a previous database export from file-pps How many points per second the import will allow. By default it is zero and will not throttle importing.-path Path to file to import-compressed Set to true if the import file is compressed Examples:# Use influx in a non-interactive mode to query the database "metrics" and pretty print json: $ influx -database 'metrics' -execute 'select * from cpu' -format 'json' -pretty # Connect to a specific database on startup and set database context: $ influx -database 'metrics' -host 'localhost' -port '8086'[root@test25 ~]#参数 描述-version 显示版本号并退出-host ‘host name’ 连接到远程主机-port ‘port #’ 连接远程主机端口-socket ‘unix domain socket’ 连接unix套接字-database ‘database name’ 连接到服务器的数据库-password ‘password’ 连接到服务器的密码-username ‘username’ 连接到服务器的用户名-ssl 使用https请求-unsafeSsl 使用https连接到集群时，不要使用SSL验证。-execute ‘command’ 执行命令并退出-format ‘json|csv|column’ 格式指定了服务器响应的格式：json、csv或column.默认是column-precision ‘rfc3339|h|m|s|ms|u|ns’ 指定时间戳的格式精度: rfc3339 (YYYY-MM-DDTHH:MM:SS.nnnnnnnnnZ), h (hours), m (minutes), s (seconds), ms (milliseconds), u (microseconds), ns (nanoseconds)..-consistency ‘any|one|quorum|all’ 设置写一致性级别: any, one, quorum, or all-pretty 打开美化json打印-import 导入备份的数据库文件-pps 导入允许每秒多少个点。默认情况下，它是零，不会限制进口-path import的文件路径-compressed 如果导入文件被压缩，则设置为true给出一些demo显示版本 -versionCODE[root@test25 ~]# influx -versionInfluxDB shell version: 1.6.2连接指定主机 -hostCODE[root@test25 ~]# influx -host localhostConnected to http://localhost:8086 version 1.6.1InfluxDB shell version: 1.6.2quit用使用端口连接主机 -portCODE[root@test25 ~]# influx -host localhost -port 8086Connected to http://localhost:8086 version 1.6.1InfluxDB shell version: 1.6.2quit连接指定数据库 -databaseCODE[root@test25 ~]# influx -host localhost -port 8086 -database mydbConnected to http://localhost:8086 version 1.6.1InfluxDB shell version: 1.6.2quit使用指定的用户名和密码(添加用户见下面) -password -usernameCODE[root@test25 ~]# influx -host localhost -port 8086 -database mydb -username 'yueling' -password '123456'Connected to http://localhost:8086 version 1.6.1InfluxDB shell version: 1.6.2添加用户：yueling和管理员用户lingyueCODE[root@test25 ~]# influx -database 'mydb' -host 'localhost' -port '8086'Connected to http://localhost:8086 version 1.6.1InfluxDB shell version: 1.6.2show usersuser admin---- -----create user "yueling" with password '123456'create user "lingyue" with password '123456' with all privilegesshow usersuser admin---- -----yueling falselingyue true执行命令并返回 -executeCODE[root@test25 ~]# influx -host localhost -port 8086 -database mydb -username 'yueling' -password '123456' -execute 'select * from cpu_load_short'name: cpu_load_shorttime direction host region value---- --------- ---- ------ -----1422568543702900257 in server01 us-west 21422568543702900257 server02 us-west 0.551434055562000000000 server01 us-west 0.641536579271011551389 server02 0.67[root@test25 ~]# 指定返回格式 -formatCODE[root@test25 ~]# influx -host localhost -port 8086 -database mydb -username 'yueling' -password '123456' -execute 'select * from cpu_load_short' -format json{"results":[{"series":[{"name":"cpu_load_short","columns":["time","direction","host","region","value"],"values":[[1422568543702900257,"in","server01","us-west",2],[1422568543702900257,null,"server02","us-west",0.55],[1434055562000000000,null,"server01","us-west",0.64],[1536579271011551389,null,"server02",null,0.67]]}]}]}[root@test25 ~]# influx -host localhost -port 8086 -database mydb -format json Connected to http://localhost:8086 version 1.6.1InfluxDB shell version: 1.6.2use mydbUsing database mydbselect * from cpu_load_short{"results":[{"series":[{"name":"cpu_load_short","columns":["time","direction","host","region","value"],"values":[[1422568543702900257,"in","server01","us-west",2],[1422568543702900257,null,"server02","us-west",0.55],[1434055562000000000,null,"server01","us-west",0.64],[1536579271011551389,null,"server02",null,0.67]]}]}]}时间戳精度 -precisionCODE[root@test25 ~]# influx -host localhost -port 8086 -database mydb -username 'yueling' -password '123456' -execute 'select * from cpu_load_short' -format column -precision msname: cpu_load_shorttime direction host region value---- --------- ---- ------ -----1422568543702 in server01 us-west 21422568543702 server02 us-west 0.551434055562000 server01 us-west 0.641536579271011 server02 0.67使用json美化输出 -prettyCODE[root@test25 ~]# influx -host localhost -port 8086 -database mydb -username 'yueling' -password '123456' -execute 'select * from cpu_load_short' -format json -pretty{"results": [ { "series": [ { "name": "cpu_load_short", "columns": [ "time", "direction", "host", "region", "value" ], "values": [ [ 1422568543702900257, "in", "server01", "us-west", 2 ], [ 1422568543702900257, null, "server02", "us-west", 0.55 ], [ 1434055562000000000, null, "server01", "us-west", 0.64 ], [ 1536579271011551389, null, "server02", null, 0.67 ] ] } ] } ]}使用文件导入数据 -import导入的文件包含两个章节DDL：Data Definition LanguageDML：Data Manipulation Language注意文件里的时间戳，自己试验的时候记得修改使符合规则 比如当前时间戳 date +’%s’CODE[root@test25 ~]# cat dataarr.txtDDLCREATE DATABASE piratesCREATE RETENTION POLICY oneday ON pirates DURATION 1d REPLICATION 1DMLCONTEXT-DATABASE: piratesCONTEXT-RETENTION-POLICY: onedaytreasures,captain_id=dread_pirate_roberts value=801 1536658695treasures,captain_id=flint value=29 1536658695[root@test25 ~]#[root@test25 ~]# influx -import -path=dataarr.txt -precision=s2018/09/11 17:40:39 Processed 2 commands2018/09/11 17:40:39 Processed 2 inserts2018/09/11 17:40:39 Failed 0 inserts[root@test25 ~]#如果是压缩的文件 要配合 -compressedCODE[root@test25 ~]# gzip dataarr.txt[root@test25 ~]# lsanaconda-ks.cfg dataarr.txt.gz ……[root@test25 ~]# influx -import -path=dataarr.txt.gz -precision=s -compressed2018/09/11 17:50:47 Processed 2 commands2018/09/11 17:50:47 Processed 2 inserts2018/09/11 17:50:47 Failed 0 inserts[root@test25 ~]#influx命令CODE[root@test25 ~]# influxConnected to http://localhost:8086 version 1.6.1InfluxDB shell version: 1.6.2查看influx内部命令用法CODEhelpUsage: connect <host:port> connects to another node specified by host:port auth prompts for username and password pretty toggles pretty print for the json format chunked turns on chunked responses from server chunk size <size> sets the size of the chunked responses. Set to 0 to reset to the default chunked size use <db_name> sets current database format <format> specifies the format of the server responses: json, csv, or column precision <format> specifies the format of the timestamp: rfc3339, h, m, s, ms, u or ns consistency <level> sets write consistency level: any, one, quorum, or all history displays command history settings outputs the current settings for the shell clear clears settings such as database or retention policy. run 'clear' for help exit/quit/ctrl+d quits the influx shell show databases show database names show series show series information show measurements show measurement information show tag keys show tag key information show field keys show field key information A full list of influxql commands can be found at: https://docs.influxdata.com/influxdb/latest/query_language/spec/命令 描述connect host:port 通过host:port连接指定服务器auth 提示输入用户名和密码pretty 开启/关闭美化json输出chunked 开启/关闭服务器响应chunk size 设置服务器响应的大小，设置为0则重置返回大小use 切换数据库format 指定输出格式: json, csv, or column（默认是column，当然启动的时候可以用-format指定）precision 时间戳精度: rfc3339 (YYYY-MM-DDTHH:MM:SS.nnnnnnnnnZ), h (hours), m (minutes), s (seconds), ms (milliseconds), u (microseconds), ns (nanoseconds)consistency 设置并发级别: any, one, quorum, or allhistory 显示执行命令历史，类似linux的historysettings 输出当前的设置项clear 清除数据库设置或者保留策略 clear [ database | db | retention policy | rp ]exit/quit/ctrl+d 退出influxshow databases 显示所有数据库的名称show series 显示所有series信息show measurements 显示所有指标信息，相当于表show tag keys 显示所有tag信息show field keys 显示所有field信息insert 写入数据insert intoinflux命令的一些示例连接服务器、认证 connect和authCODE[root@test25 ~]# influx -database 'mydb' -host 'localhost' -port '8086'Connected to http://localhost:8086 version 1.6.1InfluxDB shell version: 1.6.2connect localhost:8086authusername: lingyuepassword:显示设置 settingsCODEsettingsSetting Value-------- --------Host localhost:8086Username Database mydbRetentionPolicy Pretty falseFormat columnWrite Consistency allChunked trueChunk Size 0显示数据 show databasesCODEshow databasesname: databasesnamejmeter_internaltestmydbpirates切换database use databaseNameCODEuse mydbUsing database mydb显示指标 show measurementsCODEshow measurementsname: measurementsnamecpu_load_short显示tagCODEshow tag keysname: cpu_load_shorttagKeydirectionhostregion显示seriesCODEshow serieskeycpu_load_short,direction=in,host=server01,region=us-westcpu_load_short,host=server01,region=us-westcpu_load_short,host=server02cpu_load_short,host=server02,region=us-west显示filedCODEshow field keysname: cpu_load_shortfieldKey fieldType-------- ---------value float指定输出格式CODEformat jsonshow databases{"results":[{"series":[{"name":"databases","columns":["name"],"values":[["jmeter"],["_internal"],["test"],["mydb"],["pirates"]]}]}]}格式化json输出CODEprettyPretty print enabledshow databases{"results": [ { "series": [ { "name": "databases", "columns": [ "name" ], "values": [ [ "jmeter" ], [ "_internal" ], [ "test" ], [ "mydb" ], [ "pirates" ] ] } ] } ]}显示执行命令历史 historyCODEhistorycreate database testshow databases……format jsonshow databasesprettyshow databasesinsertInfluxDB中没有显式的新建表的语句，只能通过insert数据的方式来建立新表增加数据采用insert的方式，要注意的是 InfluxDB的insert中，表名与数据之间用逗号（,）分隔，tag和field之间用 空格分隔，多个tag或者多个field之间用逗号（,）分隔CODEINSERT treasures,captain_id=pirate_king value=2SHOW RETENTION POLICIES ON mydbname duration shardGroupDuration replicaN default---- -------- ------------------ -------- -------autogen 0s 168h0m0s 1 trueINSERT INTO autogen treasures,captain_id=pirate_king value=2select 查询数据和sql结构一致CODEselect * from cpu_load_shortname: cpu_load_shorttime direction host region value---- --------- ---- ------ -----1422568543702900257 in server01 us-west 21422568543702900257 server02 us-west 0.551434055562000000000 server01 us-west 0.641536579271011551389 server02 0.67drop 删除measurement和databaseCODEshow databasesname: databasesnamejmeter_internaltestmydbpiratesuse testUsing database testshow measurementsname: measurementsnamedisk_freedrop measurement disk_freeshow measurementsdrop database testshow databasesname: databasesnamejmeter_internalmydbpirates
Telegraf+InfluxDB+Grafana+Docker搭建服务器监控平台写在前面因为监控Docker的事情头疼了很久,终于找到了这个很适合业务需求的方案.(我知道你们肯定想说,那么多监控docker的方案都不能使用吗?答案是:可能会使用,但我是FW)要搭建服务器监控平台，总共分三步：第一步，数据采集；第二步，数据存储；第三步，数据可视化。其中，数据存储连接数据采集与数据可视化，是非常重要的中间环节。本文选择了时序数据库InfluxDB。InfluxDB是一款优秀的时间序列数据库，适合存储设备性能、日志、物联网传感器等带时间戳的数据。能轻松处理高写入和高查询负载（数据采集与数据可视化非常常见的场景）。具体介绍请参阅InfluxDB官方文档：https://docs.influxdata.com/influxdb/。数据采集方面有非常多的选择，你甚至可以自己开发一个。这里为了方便直接选择Influxdata官方出品的采集工具Telegraf ，毕竟是全家桶产品。Telegraf详情介绍：https://docs.influxdata.com/telegraf。可视化方面选择了超高颜值、功能强大的开源可视化利器Gafana，具体颜值有多高，功能有多强大，本文就不再赘述了，直接上官网：https://grafana.com/grafana/dashboards。原博主甚至还给Grafana做了一下中文的本地汉化：https://github.com/WangHL0927/grafana-chinese。Grafana从早期版本就对InfluxDB有着完善的支持。最终平台的方案：Telegraf(数据采集)+InfluxDB（数据存储）+Grafana（数据可视化）==>Docker(监控Docker相关业务)。设计部署InfluxDB与Grafana直接使用官方容器进行部署，方便快捷。服务器需先安装Docker，具体步骤参考本站文章CentOS7安装Docker。当然你也可以选择我下面给出的一键安装Docker.适用范围Centos 7.2-7.8,需提前准备epel源curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun1 部署InfluxDBdocker pull influxdb:1.6.5 docker run -d -p 8086:8086 --name=influxdb influxdb:1.6.5以上命令dcoker会自动从仓库下载最新版本的influxdb镜像，后台运行一个名为influxdb的容器并映射主机8086端口到容器8086端口。若想将数据存储到宿主机而非容器内，可使用以下命令启动挂载本地目录到容器内。# $pwd为当前工作目录，可替换为其它宿主机目录 docker run -d -p 8086:8086 -v $PWD:/var/lib/influxdb --name=influxdb influxdb启动InfluxDB容器后，通过http接口访问进行测试。curl -G http://localhost:8086/query --data-urlencode "q=show databases"若influxdb运行正常，则会返回如下结果：# 链接查询参数为show databases 数据库会返回所有的数据库名，新安装的influxdb默认只有一个"_internal" # 数据库。 {"results":[{"statement_id":0,"series":[{"name":"databases","columns":["name"],"values":[["_internal"],["telegraf"]]}]}]}influxdb容器管理# 启动 docker start influxdb # 停止 docker stop influxdb # 重启 docker restart influxdb2 安装Telegraf下载安装Telegraf为了方便配置调试，选择直接在宿主机安装。# 以CentOS为例 # 下载Telegraf wget https://dl.influxdata.com/telegraf/releases/telegraf-1.6.3-1.x86_64.rpm # 安装Telegraf sudo yum localinstall telegraf-1.6.3-1.x86_64.rpm配置Telegraf用户可修改Telegraf配置文件进行采集项的配置。配置文件默认位于/etc/telegraf/telegraf.conf。在本文方案中，需要配置数据输出项（输出到influxdb），其它项使用telegraf默认即可。按照示例配置influxdb url、database名称############################################################################### # OUTPUT PLUGINS # ############################################################################### # Configuration for sending metrics to InfluxDB outputs.influxdb ## The full HTTP or UDP URL for your InfluxDB instance. ## ## Multiple URLs can be specified for a single cluster, only ONE of the ## urls will be written to each interval. # urls = ["unix:///var/run/influxdb.sock"] # urls = ["udp://127.0.0.1:8089"] # influxdb http地址，由于是宿主机直接安装，直接访问本地8086端口即可。 urls = ["http://127.0.0.1:8086"] ## The target database for metrics; will be created as needed. # 数据库名，不存在会自动创建，默认"telegraf" database = "telegraf" ## If true, no CREATE DATABASE queries will be sent. Set to true when using ## Telegraf with a user without permissions to create databases or when the ## database already exists. # 跳过创建数据库 skip_database_creation = false ## Name of existing retention policy to write to. Empty string writes to ## the default retention policy. # retention_policy = "" ## Write consistency (clusters only), can be: "any", "one", "quorum", "all" # write_consistency = "any" ## Timeout for HTTP messages. # 超时时间 timeout = "5s" ## HTTP Basic Auth # username = "telegraf" # password = "metricsmetricsmetricsmetrics" ## HTTP User-Agent # user_agent = "telegraf" ## UDP payload size is the maximum packet size to send. # udp_payload = 512 ## Optional SSL Config # ssl_ca = "/etc/telegraf/ca.pem" # ssl_cert = "/etc/telegraf/cert.pem" # ssl_key = "/etc/telegraf/key.pem" ## Use SSL but skip chain & host verification # insecure_skip_verify = false ## HTTP Proxy override, if unset values the standard proxy environment ## variables are consulted to determine which proxy, if any, should be used. # http_proxy = "http://corporate.proxy:3128" ## Additional HTTP headers # http_headers = {"X-Special-Header" = "Special-Value"} ## HTTP Content-Encoding for write request body, can be set to "gzip" to ## compress body or "identity" to apply no encoding. # content_encoding = "identity" ## When true, Telegraf will output unsigned integers as unsigned values, ## i.e.: "42u". You will need a version of InfluxDB supporting unsigned ## integer values. Enabling this option will result in field type errors if ## existing data has been written. # influx_uint_support = false inputs.docker ###指定本机docker运行时sock文件 endpoint = "unix:///var/run/docker.sock" ###设置为true以收集集群度量 ###如果使用docker-compose或者docker-swarm需要用到 gather_services = false ###排除容器名等配置 container_name_include = [] container_name_exclude = [] ###Docker统计信息超时时间 timeout = "5s" ###包含和排除docker标签,空数组包含所有标签 ###哪些环境变量，我们应该作为一个标签使用＃tag_env = “ JAVA_HOME ”，“ HEAP_SIZE ” ] ＃＃可选TLS配置＃ tls_ca = “/etc/telegraf/ca.pem” ＃ TLS_CERT = “/etc/telegraf/cert.pem” ＃ TLS_KEY = “/etc/telegraf/key.pem” docker_label_include = [] docker_label_exclude = [] ###每个容器的IO报告 perdevice = true ###每个容器的总IO和网络统计信息 total = falseTelegraf提供的采集内容非常丰富，将相应配置项取消注释并重启Telegraf即可生效。其它更多配置项请参考Telegraf官方文档：https://docs.influxdata.com/telegraf启动Telegraf 注意telegraf权限问题 确保telegraf程序正常访问docker.sock # 启动 usermod -aG docker telegraf systemctl start telegraf # 停止 systemctl stop telegraf # 重启 systemctl restart telegraf # 查看服务状态 systemctl status telegraf部署GrafanaGrafana同样采用官方docker镜像进行快速部署。docker run -d -p 3000:3000 --name=grafana grafana/grafana以上命令docker会拉取最新版grafana镜像，运行名为grafana的容器，并映射宿主机3000端口。初次启动，grafana会创建数据库，时间稍长，稍后即可访问http://localhost:3000打开grafana登录页面。输入默认用户名密码登录（admin）。你可以自行创建仪表盘,当然也可以引用Grafana官网已经创建好的模板,毕竟你走过的路可能别人早就走过好几遍了.Grafana绘图示例按照主页向导完成初次配置。1 添加数据源点击添加数据源，按照下图配置选择influxdb添加一个influxdb数据源。url需配置成正确的宿主机ip和端口（防火墙需放行8086），若不想暴露数据库端口，可换成influxdb容器的ip地址（需自行进入容器查看，容器重启后可能会发生变化）避免数据库暴露至公网。InfluxDB Details需填写数据名（默认telegraf）、用户名和密码（默认均为root）。填写完成后，点击Save&Test按钮，若访问正常，会出现Data source is working提示，否则请检查配置内容以及网络（防火墙）。添加仪表板返回主页，点击添加仪表板按钮添加新仪表板，点击Graph创建一个Graph Panel。点击标题展开菜单，选择Edit进入面板编辑。选择Metrics选项卡配置面板数据。如图示配置可显示一条CPU-total的数据曲线。还可添加多条查询，同时在一个panel显示多条曲线。配置完成后点击上方保存按钮保存仪表板。Grafana详细的使用方法请参考官方文档：http://docs.grafana.org/或其它教程。引用Grafana官网模板就写到这里.欢迎大佬补充.
1.备份数据1.1 创建备份仓库$ curl -u elastic:123456 -XPOST '192.168.1.1:9200/_snapshot/hsbc_backup' -H 'Content-Type: application/json' -d '{ "type": "fs", "settings": { "location": "/alidata1/admin/backup/elasticsearch", "compress": true, "chunk_size": "1g", "max_snapshot_bytes_per_sec": "50m", "max_restore_bytes_per_sec": "50m"}}' 11.2 备份脚本$ cat /alidata1/admin/scripts/elasticsearch/es_bak_del.sh #!/bin/bash ## define vars es_url="http://192.168.1.1:9200" es_bak_repo="hsbc_backup" es_user="elastic" es_pass="123456" es_bak_date=`date +'%Y-%m-%d-%H'` echo -e "\n =========== $es_bak_date ============" ## bak curl -u ${es_user}:${es_pass} -XPUT "${es_url}/_snapshot/${es_bak_repo}/es_bak_${es_bak_date}?wait_for_completion=true" echo "" ##sleep sleep 10 ##del 最后的60: 定时任务 每4小时备份一次 一天备份6次 数据保留10天 es_del_snapshots=`curl -u ${es_user}:${es_pass} -s -XGET "${es_url}/_snapshot/${es_bak_repo}/_all" | python -m json.tool| python -c 'import json; import sys; input = sys.stdin.read(); result = [x["snapshot"] for x in json.loads(input)["snapshots"]]; print("\n".join(result[:-60]));'` for es_del_snapshot in ${es_del_snapshots}; do echo "===========$es_del_snapshot del" curl -u ${es_user}:${es_pass} -s -XDELETE "${es_url}/_snapshot/${es_bak_repo}/${es_del_snapshot}" echo "" done1.3 创建定时任务$ crontab -e 0 */4 * ** /bin/bash /alidata1/admin/scripts/elasticsearch/es_bak_del.sh >> /alidata1/admin/logs/crontab/es_bak/crontab.log 2>&1 122.数据还原目的：将某一个备份的文件还原到192.168.1.1$ cat es_restore.sh #!/bin/bash set -e ## define vars es_url="http://192.168.1.1:9200" es_bak_repo="hsbc_backup" es_restore_snapshots="es_bak_20200811" es_user="elastic" es_pass="123456" ##(1)获取备份文件中存在的索引 es_get_snapshots_index=`curl -u ${es_user}:${es_pass} -s -XGET "${es_url}/_snapshot/${es_bak_repo}/${es_restore_snapshots}" | python -m json.tool| python -c 'import json; import sys; input = sys.stdin.read(); result=json.loads(input); indices = result["snapshots"][0]["indices"]; sys.stdout.write(" ".join([i for i in indices]));'` ##(2)将备份文件中存在的索引删除 然后恢复 for index in ${es_get_snapshots_index}; do if [ ${index} == ".security-6" ]; then # 如果索引为 .security-6 则不能删除 continue fi # 判断索引是否存在 res=`curl -s -u ${es_user}:${es_pass} -XGET "${es_url}/${index}"| grep "error" |grep 404|awk '{print $1}'` if [ -z ${res} ] ; then #如果存在则删除索引 curl -s -u ${es_user}:${es_pass} -XDELETE ${es_url}/${index} echo -e "\ndelete index data : ${index} " fi #数据恢复 echo -e "data restore : ${index}\n" curl -s -u ${es_user}:${es_pass} -XPOST "${es_url}/_snapshot/${es_bak_repo}/${es_restore_snapshots}/_restore" -H 'Content-Type: application/json' -d '{"indices": "'${index}'"}' done
Redis-5.x第1章 关系型与非关系型CODE 关系型： mysql oracle 非关系型：redis mongo ES 第2章 Redis重要特性SWIFT 1.速度快 c语言写的 代码优雅 单线程架构 2.支持多种数据结构 字符串，哈希，列表，集合，有序集合，地理位置 3.丰富的功能 天然计数器 健过期功能 消息队列 4.支持客户端语言多 php,java,python 5.数据持久化 所有的数据都运行在内存中 支持2种格式持久化数据AOF RDB AOF&RDB 6.自带多种高可用架构 主从 哨兵 集群第3章 redis应用场景CODE 1.缓存-键过期时间 把session会话存在redis,过期删除 缓存用户信息，缓存Mysql部分数据，用户先访问redis，redis没有再访问mysql，然后回写给redis 商城优惠卷过期时间 2.排行榜-列表&有序集合 热度/点击数排行榜 直播间礼物积分排行 3.计数器-天然支持计数器 帖子浏览数 视频播放数 评论数 点赞/踩 4.社交网络-集合 粉丝 共同好友 兴趣爱好 标签 5.消息队列-发布订阅 配合ELK缓存收集来的日志第4章 Redis安装部署1.redis官网CPP https://redis.io/2.版本选择CSS 2.x very old 3.x redis-cluster 4.x 混合持久化 5.x 新增加了流处理类型 最新稳定版 3.规划目录KOTLIN /data/soft 下载目录 /opt/redis_6379/{conf,logs,pid} 安装目录,日志目录,pid目录,配置目录 /data/redis_6379/ 数据目录4.安装命令GO mkdir /data/soft -p cd /data/soft wget http://download.redis.io/releases/redis-5.0.7.tar.gz tar xf redis-5.0.7.tar.gz -C /opt/ ln -s /opt/redis-5.0.7 /opt/redis cd /opt/redis make make install 5.配置文件BASH mkdir -p /opt/redis_6379/{conf,pid,logs} mkdir -p /data/redis_6379 cat >/opt/redis_6379/conf/redis_6379.conf<< EOF daemonize yes bind 127.0.0.1 10.0.0.51 port 6379 pidfile /opt/redis_6379/pid/redis_6379.pid logfile /opt/redis_6379/logs/redis_6379.log EOF6.启动命令CODE redis-server /opt/redis_6379/conf/redis_6379.conf7.检查RUBY ps -ef|grep redis netstat -lntup|grep 63798.连接redis终端CSS [root@db01 ~]# redis-cli 127.0.0.1:6379> 127.0.0.1:6379> set k1 v1 OK 127.0.0.1:6379> get k1 "v1" 127.0.0.1:6379>9.关闭命令BASH kill pkill redis-cli >SHUTDOWN - redis-cli shutdown10.system启动配置CSHARP groupadd -g 1000 redis useradd -u 1000 -g 1000 -M -s /sbin/nologin chown -R redis:redis /data/redis* chown -R redis:redis /opt/redis* cat >/usr/lib/systemd/system/redis.service<<EOF [Unit] Description=Redis persistent key-value database After=network.target After=network-online.target Wants=network-online.target [Service] ExecStart=/usr/local/bin/redis /opt/redis_6379/conf/redis_6379.conf --supervised systemd ExecStop=/usr/local/bin/redis-cli -h $(ifconfig eth0|awk 'NR==2{print $2}') -p 6379 shutdown Type=notify User=redis Group=redis RuntimeDirectory=redis RuntimeDirectoryMode=0755 [Install] WantedBy=multi-user.target EOF systemctl daemon-reload systemctl start redis第5章 Redis全局命令全局命令是指对所有数据类型都通用的命令0.redis数据格式CSHARP key:value 键:值1.写入测试keyBASH set k1 v1 set k2 v2 set k3 v32.查看所有的key！！！危险命令！！！此操作未满30岁禁止请在家人的看管下执行CODE keys *3.查看有多少个keyCODE DBSIZE4.查看某个Key是否存在CODE EXISTS k1 状态码： 0 表示这个key不存在 1 表示这个key存在 N 表示存在N个key5.删除keyCODE DEL k1 DEL k1 k2 状态码： 0 表示这个key不存在 1 表示这个key存在，并且删除成功了 N 表示N个key存在，并且删除成功了N个key6.键过期设置过期时间CODE EXPIRE k1 10 状态码： 0 这个key不存在 1 这个key存在，并且设置过期时间成功查看keys是否过期CODE TTL k1 状态码： -1 这个key存在,并且没有设定存活周期，永不过期 -2 这个key不存在 N 这个key存在，并且在N秒后过期取消过期时间：BASH 第一种方法： PERSIST k1 第二种方法： set k1 v1 结论： 过期后的key会被直接删除第6章 字符串操作1.设置一个keyBASH set k1 v12.查看一个keyCSHARP get k13.设置多个keyCODE MSET k1 v1 k2 v2 k3 v3 k4 v44.查看多个keyCODE MGET k1 k2 k3 k45.天然计数器CODE 加1: SET k1 1 INCR k1 GET k1 加N： INCRBY k1 100 减1: INCRBY k1 -1 减N: INCRBY k1 -100第7章 列表操作1.插入列表CODE LPUSH: 从列表左侧插入数据 RPUSH: 从列表右侧插入数据2.查看列表长度CODE LLEN list13.查看列表内容CODE LRANGE list1 0 -14.删除列表元素CODE LPOP: 从列表左边删除一个元素 RPOP: 从列表右边删除一个元素 LPOP list1 RPOP list1 5.删除整个列表CODE DEL list1第8章 hash操作1.mysql数据如何缓存到redisCSS mysql存储格式： user id name job age 1 bobo IT 28 2 json py 25 3 hao bug 26 hash类型存储格式： key field value field value user:1 name bobo job IT age 28 user:2 name json job py age 25 user:3 name hao job bug age 262.创建一个Hash数据CSS HMSET user:1 name bobo job IT age 28 HMSET user:2 name json job py age 29 HMSET user:3 name hao job bug age 19 3.查看hash里指定的值CSHARP select name from user where id =1 ; HMGET user:1 name HMGET user:1 name job age4.查看Hash里所有的值CSHARP select * from user where id =1 ; HGETALL user:1第9章 集合操作 set1.创建集合CODE SADD set1 1 2 3 SADD set2 1 3 5 7 2.查看集合成员CODE SMEMBERS set1 SMEMBERS set23.查看集合的交集CSS 127.0.0.1:6379> SINTER set1 set2 1) "1" 2) "3"4.查看集合的并集RUBY 127.0.0.1:6379> SUNION set1 set2 1) "1" 2) "2" 3) "3" 4) "5" 5) "7"5.查看集合的差集CSS 127.0.0.1:6379> SDIFF set1 set2 1) "2" 127.0.0.1:6379> SDIFF set2 set1 1) "5" 2) "7"6.删除一个成员CODE SREM set1 16.注意CODE 集合不允许出现重复的值，自动去重第10章 有序集合操作1.添加成员CODE ZADD SZ3 100 json ZADD SZ3 90 bobo ZADD SZ3 99 xiaocancan ZADD SZ3 98 bughao2.计算成员个数CODE ZCARD SZ33.计算某个成员分数CODE ZSCORE SZ3 json4.按照降序查看成员名次：CODE ZRANK SZ3 json ZRANK SZ3 bobo5.按照升序查看成员名次：CODE ZREVRANK SZ3 json ZREVRANK SZ3 bobo6.删除成员CODE ZREM SZ3 json7.增加成员分数CODE ZINCRBY SZ3 2 xiaocancan ZSCORE SZ3 xiaocancan8.返回指定排名范围的成员CODE ZRANGE SZ3 0 3 ZRANGE SZ3 0 3 WITHSCORES9.返回指定分数范围的成员CODE ZRANGEBYSCORE SZ3 95 100 ZRANGEBYSCORE SZ3 95 100 WITHSCORES10.返回指定分数范围的成员的个数CODE ZCOUNT SZ3 90 110第11章 持久化RDB流程图AOF流程图1.RDB和AOF介绍CODE RDB：类似于快照的形式，当前内存里的状态持久化到硬盘里 优点：压缩格式/恢复速度快 缺点：不是实时的，可能会丢失数据,操作比较重 AOF：类似于mysql的binlog，可以设置为每秒/每次操作以追加的形式持久化 优点：安全，最多损失1秒的数据，可读 缺点：文件比较大，恢复速度慢2.配置RDBKOTLIN save 900 1 save 300 10 save 60 10000 dbfilename redis.rdb dir /data/redis_6379/3.RDB结论BASH 1.没有配置save参数时，shutdown不会持久化保存 2.没有配置save参数时，可以手动执行bgsave触发持久化 3.在配置了save参数后，shutdown,kill,pkill都会自动触发bgsave 4.恢复的时候，rdb文件名要和配置文件里写的一样。 5.RDB高版本兼容低版本，低版本不兼容高版本4.AOF配置BASH appendonly yes appendfilename "redis.aof" appendfsync everysec5.AOF重写机制BASH 执行的命令 aof记录 redis的数据 set k1 v1 set k1 k1 set k2 v2 set k2 k1 k2 set k3 v3 set k3 k1 k2 k3 del k1 del k1 k2 k3 del k2 del k2 k3 实际有意义的只有一条记录： set k36.aof和rdb实验实验背景：CODE aof和rdb同时存在的时候，redis重启会读取哪一个数据？实验步骤：KOTLIN set k1 v1 set k2 v2 bgsave RDB k1 k2 mv redis.rdb /opt/ flushall set k3 v3 set k4 v4 AOF k3 k4 mv redis.aof /opt/ pkill redis rm -rf /data/redis_6379/* mv /opt/redis.rdb . mv /opt/redis.aof . redis-server /opt/redis_6379/conf/redis.conf redis-cli keys * 结论：CODE 当aof和rdb同时存在时，重启redis会优先读取aof的内容7.如何选择是rdb还是aofCPP https://redis.io/topics/persistence 1.开启混合模式 2.开启aof 3.不开启rdb 4.rdb采用定时任务的方式定时备份8.aof文件故障模拟实验结论CSS 1.aof文件损坏之后，使用修复工具，一刀流，从aof文件出错的地方开始到最后全部删掉 2.任何操作之前，先备份数据 3.aof备份一般情况最多损失1秒的数据9.实验：如果设置了过期时间，恢复数据会如何处理CSS 1.aof文件会记录下过期的时间 2.恢复的时候会去对比记录的过期时间和当前时间，如果超过了，就删除key 3.key的过期时间不受备份恢复影响第12章 redis用户认证1.写入配置文件CODE requirepass cookzhang2.使用密码登陆第一种：CSS [root@db01 ~]# redis-cli 127.0.0.1:6379> AUTH cookzhang OK 127.0.0.1:6379> set k1 v1 OK 第二种：CSHARP redis-cli -a cookz get k13.为什么redis的密码认证这么简单？CSS 1.redis一般都部署在内网环境，默认是比较安全的环境 2.有同学担心密码写在配置文件里，开发不允许登陆到Linux服务器上，但是可以连接到redis,设个密码安全些第13章 禁用或重命名危险命令1.禁用危险命令BASH rename-command CONFIG "" rename-command KEYS "" rename-command SHUTDOWN "" rename-command FLUSHALL "" rename-command DEL "" rename-command FLUSHDB ""2.来自json的灵魂拷问：shutdown禁用了 让后用kill?BASH rename-command CONFIG "" rename-command KEYS "" rename-command SHUTDOWN "qq526195417" rename-command FLUSHALL "" rename-command DEL "byebye" rename-command FLUSHDB ""第14章 Redis主从复制1.快速部署第二台服务器RUBY rsync -avz 10.0.0.51:/opt/* /opt/* mkdir /data/redis_6379/ -p cd /opt/redis make install sed -i 's#51#52#g' /opt/redis_6379/conf/redis_6379.conf redis-server /opt/redis_6379/conf/redis_6379.conf2.db01插入测试命令BASH for i in {1..1000};do redis-cli -h 10.0.0.51 set ${i} ${i};done3.配置主从复制方法1:临时生效CSS redis-cli -h 10.0.0.52 slaveof 10.0.0.51 6379 方法2:写进配置文件CSS slaveof 10.0.0.51 63794.主从复制的流程1.简单流程：CODE 1.从节点发送同步请求到主节点 2.主节点接收到从节点的请求之后,做了如下操作 - 立即执行bgsave将当前内存里的数据持久化到磁盘上 - 持久化完成之后,将rdb文件发送给从节点 3.从节点从主节点接收到rdb文件之后,做了如下操作 - 清空自己的数据 - 载入从主节点接收的rdb文件到自己的内存里 4.后面的操作就是和主节点实时的了5.取消复制CODE SLAVEOF no one6.主从复制注意RUBY 1.从节点只读不可写 2.从节点不会自动故障转移,它会一直同步主节点 10.0.0.52:6379> set k1 v1 (error) READONLY You can't write against a read only slave. 3.主从复制故障转移需要人工介入 - 修改代码指向REDIS的IP地址 - 从节点需要执行SLAVEOF no one 4.从节点会清空自己原有的数据,如果同步的对象写错了,就会导致数据丢失 5.从库和主库后续的同步依靠的是redis的SYNC协议，而不是RDB文件，RDB文件只是第一次建立同步时使用。 6.从库也可以正常的持久化文件7.安全的操作无论是同步,无论是主节点还是从节点,请先备份一下数据第15章 Redis哨兵1.哨兵的作用CODE 1.解决了主从复制故障需要人为干预的问题 2.提供了自动的高可用解决方案2.目录和端口规划CODE redis节点： 6379 哨兵节点： 263793.部署3台redis单节点db01操作：BASH pkill redis cat >/opt/redis_6379/conf/redis_6379.conf <<EOF daemonize yes bind 127.0.0.1 10.0.0.51 port 6379 pidfile "/opt/redis_6379/pid/redis_6379.pid" logfile "/opt/redis_6379/logs/redis_6379.log" dbfilename "redis.rdb" dir "/data/redis_6379" appendonly yes appendfilename "redis.aof" appendfsync everysec EOF systemctl start redis redis-clidb02和db03的操作：RUBY pkill redis rm -rf /opt/redis* rsync -avz 10.0.0.51:/usr/local/bin/redis-* /usr/local/bin rsync -avz 10.0.0.51:/usr/lib/systemd/system/redis.service /usr/lib/systemd/system/ mkdir /opt/redis_6379/{conf,logs,pid} -p mkdir /data/redis_6379 -p cat >/opt/redis_6379/conf/redis_6379.conf <<EOF daemonize yes bind 127.0.0.1 $(ifconfig eth0|awk 'NR==2{print $2}') port 6379 pidfile "/opt/redis_6379/pid/redis_6379.pid" logfile "/opt/redis_6379/logs/redis_6379.log" dbfilename "redis.rdb" dir "/data/redis_6379" appendonly yes appendfilename "redis.aof" appendfsync everysec EOF useradd redis -M -s /sbin/nologin chown -R redis:redis /opt/redis* chown -R redis:redis /data/redis* systemctl daemon-reload systemctl start redis redis-cli4.配置主从复制CSS redis-cli -h 10.0.0.52 slaveof 10.0.0.51 6379 redis-cli -h 10.0.0.53 slaveof 10.0.0.51 6379 redis-cli -h 10.0.0.51 info Replication5.部署哨兵节点-3台机器都操作KOTLIN mkdir -p /data/redis_26379 mkdir -p /opt/redis_26379/{conf,pid,logs} cat >/opt/redis_26379/conf/redis_26379.conf << EOF bind $(ifconfig eth0|awk 'NR==2{print $2}') port 26379 daemonize yes logfile /opt/redis_26379/logs/redis_26379.log dir /data/redis_26379 sentinel monitor myredis 10.0.0.51 6379 2 sentinel down-after-milliseconds myredis 3000 sentinel parallel-syncs myredis 1 sentinel failover-timeout myredis 18000 EOF chown -R redis:redis /data/redis* chown -R redis:redis /opt/redis*参数解释：BASH sentinel monitor mymaster 10.0.0.51 6379 2 #mymaster 主节点别名 主节点 ip 和端口， 判断主节点失败， 两个 sentinel 节点同意 sentinel down-after-milliseconds mymaster 3000 #选项指定了 Sentinel 认为服务器已经断线所需的毫秒数。 sentinel parallel-syncs mymaster 1 #向新的主节点发起复制操作的从节点个数， 1 轮询发起复制 sentinel failover-timeout mymaster 180000 #故障转移超时时间6.编写哨兵system配置文件-3台机器都操作CSHARP cat >/usr/lib/systemd/system/redis-sentinel.service<<EOF [Unit] Description=Redis persistent key-value database After=network.target After=network-online.target Wants=network-online.target [Service] ExecStart=/usr/local/bin/redis-sentinel /opt/redis_26379/conf/redis_26379.conf --supervised systemd ExecStop=/usr/local/bin/redis-cli -h $(ifconfig eth0|awk 'NR==2{print $2}') -p 26379 shutdown Type=notify User=redis Group=redis RuntimeDirectory=redis RuntimeDirectoryMode=0755 [Install] WantedBy=multi-user.target EOF systemctl daemon-reload 7.启动哨兵并检查CODE systemctl start redis-sentinel 8.验证主节点CSS redis-cli -h 10.0.0.51 -p 26379 Sentinel get-master-addr-by-name myredis redis-cli -h 10.0.0.52 -p 26379 Sentinel get-master-addr-by-name myredis redis-cli -h 10.0.0.53 -p 26379 Sentinel get-master-addr-by-name myredis9.模拟故障转移关闭主节点服务上的所有redis进程观察其他2个节点会不会发生选举查看配置文件里会不会自动更新查看新的主节点能不能写入查看从节点能否正常同步10.模拟故障修复上线启动单节点启动哨兵11.来自json的灵魂发问：能够给redis 节点加权 来确定优先备选主节点嘛?流程说明：设置其他节点的权重为0手动发起重新选举观察所有节点消息是否同步观察切换结果是否符合预期命令解释：CSS 查询命令:CONFIG GET slave-priority 设置命令:CONFIG SET slave-priority 0 主动切换:sentinel failover myredis操作命令：CSS redis-cli -h 10.0.0.52 -p 6379 CONFIG SET slave-priority 0 redis-cli -h 10.0.0.53 -p 6379 CONFIG SET slave-priority 0 redis-cli -h 10.0.0.51 -p 26379 sentinel failover myredis验证选举结果：CSS redis-cli -h 10.0.0.51 -p 26379 Sentinel get-master-addr-by-name myredis第16章 手动部署Redis集群集群架构图1集群架构图21.烧饼的不足资源利用率不高主库压力大连接过程繁琐2.集群重要概念BASH redis集群，无论有几个节点，一共只有16384个槽 所有的槽位都必须分配，哪怕有1个槽位不正常，整个集群都不能用 每个节点的槽的顺序不重要，重点是数量 hash算法足够随机，足够平均 每个槽被分配到数据的概率是相当的 集群的高可用依赖于主从复制 集群拥有自己的配置文件，动态更新，不要手欠修改 集群通讯会使用基础端口号+10000的端口，这个是自动创建的，不是配置文件配置的 集群槽位分配比例允许误差在%2之间3.目录规划CODE 主节点 6380 从节点 63814.db01的操作JSX ssh-keygen ssh-copy-id 10.0.0.52 ssh-copy-id 10.0.0.53 pkill redis mkdir -p /opt/redis_{6380,6381}/{conf,logs,pid} mkdir -p /data/redis_{6380,6381} cat >/opt/redis_6380/conf/redis_6380.conf<<EOF bind 10.0.0.51 port 6380 daemonize yes pidfile "/opt/redis_6380/pid/redis_6380.pid" logfile "/opt/redis_6380/logs/redis_6380.log" dbfilename "redis_6380.rdb" dir "/data/redis_6380/" appendonly yes appendfilename "redis.aof" appendfsync everysec cluster-enabled yes cluster-config-file nodes_6380.conf cluster-node-timeout 15000 EOF cd /opt/ cp redis_6380/conf/redis_6380.conf redis_6381/conf/redis_6381.conf sed -i 's#6380#6381#g' redis_6381/conf/redis_6381.conf chown -R redis:redis /opt/redis_* chown -R redis:redis /data/redis_* cat >/usr/lib/systemd/system/redis-master.service<<EOF [Unit] Description=Redis persistent key-value database After=network.target After=network-online.target Wants=network-online.target [Service] ExecStart=/usr/local/bin/redis-server /opt/redis_6380/conf/redis_6380.conf --supervised systemd ExecStop=/usr/local/bin/redis-cli -h $(ifconfig eth0|awk 'NR==2{print $2}') -p 6380 shutdown Type=notify User=redis Group=redis RuntimeDirectory=redis RuntimeDirectoryMode=0755 [Install] WantedBy=multi-user.target EOF cd /usr/lib/systemd/system/ cp redis-master.service redis-slave.service sed -i 's#6380#6381#g' redis-slave.service systemctl daemon-reload systemctl start redis-master systemctl start redis-slave ps -ef|grep redis rsync -avz /opt/redis_638* 10.0.0.52:/opt/ rsync -avz /opt/redis_638* 10.0.0.53:/opt/ rsync -avz /usr/lib/systemd/system/redis-*.service 10.0.0.52:/usr/lib/systemd/system/redis-master.service rsync -avz /usr/lib/systemd/system/redis-*.service 10.0.0.53:/usr/lib/systemd/system/redis-master.service5.db02的操作BASH pkill redis find /opt/redis_638* -type f -name "*.conf"|xargs sed -i "/bind/s#51#52#g" cd /usr/lib/systemd/system/ sed -i 's#51#52#g' redis-*.service mkdir –p /data/redis_{6380,6381} chown -R redis:redis /opt/redis_* chown -R redis:redis /data/redis_* systemctl daemon-reload systemctl start redis-master systemctl start redis-slave ps -ef|grep redis6.db03的操作BASH pkill redis find /opt/redis_638* -type f -name "*.conf"|xargs sed -i "/bind/s#51#53#g" cd /usr/lib/systemd/system/ sed -i 's#51#53#g' redis-*.service mkdir –p /data/redis_{6380,6381} chown -R redis:redis /opt/redis_* chown -R redis:redis /data/redis_* systemctl daemon-reload systemctl start redis-master systemctl start redis-slave ps -ef|grep redis7.集群手动发现节点CSS redis-cli -h db01 -p 6380 CLUSTER MEET 10.0.0.52 6380 redis-cli -h db01 -p 6380 CLUSTER MEET 10.0.0.53 6380 redis-cli -h db01 -p 6380 CLUSTER MEET 10.0.0.51 6381 redis-cli -h db01 -p 6380 CLUSTER MEET 10.0.0.52 6381 redis-cli -h db01 -p 6380 CLUSTER MEET 10.0.0.53 6381 redis-cli -h db01 -p 6380 CLUSTER NODES 8.集群手动分配槽位1.槽位规划CSS db01:6380 5461 0-5460 db02:6380 5461 5461-10921 db03:6380 5462 10922-163832.分配槽位OBJECTIVEC redis-cli -h db01 -p 6380 CLUSTER ADDSLOTS {0..5460} redis-cli -h db02 -p 6380 CLUSTER ADDSLOTS {5461..10921} redis-cli -h db03 -p 6380 CLUSTER ADDSLOTS {10922..16383}3.查看集群状态OBJECTIVEC redis-cli -h db01 -p 6380 CLUSTER NODES redis-cli -h db01 -p 6380 CLUSTER INFO9.手动部署复制关系0.先获取集群节点信息OBJECTIVEC redis-cli -h db01 -p 6380 CLUSTER NODES1.先删除所有6381的内容和不需要内容CSS 6380的ID 10.0.0.51 6380的ID 10.0.0.53 6380的ID 10.0.0.522.画图3.确定复制关系OBJECTIVEC redis-cli -h db01 -p 6381 CLUSTER REPLICATE 52的6380的ID redis-cli -h db02 -p 6381 CLUSTER REPLICATE 53的6380的ID redis-cli -h db03 -p 6381 CLUSTER REPLICATE 51的6380的ID4.检查复制关系OBJECTIVEC redis-cli -h db01 -p 6380 CLUSTER NODES10.集群插入数据1.尝试插入一条数据发现报错CSS 10.0.0.51:6380> set k1 v1 (error) MOVED 12706 10.0.0.53:63802.目前的现象在db01的6380节点插入数据提示报错报错内容提示应该移动到db03的6380上在db03的6380上执行相同的插入命令可以插入成功在db01的6380节点插入数据有时候可以,有时候不行使用-c参数后,可以正常插入命令,并且节点切换到了提示的对应节点上3.问题原因因为集群模式有ASK路由规则,加入-c参数后,会自动跳转到目标节点处理并且最后由目标节点返回信息11.验证集群是否足够足迹足够平均0.写入测试数据BASH for i in {1..10000};do redis-cli -c -h db01 -p 6380 set k_${i} v_${i};echo ${i};done1.验证足够平均:CODE DBSIZE2.验证足够随机：SWIFT redis-cli -c -h db03 -p 6380 keys \* > keys_all.txt cat keys_all.txt |awk -F "_" '{print $2}'|sort -rn 3.允许节点的key在2%误差的依据来源：CSS [root@db01 /opt/redis/src]# redis-cli --cluster rebalance 10.0.0.51 6380 >>> Performing Cluster Check (using node 10.0.0.51:6380) [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered. *** No rebalancing needed! All nodes are within the 2.00% threshold.4.检查集群健康状态：RUBY [root@db01 /opt/redis/src]# redis-cli --cluster info 10.0.0.51 6380 10.0.0.51:6380 (ccaa5dcb...) -> 3343 keys | 5461 slots | 1 slaves. 10.0.0.53:6380 (a69e46ea...) -> 3343 keys | 5462 slots | 1 slaves. 10.0.0.52:6380 (b2719c41...) -> 3314 keys | 5461 slots | 1 slaves. [OK] 10000 keys in 3 masters. 0.61 keys per slot on average.第17章 实战-槽位分配错误如何调整1.故障背景某日某豪接到任务，需要部署redis集群结果不小心无脑复制粘贴，把所有的槽都分配给了1个节点，还没发现，然后就交付使用了，过了1天才发现问题。而此时，已经有不少数据写入了，如何在不丢失数据的情况下解决这个问题？2.前提数据不能丢，最好不中断业务3.实验现象RUBY [root@db01 ~]# redis-cli --cluster info 10.0.0.51 6380 10.0.0.51:6380 (ccaa5dcb...) -> 1000 keys | 16384 slots | 3 slaves. 10.0.0.53:6380 (a69e46ea...) -> 0 keys | 0 slots | 0 slaves. 10.0.0.52:6380 (b2719c41...) -> 0 keys | 0 slots | 0 slaves. [OK] 1000 keys in 3 masters. 0.06 keys per slot on average.解决思路1：备份数据，重做集群，导入数据OBJECTIVEC 来自json的灵魂发问： redis.cof的数据 集群重做后 aof文件里面的数据能被hash嘛? 备份数据： redis-cli -c -h db01 -p 6380 db01:6380> BGREWRITEAOF cp redis.aof redis.aof-1000.bak 重做集群： redis-cli -h db01 -p 6380 FLUSHALL redis-cli -h db02 -p 6380 FLUSHALL redis-cli -h db03 -p 6380 FLUSHALL redis-cli -h db01 -p 6380 CLUSTER RESET redis-cli -h db02 -p 6380 CLUSTER RESET redis-cli -h db03 -p 6380 CLUSTER RESET redis-cli -h db01 -p 6380 CLUSTER MEET 10.0.0.52 6380 redis-cli -h db01 -p 6380 CLUSTER MEET 10.0.0.53 6380 redis-cli -h db01 -p 6380 CLUSTER NODES redis-cli -h db01 -p 6380 CLUSTER ADDSLOTS {0..5460} redis-cli -h db02 -p 6380 CLUSTER ADDSLOTS {5461..10921} redis-cli -h db03 -p 6380 CLUSTER ADDSLOTS {10922..16383} redis-cli --cluster info 10.0.0.51 6380 实验结论： 重启后所有的数据还是在db01上。 db01重启后数据虽然可以写入，但是访问的时候还是按照正常的hash规则去分配的，所以db01的数据实际上是没用的。 所以这样的方法是不可行的。 相关日志： 16790:M 12 Mar 2020 10:08:08.875 # I have keys for slot 5812, but the slot is assigned to another node. Setting it to importing state. 16790:M 12 Mar 2020 10:08:08.875 # I have keys for slot 5821, but the slot is assigned to another node. Setting it to importing state. 16790:M 12 Mar 2020 10:08:08.875 # I have keys for slot 5842, but the slot is assigned to another node. Setting it to importing state.解决思路2:获得所有key的名称，导出再导入BASH 0.重新制作一个测试集群，槽位分布和线上出错的一样 1.将线上环境里的aof导出来 2.恢复到测试的集群里 3.收集所有的key redis-cli -c -h db01 -p 6380 keys \* > keys_all.txt 4.编写脚本遍历所有的key获取值 cat >get_key.sh<<EOF #!/bin/bash for key in $(cat keys_all.txt) do value=$(redis-cli -c -h 10.0.0.51 -p 6380 get ${key}) echo redis-cli -c -h 10.0.0.51 -p 6380 set ${key} ${value} >> backup_all_key.txt done EOF 5.按照正常槽位分配去重新初始化集群 redis-cli -h db01 -p 6380 FLUSHALL redis-cli -h db02 -p 6380 FLUSHALL redis-cli -h db03 -p 6380 FLUSHALL redis-cli -h db01 -p 6380 CLUSTER RESET redis-cli -h db02 -p 6380 CLUSTER RESET redis-cli -h db03 -p 6380 CLUSTER RESET redis-cli -h db01 -p 6380 CLUSTER MEET 10.0.0.52 6380 redis-cli -h db01 -p 6380 CLUSTER MEET 10.0.0.53 6380 redis-cli -h db01 -p 6380 CLUSTER NODES redis-cli -h db01 -p 6380 CLUSTER ADDSLOTS {0..5460} redis-cli -h db02 -p 6380 CLUSTER ADDSLOTS {5461..10921} redis-cli -h db03 -p 6380 CLUSTER ADDSLOTS {10922..16383} redis-cli --cluster info 10.0.0.51 6380 6.执行导入脚本 bash backup_all_key.txt 7.检查是否导入成功 redis-cli --cluster info 10.0.0.51 6380 8.测试环境没问题之后再去生产环境操作解决思路3: 流水线 piplineCSS 前提条件： 1.了解aof格式 2.了解新版本redis默认是开启混合模式的 3.需要修改为普通的aof格式并重启 4.恢复时使用-c参数无效，需要在每一个节点都执行 命令： redis-cli -c -h 10.0.0.51 -p 6380 --pipe < redis.aof redis-cli -c -h 10.0.0.52 -p 6380 --pipe < redis.aof redis-cli -c -h 10.0.0.53 -p 6380 --pipe < redis.aof解决思路4: 使用redis-cli工具重新分配槽位BASH 重新分配槽位 redis-cli --cluster reshard 10.0.0.51:6380 第一次交互：输入迁出的槽的数量 How many slots do you want to move (from 1 to 16384)? 5461 第二次交互：输入接受的ID What is the receiving node ID? db02的6380的ID 第三次交互：输入发送者的ID Please enter all the source node IDs. Type 'all' to use all the nodes as source nodes for the hash slots. Type 'done' once you entered all the source nodes IDs. Source node #1: db01的6390的ID Source node #2: done 第四次交互：YES! 重复上面的操作，知道所有的节点槽位都分配正确解决思路5:直接使用工具在线导入CSS redis-cli --cluster import 10.0.0.51:6380 --cluster-copy --cluster-replace --cluster-from 10.0.0.51:6379 第18章 使用工具自动部署redis集群1.恢复集群初始化OBJECTIVEC redis-cli -h db01 -p 6380 FLUSHALL redis-cli -h db02 -p 6380 FLUSHALL redis-cli -h db03 -p 6380 FLUSHALL redis-cli -h db01 -p 6381 FLUSHALL redis-cli -h db02 -p 6381 FLUSHALL redis-cli -h db03 -p 6381 FLUSHALL redis-cli -h db01 -p 6380 CLUSTER RESET redis-cli -h db02 -p 6380 CLUSTER RESET redis-cli -h db03 -p 6380 CLUSTER RESET redis-cli -h db01 -p 6381 CLUSTER RESET redis-cli -h db02 -p 6381 CLUSTER RESET redis-cli -h db03 -p 6381 CLUSTER RESET redis-cli -h db01 -p 6380 CLUSTER NODES 2.使用工具初始化CSS redis-cli --cluster create 10.0.0.51:6380 10.0.0.52:6380 10.0.0.53:6380 10.0.0.51:6381 10.0.0.52:6381 10.0.0.53:6381 --cluster-replicas 13.检查集群CSS redis-cli --cluster info 10.0.0.51 6380 redis-cli -h db01 -p 6380 CLUSTER NODES redis-cli --cluster check 10.0.0.51 6380 第19章 使用工具扩容1.来自json的灵魂发问：迁移时候槽的数据咋办？需要停库吗？访问受影响吗？从库呢？2.如何设计实验验证数据是否受影响？迁移的过程中一个窗口不断的写数据一个窗口不断的读数据观察是否会中断3.创建新节点BASH mkdir -p /opt/redis_{6390,6391}/{conf,logs,pid} mkdir -p /data/redis_{6390,6391} cd /opt/ cp redis_6380/conf/redis_6380.conf redis_6390/conf/redis_6390.conf cp redis_6380/conf/redis_6380.conf redis_6391/conf/redis_6391.conf sed -i 's#6380#6390#g' redis_6390/conf/redis_6390.conf sed -i 's#6380#6391#g' redis_6391/conf/redis_6391.conf redis-server /opt/redis_6390/conf/redis_6390.conf redis-server /opt/redis_6391/conf/redis_6391.conf ps -ef|grep redis redis-cli -c -h db01 -p 6380 cluster meet 10.0.0.51 6390 redis-cli -c -h db01 -p 6380 cluster meet 10.0.0.51 6391 redis-cli -c -h db01 -p 6380 cluster nodes4.使用工具扩容步骤CSHARP 重新分配槽位 redis-cli --cluster reshard 10.0.0.51:6380 第一次交互：每个节点分配多少个槽位 How many slots do you want to move (from 1 to 16384)? 4096 第二次交互：接受节点的ID是什么 What is the receiving node ID? 6390的ID 第三次交互：哪些节点需要导出 Source node #1: all 第四次交互：确认是否执行 Do you want to proceed with the proposed reshard plan (yes/no)? yes第20章 使用工具缩容1.操作命令PHP 重新分配槽位 redis-cli --cluster reshard 10.0.0.51:6380 第一次交互：需要迁移多少个槽位 How many slots do you want to move (from 1 to 16384)? 1365 第二次交互：接受节点的ID是什么 What is the receiving node ID? db01的6380的ID 第三次交互：哪些节点需要导出 Source node #1: db01的6390的ID Source node #2: done 第四次交互：确认 Do you want to proceed with the proposed reshard plan (yes/no)? yes 重复上面的操作，直到6390所有的槽位都被分配出去了 检查集群状态，确认6390没有槽位了 redis-cli --cluster info 10.0.0.51:6380 使用工具删除节点了 redis-cli --cluster del-node 10.0.0.51:6390 6390的ID redis-cli --cluster del-node 10.0.0.51:6391 6391的ID2.提问：公司先用的是哨兵然后在改集群 如何迁移数据用槽位分配解决方法：CODE 1.搭建好Redis集群并互相发现 2.把所有的key都分配到db01上 3.把哨兵里的数据AOF持久化 4.拷贝到db01上，启动集群节点 5.重新分配槽位迁移到其他2个节点第21章 .验证集群高可用1.提问：故障的主库修复后启动会变成备胎吗？2.实验结论：CODE 1.主库挂了，从库会自动接替主库的角色，集群恢复正常会受超时时间控制 2.老得主库修复上线后，会自动变成从库，同步新的主库3.主动发起集群角色切换：OBJECTIVEC CLUSTER FAILOVER第22章 模拟分配时故障1.模拟场景：迁移数据时人为中断了，导致槽的状态不对JSON [11213-<-a69e46ea7560684a7061ddb6dc3f854a1ef3dbd4] 51 [11213->-ccaa5dcb0f0320332100594d629122b2702660d5] 532.使用工具修复：CSS redis-cli --cluster fix 10.0.0.51:63803.手动修复：OBJECTIVEC CLUSTER SETSLOT <slot> STABLE第23章 使用工具维护集群的好处CODE 工具有很多判断条件，更加严谨，健壮性更好 删除槽，使用工具会判断，如果槽里有数据，就不执行 添加节点使用工具会判断，如果新增加的节点本身不为空，不允许加入到集群里 删除节点使用工具会判断，如果本删除节点本身还有槽，不允许删除第24章 数据迁移1.新版本直接使用工具迁移不加copy参数相当于mv，老数据迁移成功就删掉了CSS redis-cli --cluster import 10.0.0.51:6380 --cluster-from 10.0.0.51:6379添加copy参数相当于cp,老数据迁移成功后会保留CSS redis-cli --cluster import 10.0.0.51:6380 --cluster-copy --cluster-from 10.0.0.51:6379 添加replace参数会覆盖掉同名的数据，对新集群新增加的数据不受影响CSS redis-cli --cluster import 10.0.0.51:6380 --cluster-copy --cluster-replace --cluster-from 10.0.0.51:6379 验证迁移期间边写边导会不会影响: 同时开2个终端，一个写入key，BASH for i in {1..1000};do redis-cli set k_${i} v_${i};sleep 0.2;echo ${i};done一个执行导入命令CSS redis-cli --cluster import 10.0.0.51:6380 --cluster-copy --cluster-replace --cluster-from 10.0.0.51:6379 得出结论：CODE 只会导入当你执行导入命令那一刻时，当前被导入节点的所有数据，类似于快照，对于后面再写入的数据不会更新第25章 分析key的大小0.使用自带工具分析CODE redis-cli --bigkeys 1.使用第三方工具分析1.安装命令BASH yum install python-pip gcc python-devel -y cd /opt/ git clone https://github.com/sripathikrishnan/redis-rdb-tools cd redis-rdb-tools pip install python-lzf python setup.py install2.生成测试数据CODE redis-cli -h db01 -p 6379 set txt $(cat txt.txt)3.执行bgsave生成rdb文件CODE redis-cli -h db01 -p 6379 BGSAVE4.使用工具分析BASH cd /data/redis_6379/ rdb -c memory redis_6379.rdb -f redis_6379.rdb.csv5.过滤分析DART awk -F"," '{print $4,$3}' redis_6379.rdb.csv |sort -r6.汇报领导将结果整理汇报给领导,询问开发这个key是否可以删除第26章 redis的内存管理1.设置最大内存限制BASH config set maxmemory 2G2.内存回收机制生产上一定要限制redis的内存使用大小。当达到内存使用限制之后redis会出发对应的控制策略redis支持6种策略：CSS 1.noevicition 默认策略，不会删除任务数据，拒绝所有写入操作并返回客户端错误信息，此时只响应读操作 2.volatile-lru 根据LRU算法删除设置了超时属性的key，指导腾出足够空间为止，如果没有可删除的key，则退回到noevicition策略 3.allkeys-lru 根据LRU算法删除key，不管数据有没有设置超时属性 4.allkeys-random 随机删除所有key 5.volatile-random 随机删除过期key 5.volatile-ttl 根据key的ttl，删除最近要过期的key3.生产上redis限制多大内存CODE 先空出来系统一半内存 48G 一共 24G 系统 24G redis redis先给8G内存 满了之后，分析结果告诉老大和开发，让他们排查一下是否所有的key都是必须的 redis再给到12G内存 满了之后，分析结果告诉老大和开发，让他们排查一下是否所有的key都是必须的 redis再给到16G内存 满了之后，分析结果告诉老大和开发，让他们排查一下是否所有的key都是必须的 等到24G都用完了之后，汇报领导，要考虑买内存了。 等到35G的时候，就要考虑是加内存，还是扩容机器。第27章 性能测试CODE redis-benchmark -n 10000 -q第28章 集群相关命令CSS redis-cli -h db01 -p 6380 CLUSTER NODES CLUSTER MEET 10.0.0.52 6380 CLUSTER INFO CLUSTER REPLICATE CLUSTER ADDSLOTS CLUSTER RESET CLUSTER FAILOVER CLUSTER SETSLOT <slot> STABLE redis-cli --cluster info 10.0.0.51 6380 redis-cli --cluster rebalance 10.0.0.51 6380 redis-cli --cluster del-node redis-cli --cluster fix 10.0.0.51:6380第29章 命令总结CSHARP 1.全局命令 keys * DBSIZE EXISTS k1 EXPIRE k1 10 TTL k1 DEL k1 2.字符串: set k1 v1 get k1 mset k1 v1 k2 v2 k3 v3 mget k1 k2 k3 incr k1 incrby k1 N 3.列表： LPUSH RPUSH LPOP RPOP LLEN LRANGE list1 0 -1 HASH: HMSET HGET HMGET HGETALL 4.集合： SADD SDIFF SINTER SUNION SREM 5.有序集合： ZADD ZCARD ZSCORE ZRANK ZREVRANK ZRANGE ZRANGEBYSCORE ZINCRBY ZCOUNT转自：简书张导https://www.jianshu.com/p/9622d5906bcf老男孩-NoSQL
企业高可用性标准全年无故障率(非计划内故障停机)99.9% ----> 0.001*365*24*60=525.6 min 99.99% ----> 0.0001*365*24*60=52.56 min 99.999% ----> 0.0001*365*24*60=5.256 min 高可用架构方案负载均衡:有一定的高可用性 LVS Nginx 主备系统:有高可用性,但是需要切换,是单活的架构 KA , MHA, MMM 真正高可用(多活系统): NDB Cluster Oracle RAC Sysbase cluster , InnoDB Cluster（MGR）,PXC , MGC 主从复制简介1.1. 基于二进制日志复制的 1.2. 主库的修改操作会记录二进制日志 1.3. 从库会请求新的二进制日志并回放,最终达到主从数据同步 1.4. 主从复制核心功能: 辅助备份,处理物理损坏 扩展新型的架构:高可用,高性能,分布式架构等 主从复制前提(搭建主从的过程)2.1 两台以上mysql实例 ,server_id,server_uuid不同 2.2 主库开启二进制日志 2.3 专用的复制用户 2.4 保证主从开启之前的某个时间点,从库数据是和主库一致(补课) 2.5 告知从库,复制user,passwd,IP port,以及复制起点(change master to) 2.6 线程(三个):Dump thread IO thread SQL thread 开启(start slave) 主从复制搭建(Classic replication)清理主库数据rm -rf /data/3307/data/* 重新初始化3307mysqld --initialize-insecure --user=mysql --basedir=/app/mysql --datadir=/data/3307/data 修改my.cnf ,开启二进制日志功能[root@db01 3307]# vim /data/3307/my.cnf log_bin=/data/3307/data/mysql-bin 启动所有节点[root@db01 3307]# systemctl start mysqld3307 [root@db01 3307]# systemctl start mysqld3308 [root@db01 3307]# systemctl start mysqld3309 [root@db01 3307]# ps -ef |grep mysqld mysql 3684 1 4 09:59 ? 00:00:00 /app/mysql/bin/mysqld --defaults-file=/data/3307/my.cnf mysql 3719 1 7 09:59 ? 00:00:00 /app/mysql/bin/mysqld --defaults-file=/data/3308/my.cnf mysql 3754 1 8 09:59 ? 00:00:00 /app/mysql/bin/mysqld --defaults-file=/data/3309/my.cnf [root@db01 3307]# mysql -S /data/3307/mysql.sock -e "select @@server_id" [root@db01 3307]# mysql -S /data/3308/mysql.sock -e "select @@server_id" [root@db01 3307]# mysql -S /data/3309/mysql.sock -e "select @@server_id" 主库中创建复制用户[root@db01 3307]# mysql -S /data/3307/mysql.sock db01 [(none)]>grant replication slave on *.* to repl@'10.0.0.%' identified by '123'; db01 [(none)]>select user,host from mysql.user; 备份主库并恢复到从库[root@db01 3307]# mysqldump -S /data/3307/mysql.sock -A --master-data=2 --single-transaction -R --triggers >/backup/full.sql -- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=653; [root@db01 3307]# mysql -S /data/3308/mysql.sock db01 [(none)]>source /backup/full.sql 告知从库关键复制信息ip port user password binlog position [root@db01 3307]# mysql -S /data/3308/mysql.sock db01 [mysql]>help change master to CHANGE MASTER TO MASTER_HOST='10.0.0.51', MASTER_USER='repl', MASTER_PASSWORD='123', MASTER_PORT=3307, MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=653, MASTER_CONNECT_RETRY=10; 开启主从专用线程start slave ; 检查复制状态db01 [mysql]>show slave status \G Slave_IO_Running: Yes Slave_SQL_Running: Yes 主从复制的原理 (Classic Replication)主从中设置到的文件和线程线程主: DUMP THREAD 从: IO THREAD SQL THREAD 文件主: mysql-bin.000001 从: db01-relay.000001 ===>中继日志 master.info ===》主库信息记录日志 relay-log.info ===> 记录中继应用情况信息 主从复制原理主从复制原理描述：1.change master to 时，ip pot user password binlog position写入到master.info进行记录 2. start slave 时，从库会启动IO线程和SQL线程 3.IO_T，读取master.info信息，获取主库信息连接主库 4. 主库会生成一个准备binlog DUMP线程，来响应从库 5. IO_T根据master.info记录的binlog文件名和position号，请求主库DUMP最新日志 6. DUMP线程检查主库的binlog日志，如果有新的，TP(传送)给从从库的IO_T 7. IO_T将收到的日志存储到了TCP/IP 缓存，立即返回ACK给主库 ，主库工作完成 8.IO_T将缓存中的数据，存储到relay-log日志文件,更新master.info文件binlog 文件名和postion，IO_T工作完成 9.SQL_T读取relay-log.info文件，获取到上次执行到的relay-log的位置，作为起点，回放relay-log 10.SQL_T回放完成之后，会更新relay-log.info文件。 11. relay-log会有自动清理的功能。 细节：（5.5版本之后） 1.主库一旦有新的日志生成，会发送“信号”给binlog dump ，IO线程再请求 主从故障监控分析处理线程相关监控主库:show full processlist; 每个从库都会有一行dump相关的信息 HOSTS: db01:47176 State: Master has sent all binlog to slave; waiting for more updates 如果现实非以上信息,说明主从之间的关系出现了问题 从库:db01 [(none)]>show slave status \G 主库相关信息监控Master_Host: 10.0.0.51 Master_User: repl Master_Port: 3307 Master_Log_File: mysql-bin.000005 Read_Master_Log_Pos: 444 从库中继日志的应用状态Relay_Log_File: db01-relay-bin.000002 Relay_Log_Pos: 485 从库复制线程有关的状态Slave_IO_Running: Yes Slave_SQL_Running: Yes Last_IO_Errno: 0 Last_IO_Error: Last_SQL_Errno: 0 Last_SQL_Error: 过滤复制有关的状态Replicate_Do_DB: Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: 主从延时相关状态(非人为)Seconds_Behind_Master: 0 延时从库有关的状态(人为)SQL_Delay: 0 SQL_Remaining_Delay: NULL GTID 复制有关的状态Retrieved_Gtid_Set: Executed_Gtid_Set: Auto_Position: 0 主从复制故障分析IO连接主库(1) 用户 密码 IP port Last_IO_Error: error reconnecting to master 'repl@10.0.0.51:3307' - retry-time: 10 retries: 7 [root@db01 ~]# mysql -urepl -p123333 -h 10.0.0.51 -P 3307 ERROR 1045 (28000): Access denied for user 'repl'@'db01' (using password: YES) 原因: 密码错误 用户错误 skip_name_resolve 地址错误 端口处理方法stop slave reset slave all change master to start slave 主库连接数上线,或者是主库太繁忙 show slave staus \G Last_IO_Errno: 1040 Last_IO_Error: error reconnecting to master 'repl@10.0.0.51:3307' - retry-time: 10 retries: 7 处理思路: 拿复制用户,手工连接一下 [root@db01 ~]# mysql -urepl -p123 -h 10.0.0.51 -P 3307 mysql: [Warning] Using a password on the command line interface can be insecure. ERROR 1040 (HY000): Too many connections 处理方法: db01 [(none)]>set global max_connections=300; (3) 防火墙,网络不通 请求二进制日志主库缺失日志 从库方面,二进制日志位置点不对 Last_IO_Error: Got fatal error 1236 from master when reading data from binary log: 'could not find next log; the first event 'mysql-bin.000001' at 154, the last event read from '/data/3307/data/mysql-bin.000002' at 154, the last byte read from '/data/3307/data/mysql-bin.000002' at 154.' 注意: 在主从复制环境中,严令禁止主库中reset master; 可以选择expire 进行定期清理主库二进制日志 解决方案: 重新构建主从 SQL 线程故障SQL线程功能：(1)读写relay-log.info (2)relay-log损坏,断节,找不到 (3)接收到的SQL无法执行 导致SQL线程故障原因分析：1. 版本差异，参数设定不同，比如：数据类型的差异，SQL_MODE影响 2.要创建的数据库对象,已经存在 3.要删除或修改的对象不存在 4.DML语句不符合表定义及约束时. 归根揭底的原因都是由于从库发生了写入操作. Last_SQL_Error: Error 'Can't create database 'db'; database exists' on query. Default database: 'db'. Query: 'create database db' 处理方法(以从库为核心的处理方案)： 方法一： stop slave; set global sql_slave_skip_counter = 1; #将同步指针向下移动一个，如果多次不同步，可以重复操作。 start slave; 方法二： /etc/my.cnf slave-skip-errors = 1032,1062,1007 常见错误代码: 1007:对象已存在 1032:无法执行DML 1062:主键冲突,或约束冲突 但是，以上操作有时是有风险的，最安全的做法就是重新构建主从。把握一个原则,一切以主库为主. 一劳永逸的方法:(1) 可以设置从库只读. db01 [(none)]>show variables like '%read_only%'; 注意： 只会影响到普通用户，对管理员用户无效。 (2)加中间件 读写分离。 主从延时监控及原因主库做了修改操作,从库比较长时间才能追上. 外在因素网络 主从硬件差异较大 版本差异 参数因素 主库(1) 二进制日志写入不及时 [rep]>select @@sync_binlog; (2) CR的主从复制中,binlog_dump线程,事件为单元,串行传送二进制日志(5.6 5.5) 1. 主库并发事务量大,主库可以并行,传送时是串行 2. 主库发生了大事务,由于是串行传送,会产生阻塞后续的事务. 解决方案: 1. 5.6 开始,开启GTID,实现了GC(group commit)机制,可以并行传输日志给从库IO 2. 5.7 开始,不开启GTID,会自动维护匿名的GTID,也能实现GC,我们建议还是认为开启GTID 3. 大事务拆成多个小事务,可以有效的减少主从延时. 从库SQL线程导致的主从延时 在CR复制情况下: 从库默认情况下只有一个SQL,只能串行回放事务SQL 1. 主库如果并发事务量较大,从库只能串行回放 2. 主库发生了大事务,会阻塞后续的所有的事务的运行 解决方案: 1. 5.6 版本开启GTID之后,加入了SQL多线程的特性,但是只能针对不同库(database)下的事务进行并发回放. 2. 5.7 版本开始GTID之后,在SQL方面,提供了基于逻辑时钟(logical_clock),binlog加入了seq_no机制, 真正实现了基于事务级别的并发回放,这种技术我们把它称之为MTS(enhanced multi-threaded slave). 3. 大事务拆成多个小事务,可以有效的减少主从延时. [https://dev.mysql.com/worklog/task/?id=6314] 小结1. 主从复制原理 2. 主从复制故障 3. 主从延时：group commit MTS [player id='712292593' type='collect' autoplay='true'/]