分类 默认分类 下的文章

两种认证方式,
第一种: 临时链接;
第二种: 固定密码链接;

第一种: 临时链接

  1. 服务端生成md5值和expires过期时间, 代码如下:
$expire = time() + 20;/*链接的有效期*/
$uri = '/audio/979.mp3'; /*访问的资源*/
$remoteAddr = '183.45.175.200';/*访问者的公网IP地址*/
$secret = 'zhuangdebiao'; /*密钥*/

/*拼接字符串, 生成哈希值*/
$hash = base64_encode(md5($expire.' '.$uri .' '.$remoteAddr . ' ' .$secret, true));
$hash = strtr($hash, '+/', '-_'); /*可选*/
$hash = str_replace('=', '', $hash); /*可选*/
/*最终URL*/
echo 'https://yey.zdb.im'.$uri.'?hash='.$hash.'&expires='.$expire;

URL示例 :
https://yey.zdb.im/audio/979.mp3?hash=qdmp79trLCCKKVzKAvia4A==&expires=1610085706

  1. 修改nginx配置
location /audio/ {
    secure_link $arg_hash,$arg_expires;
    secure_link_md5 "$secure_link_expires $uri $remote_addr zhuangdebiao";

    # hash error
    if ($secure_link = "") {
        return 403;
    }
    # expire
    if ($secure_link = "0") {
        return 410;
    }
    try_files $uri $uri/ = 404;
}
  1. 从$args即queryString中获取md5值和过期时间

secure_link $arg_hash,$arg_expires;

  1. 计算md5值的字符串模板

secure_link_md5 "$secure_link_expires $uri $remote_addr zhuangdebiao";

$secure_link_expires 即过期时间 $arg_expires;

$uri 即访问的资源路径;

$remote_addr 即用户的IP地址;

最后一段是密钥 secret;

用空格分隔, 也可以不用空格, 随意字符串都行;

  1. 如果md5值不相等, 即密钥等参数错误, 返回http 403错误;
  2. 如果链接过期, 返回410错误;
  3. 最终, 允许访问资源, 可以proxy_pass或者try_files检测文件是否存在 并返回给客户端浏览器;

第二种: 固定密码链接

uri 格式是 /prefix/hash/link

md5值的 格式是 hex(md5(link.secret))

原链接 https://yey.zdb.im/zdb/979.mp3

固定密码链接, 举例: https://yey.zdb.im/p/1656e96df11cbbcab7186e9f5dd171f3/979.mp3

location /p/ {
    secure_link_secret zhuangdebiao; # 密钥

    if ($secure_link = "") { 
        return 403;
    }

    rewrite ^ /zdb/$secure_link;
}
location /zdb/ { 
    alias /home/wwwroot/yey/Public/audio/;
    internal; # 仅允许内部访问,直接访问会返回404
}

计算md5值的算法:

$prefix = 'p'; /*入口前缀*/
$secret = 'zhuangdebiao'; /*固定的密钥*/
$link = '979.mp3'; /*访问的资源*/

$hash = md5($link .$secret, false); /*十六进制*/
echo 'https://yey.zdb.im'.'/'.$prefix.'/'.$hash.'/' .$link;

注意:配置过程中个人使用的指令所需要的权限比较高,主要是因为个人习惯了用root账户操作,如果使用自己创建的账户(输入指令时是‘$’ 而非‘#’,‘#’表示系统账户)可能会说权限不足,请自行切换到root用户或使用可执行的其他等效指令

1.在阿里云数据库1的my.cnf的mysqld节点添加以下配置:

port=3305

server-id=1

log-bin=mysql-bin

auto_increment_increment=2

auto_increment_offset=1

binlog-ignore=mysql

binlog-ignore=information_schema

binlog-ignore=performance_schema

character_set_server=utf8

log-bin-trust-function-creators=1

2.在阿里云数据库2的my.cnf的mysqld节点添加以下配置

port=3305

server-id=2

log-bin=mysql-bin

auto_increment_increment=2

auto_increment_offset=2

binlog-ignore=mysql

binlog-ignore=information_schema

binlog-ignore=performance_schema

character_set_server=utf8

log-bin-trust-function-creators=1
这里对上述添加的配置做详细说明:

port=3305 将mysql启动端口设置成3305(默认为3306)

log_bin 启动mysql二进制日志,如果没有配置这个将无法远程链接

binlog-ignore 指定不同步的数据库,如果有多个数据库不需要同步可以多个分别声明

character_set_server=utf8 指定utf8为默认字符集

server-id 可以为任意自然数,必须保证两台mysql主机不重复

auto_increment_increment=2 步进值auto_imcrement。一般有n台主MySQL就填n

auto_increment_offset 设定数据库中自动增长的起点,两台mysql的起点必须不同,这样才能避免两台服务器同步时出现主键冲突

replicate-do-db 要同步的数据库,如果需要就填,指定数据库的名称即可,默认为所有库,声明了不同步就默认除了不同步数据库意外的所有库。这里我没写。

log-bin-trust-function-creators=1 在默认情况下mysql会阻止主从同步的数据库function的创建,这会导致我们在导入sql文件时如果有创建function或者使用function的语句将会报错。

在主主同步所需要的主要为以上所介绍到的配置,当然还有其他的配置可以添加,具体的根据实际要求可百度查询。

3.重启mysql

执行指令:service mysqld restart

4.进入mysql:

mysql -uroot -p

5.相互授权:

192.168.18.129数据库1:

grant replication slave, replication client on . to 'iot123'@'192.168.18.130' identified by 'iot123'

flush privileges; //刷新MySQL的系统权限相关表,否则会无法用账号链接

192.168.18.130数据库2:

grant replication slave, replication client on . to 'iot123'@'192.168.18.129' identified by 'iot123';

flush privileges; //刷新MySQL的系统权限相关表,否则会无法用账号链接

注意:推荐两个主机相互授权的账号密码相同,否则在接下来的操作中可能会比较乱(我就是之前用了俩个不同的账号搞了好久也没搞定,后来改成相同的账号瞬间成功)

6.分别查看两台主机的日志节点:

show master status;

7.相互设置同步的日志节点

192.168.18.129:

mysql> change master to

->master_host='192.168.18.130', 
->master_port=3305, 
->master_user='iot123',
->master_password='iot123',
->master_log_file='mysql-bin.000010',
->master_log_pos=120;

192.168.18.130:

mysql> change master to

->master_host='192.168.18.129', 
->master_port=3305, 
->master_user='iot123',
->master_password='iot123',
->master_log_file='mysql-bin.000012',
->master_log_pos=120;

分段写如果写错了c退出,第二段开始最后是逗号,最有一段是分号,表结束,端口号和pos不用加引号,其他的配置需要加引号

说明:

所有的内容都是另一台主机的内容,log_file和log_pos对于另一台主机的日志节点。还有,必须要说明的是,每次“flush privileges”和“stop slave”后日志节点的内容会改变,所以如果不确定,每次执行此操作前必须要查看日志节点——show master status。另外,执行此操作时slave必须没有启动,如果之前执行了,那就先停止,指令:stop slave;

9.在两台主机上启动slave服务

start slave;

查看状态:

show slave statusG

结果如下:

上图表示成功

10.异常及解决方法

如果状态如下图所示:

往下看有错误提示,错误原因大致如下:

网络不通

账号密码错误

pos错误

3305端口未开放

解决方法如下:

1.网络不通——你相互ping一下各自的ip地址,ping的通就说明不是这个问题,我是开的两台虚拟机,在同一局域网内,所以肯定通,如果你用的是阿里云啊之类的外网服务器,ping不通就检查网络接口之类的。

2.账号密码错误——把两台主机的账号密码设置成相同的好处就是不会出现这种情况,我之前账号密码搞混弄了好久

3.pos错误——看看当前日志节点内容与你之前打的一样不,反正重新来一遍准没错

4.3305端口未开放:

找到iptables文件(etc/sysconfig/iptables)

再里面添加如下内容:

-A INPUT -m state --state NEW -m tcp -p tcp --dport 3305 -j ACCEPT

个人开放端口如下

重启防火墙:

service iptables restart

尝试一下能不能navecat远程链接数据库,不行的话就直接把防火墙关了。

在数据库相互授权的过程中可能会报错

原因,设置的密码太简单,不符合MySQL5.7的默认要求

如果想要密码设置简单点,方法如下:

mysql > set global validate_password_policy=0;
mysql > set global validate_password_length=4;

上述是把密码程度设置成最低级,密码长度设置成4(最小是4,不能再少了)

在MySQL数据库中,在进行数据迁移和从库只读状态设置时,都会涉及到只读状态和Master-slave的设置和关系。

经过实际测试,对于MySQL单实例数据库和master库,如果需要设置为只读状态,需要进行如下操作和设置:
将MySQL设置为只读状态的命令:
mysql -uroot -p
mysql> show global variables like "%read_only%";
mysql> flush tables with read lock;
mysql> set global read_only=1;
mysql> show global variables like "%read_only%";

将MySQL从只读设置为读写状态的命令:
mysql> unlock tables;
mysql> set global read_only=0;

对于需要保证master-slave主从同步的salve库,如果要设置为只读状态,需要执行的命令为:
mysql> set global read_only=1;

将salve库从只读状态变为读写状态,需要执行的命令是:
mysql> set global read_only=0;

 对于数据库读写状态,主要靠 “read_only”全局参数来设定;默认情况下,数据库是用于读写操作的,所以read_only参数也是0或faluse状态,这时候不论是本地用户还是远程访问数据库的用户,都可以进行读写操作;如需设置为只读状态,将该read_only参数设置为1或TRUE状态,但设置 read_only=1 状态有两个需要注意的地方:
  1.read_only=1只读模式,不会影响slave同步复制的功能,所以在MySQL slave库中设定了read_only=1后,通过 show slave status\G 命令查看salve状态,可以看到salve仍然会读取master上的日志,并且在slave库中应用日志,保证主从数据库同步一致;
  2.read_only=1只读模式,可以限定普通用户进行数据修改的操作,但不会限定具有super权限的用户的数据修改操作;在MySQL中设置read_only=1后,普通的应用用户进行insert、update、delete等会产生数据变化的DML操作时,都会报出数据库处于只读模式不能发生数据变化的错误,但具有super权限的用户,例如在本地或远程通过root用户登录到数据库,还是可以进行数据变化的DML操作;

-------锁表---

  为了确保所有用户,包括具有super权限的用户也不能进行读写操作,就需要执行给所有的表加读锁的命令 “flush tables with read lock;”,这样使用具有super权限的用户登录数据库,想要发生数据变化的操作时,也会提示表被锁定不能修改的报错。

    这样通过 设置“read_only=1”和“flush tables with read lock;”两条命令,就可以确保数据库处于只读模式,不会发生任何数据改变,在MySQL进行数据库迁移时,限定master主库不能有任何数据变化,就可以通过这种方式来设定。

   但同时由于加表锁的命令对数据库表限定非常严格,如果再slave从库上执行这个命令后,slave库可以从master读取binlog日志,但不能够应用日志,slave库不能发生数据改变,当然也不能够实现主从同步了,这时如果使用 “unlock tables;”解除全局的表读锁,slave就会应用从master读取到的binlog日志,继续保证主从库数据库一致同步。

   为了保证主从同步可以一直进行,在slave库上要保证具有super权限的root等用户只能在本地登录,不会发生数据变化,其他远程连接的应用用户只按需分配为select,insert,update,delete等权限,保证没有super权限,则只需要将salve设定“read_only=1”模式,即可保证主从同步,又可以实现从库只读。
   相对的,设定“read_only=1”只读模式开启的解锁命令为设定“read_only=0”;设定全局锁“flush tables with read lock;”,对应的解锁模式命令为:“unlock tables;”.

  当然设定了read_only=1后,所有的select查询操作都是可以正常进行的。

主库配置

binlog存放目录和文件名前缀, 或者至设置日志文件名
log-bin=/data/mysql/logs/binlog/bin-log
log-bin = mysql-bin

日志格式,建议mixed防止主键重复
statement 保存SQL语句
row 保存影响记录数据
mixed 前面两种的结合
binlog_format = mixed

主数据库端ID号
server-id = 1

不同步哪些数据库
binlog-ignore-db = mysql
binlog-ignore-db = test
binlog-ignore-db = information_schema
binlog-ignore-db = performance_schema

只同步哪些数据库,除此之外,其他不同步
binlog-do-db = game

日志保留时间
expire_logs_days = 7

控制binlog的写入频率。每执行多少次事务写入一次
这个参数性能消耗很大,但可减小MySQL崩溃造成的损失
不配置sync_binlog = 100

max_binlog_size = 200M
binlog_cache_size = 128K

从库的操作是否也要写入binlog,用于主主 或者 主从从结构
log-slave-updates = 0

主库创建帐号给从库去拉取binlog

grant replication slave on . to 'slave'@'%' identified by '123456';
flush privileges;

查询master状态,得到最新的File和Position
show master status;


MySQL提供一个sync_binlog参数来控制数据库的binlog刷到磁盘上去。

默认,sync_binlog=0,表示MySQL不控制binlog的刷新,由文件系统自己控制它的缓存的刷新。这时候的性能是最好的,但是风险也是最大的。因为一旦系统Crash,在binlog_cache中的所有binlog信息都会被丢失。

如果sync_binlog>0,表示每sync_binlog次事务提交,MySQL调用文件系统的刷新操作将缓存刷下去。最安全的就是sync_binlog=1了,表示每次事务提交,MySQL都会把binlog刷下去,是最安全但是性能损耗最大的设置。这样的话,在数据库所在的主机操作系统损坏或者突然掉电的情况下,系统才有可能丢失1个事务的数据。但是binlog虽然是顺序IO,但是设置sync_binlog=1,多个事务同时提交,同样很大的影响MySQL和IO性能。虽然可以通过group commit的补丁缓解,但是刷新的频率过高对IO的影响也非常大。对于高并发事务的系统来说,“sync_binlog”设置为0和设置为1的系统写入性能差距可能高达5倍甚至更多。

所以很多MySQL DBA设置的sync_binlog并不是最安全的1,而是100或者是0。这样牺牲一定的一致性,可以获得更高的并发和性能。


从库配置

server-id =2

连接断开时,重新连接超时时间
stop slave;
change master to master_connect_retry=50;

change master to master_host='192.168.1.2',master_user='slave',master_password='123456',master_log_file='mysql-bin.000009',master_log_pos=196;

基于位点的主备切换

CHANGE MASTER TO
MASTER_HOST=$host_name
MASTER_PORT=$port
MASTER_USER=$user_name
MASTER_PASSWORD=$password
MASTER_LOG_FILE=$master_log_name
MASTER_LOG_POS=$master_log_pos

mysql5.6开始基础GTID

CHANGE MASTER TO
MASTER_HOST=$host_name
MASTER_PORT=$port
MASTER_USER=$user_name
MASTER_PASSWORD=$password
master_auto_position=1

start slave;
show slave statusG;
IF

Slave_IO_Running === 'Yes' && Slave_SQL_Running === 'Yes'

ELSE

failed

ENDIF

故障恢复是主动跳过从库里的binlog的一个事务
stop slave;
set global sql_slave_skip_counter=1;
start slave;

为了避免传回后对主库造成影响,要通过 set sql_log_bin=off 关掉binlog,但是操作可能会导致数据和日志不一致

提问之前

在通过电邮、新闻组或者聊天室提出技术问题前,检查你有没有做到:

  1. 通读手册,试着自己找答案。
  2. 在FAQ里找答案(一份维护得好的FAQ可以包罗万象:)。
  3. 在网上搜索(个人推荐google~~~)。
  4. 向你身边精于此道的朋友打听。

当你提出问题的时候,首先要说明在此之前你干了些什么;这将有助于树立你的形象:你不是一个妄图不劳而获的乞讨者,不愿浪费别人的时间。如果提问者能从答案中学到东西,我们更乐于回答他的问题。

周全的思考,准备好你的问题,草率的发问只能得到草率的回答,或者根本得不到任何答案。越表现出在寻求帮助前为解决问题付出的努力,你越能得到实质性的帮助。

小心别问错了问题。如果你的问题基于错误的假设,普通黑客(J. Random Hacker)通常会用无意义的字面解释来答复你,心里想着“蠢问题…”,希望着你会从问题的回答(而非你想得到的答案)中汲取教训。

决不要自以为够资格得到答案,你没这种资格。毕竟你没有为这种服务支付任何报酬。你要自己去“挣”回一个答案,靠提出一个有内涵的,有趣的,有思维激励作用的问题–一个对社区的经验有潜在贡献的问题,而不仅仅是被动的从他人处索要知识–去挣到这个答案。

另一方面,表明你愿意在找答案的过程中做点什么,是一个非常好的开端。“谁能给点提示?”、“我这个例子里缺了什么?”以及“我应该检查什么地方?”比“请把确切的过程贴出来”更容易得到答复。因为你显得只要有人指点正确的方向,你就有完成它的能力和决心。

怎样提问

  • 谨慎选择论坛

小心选择提问的场合。如果象下面描述的那样,你很可能被忽略掉或者被看作失败者:

  1. 在风马牛不相及的论坛贴出你的问题
  2. 在探讨高级技巧的论坛张贴非常初级的问题;反之亦然
  3. 在太多的不同新闻组交叉张贴
  • 用辞贴切,语法正确,拼写无误

我们从经验中发现,粗心的写作者通常也是马虎的思考者(我敢打包票)。 回答粗心大意者的问题很不值得,我们宁愿把时间耗在别处。

正确的拼写,标点符号和大小写很重要。

更一般的说,如果你的提问写得象个半文盲,你很有可能被忽视。

如果你在使用非母语的论坛提问,你可以犯点拼写和语法上的小错–但决不能在思考上马虎(没错,我们能弄清两者的分别)。

  • 使用含义丰富,描述准确的标题

在邮件列表或者新闻组中,大约50字以内的主题标题是抓住资深专家注意力的黄金时机。别用喋喋不休的“帮帮忙”(更别说“救命啊!!!!!”这样让人反感的话)来浪费这个机会。不要妄想用你的痛苦程度来打动我们, 别用空格代替问题的描述,哪怕是极其简短的描述。

蠢问题: 救命啊!我的膝上机不能正常显示了!

聪明问题: XFree86 4.1下鼠标光标变形,Fooware MV1005的显示芯片。

如果你在回复中提出问题,记得要修改内容标题,表明里面有一个问题。一个看起来象“Re:测试”或者“Re:新bug”的问题很难引起足够重视。另外,引用并删减前文的内容,给新来的读者留下线索。

  • 精确描述,信息量大
  1. 谨慎明确的描述症状。
  2. 提供问题发生的环境(机器配置、操作系统、应用程序以及别的什么)。
  3. 说明你在提问前是怎样去研究和理解这个问题的。
  4. 说明你在提问前采取了什么步骤去解决它。
  5. 罗列最近做过什么可能有影响的硬件、软件变更。

尽量想象一个黑客会怎样反问你,在提问的时候预先给他答案。

Simon Tatham写过一篇名为《如何有效的报告Bug》的出色短文。强力推荐你也读一读。

  • 话不在多

你需要提供精确有效的信息。这并不是要求你简单的把成吨的出错代码或者数据完全转储摘录到你的提问中。如果你有庞大而复杂的测试条件,尽量把它剪裁得越小越好。

转载自提问的艺术