CentOS 自启动失败分析

场景

Tony哥从家里搬来了一台机器做公司内网开发机,我给它上面装了 CentOS 6.6

失败情况

想要服务器自启动执行某些 sh 脚本,想当然加在 /etc/rc.local 里,但不执行。

解决办法:

1、先查看 /etc/rc.d/rc3.d/S99local 指向哪个文件

有些系统指向的是 /etc/rc.local,有一些是 /etc/rc.d/rc.local。

CentOS 6.6 指向的就是:/etc/rc.d/rc.local

2、保证该文件有可执行权限

chmod +x /etc/rc.d/rc.local

3、将 /etc/rc.local 重新软连接为 /etc/rc.d/rc.local

ln -sf /etc/rc.d/rc.local /etc/rc.local

OAuth 回顾小结

突然发现没啥好写了,从 OAuth1.0 到 1.0a,再到 OAuth2.0,现在街上 OAuth 的授权原理和流程介绍已经很多了,哪天有空再把一些安全或漏洞补一下吧。

可能想说的点:

  • OAuth1.0 有什么漏洞?1.0a 修复了哪些问题?(回跳地址劫持)
  • OAuth2.0 比 1.0 改变了哪些?为啥要用 HTTPS?
  • OAuth2.0 的 state 字段的作用?(如何防止 CSRF)

MySQL Replication 主从同步原理

Alt text

一共有三个线程:

  1. 主库上的 IO 线程
  2. 从库上的 IO 线程
  3. 从库上的 SQL 线程

大致描述一下过程:

从库的 IO 线程从主库获取二进制日志,并在本地保存为中继日志,然后通过SQL线程来在从上执行中继日志中的内容,从而使从库和主库保持一致。

  1. 主库验证连接。
  2. 主库为从库开启一个 IO 线程。
  3. 从库将主库日志的偏移位告诉主库。
  4. 主库检查该值是否小于当前二进制日志偏移位。
  5. 如果小于,则通知从库来取数据。
  6. 从库持续从主库取数据,直至取完,这时,从库线程进入睡眠,主库线程同时进入睡眠。
  7. 当主库有更新时,主库线程被激活,并将二进制日志推送给从库,并通知从库线程进入工作状态。
  8. 从库SQL线程执行二进制日志,随后进入睡眠状态。

详细的基本交互过程:

  1. slave 端的 IO 线程连接上 master 端,并请求从指定 binlog 日志文件的指定 pos 节点位置(或者从最开始的日志)开始复制之后的日志内容。

  2. master 端在接收到来自 slave 端的 IO 线程请求后,通知负责复制进程的 IO 线程,根据 slave 端 IO 线程的请求信息,读取指定 binlog 日志指定 pos 节点位置之后的日志信息,然后返回给 slave 端的 IO 线程。该返回信息中除了 binlog 日志所包含的信息之外,还包括本次返回的信息在 master 端的 binlog 文件名以及在该 binlog 日志中的 pos 节点位置。

  3. slave 端的 IO 线程在接收到 master 端 IO 返回的信息后,将接收到的 binlog 日志内容依次写入到 slave 端的 relaylog 文件(mysql-relay-bin.xxxxxx)的最末端,并将读取到的 master 端的 binlog 文件名和 pos 节点位置记录到 master-info(该文件存在 slave 端)文件中,以便在下一次读取的时候能够清楚的告诉 master “我需要从哪个 binlog 文件的哪个 pos 节点位置开始,请把此节点以后的日志内容发给我”。

  4. slave 端的 SQL 线程在检测到 relaylog 文件中新增内容后,会马上解析该 log 文件中的内容。然后还原成在 master 端真实执行的那些 SQL 语句,并在自身按顺丰依次执行这些SQL语句。这样,实际上就是在 master 端和 slave 端执行了同样的 SQL 语句,所以 master 端和 slave 端的数据是完全一样的。

以前的 MySQL 里,Slave 端的复制是由单独的一个 IO 线程来完成的(简而言之就是没有用 SQL Relay 队列)。这样存在几个问题:

  1. 从库上的 IO 线程要串行完成一系列操作:拉取+解析+执行 master binlog,执行时间比较长。

  2. 执行延迟越长,主库数据丢失的风险就越大,主库是希望从库尽可能零延迟、无间歇地来拉取数据的。一旦存在较长拉取延迟,那么在此期间 master 挂了,还没来得及被从库拉取的那一部分数据,将永远的丢失,所以我们要想办法尽可能地提高从库拉取数据的频次和效率。

  3. 新版将 Slave 端的复制改为两个线程来完成,IO 线程只负责从主库读取 SQL 并推到中继日志队列里就完事,SQL 线程则只负责从中继日志队列里依次弹出并执行SQL。这样缩短了从库的延迟时间,就减少了潜在的丢失数据的风险。

  4. 当然,即使是换成了现在这样两个线程来协作处理之后,Slave 仍然存在丟数据的可能,毕竟复制是异步的,只要数据的更改不是在一个事务中,这些问题都是存在的。

Memcached 的一些小结

阶段一哈希(客户端做,负责找出目标服务器)

阶段二哈希(服务端运算,负责根据键找出值)

memcache key 的长度最大为 250 字符,value 长度最大为1M

Memcache VS MySQL Query Cache

  1. MySQL Query Cache 是表级别,只要表中数据有变化,跟表有关的所有 Query Cache 都被清除
  2. Memcache 更加灵活,除了缓存 SQL 结果集外,还可以缓存更丰富的数据集合(例如玩家名片信息)
  3. Memcache 集群水平扩展成本低,要加内存,只需要加一堆廉价PC机,
  4. MySQL Query Cache 只能缓存到本机,如果加内存,成本高,扩展不方便

同步、异步、阻塞、非阻塞的理解

同步与异步

同步和异步关注的是消息通信机制 (synchronous communication/ asynchronous communication)

所谓同步,就是在发出一个调用时,由调用者主动等待这个调用的结果。

而异步则是相反,调用在发出之后,调用者不会立刻得到结果。 而是在调用发出后,被调用者通过状态、通知来通知调用者,或通过回调函数处理这个调用。

典型的异步编程模型比如 Node.js

阻塞与非阻塞

阻塞和非阻塞关注的是程序在等待调用结果时的自身的状态.

阻塞调用是指调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会返回。 非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程。

在处理 IO 的时候,阻塞和非阻塞都是同步 IO。只有使用了特殊的 API 才是异步 IO。

举个栗子

老张爱喝茶,废话不说,煮开水。出场人物:老张,水壶两把(普通水壶,简称水壶;会响的水壶,简称响水壶)。

1、老张把水壶放到火上,立等水开。(同步阻塞)老张觉得自己有点傻

2、老张把水壶放到火上,去客厅看电视,时不时去厨房看看水开没有。(同步非阻塞)老张还是觉得自己有点傻,于是变高端了,买了把会响笛的那种水壶。水开之后,能大声发出嘀~~~~的噪音。

3、老张把响水壶放到火上,立等水开。(异步阻塞)老张觉得这样傻等意义不大

4、老张把响水壶放到火上,去客厅看电视,水壶响之前不再去看它了,响了再去拿壶。(异步非阻塞)老张觉得自己聪明了。

所谓同步异步,只是对于水壶而言。普通水壶,同步;响水壶,异步。虽然都能干活,但响水壶可以在自己完工之后,提示老张水开了。这是普通水壶所不能及的。同步只能让调用者去轮询自己(情况2中),造成老张效率的低下。

所谓阻塞非阻塞,仅仅对于老张而言。立等的老张,阻塞;看电视的老张,非阻塞。情况1和情况3中老张就是阻塞的,媳妇喊他都不知道。虽然3中响水壶是异步的,可对于立等的老张没有太大的意义。所以一般异步是配合非阻塞使用的,这样才能发挥异步的效用。

参考文章:

MySQL 字段类型 varchar 和 text 类型的区别

MySQL 字段类型 varchar 和 text 类型的区别

  1. text 不允许有默认值,varchar允许有默认值
  2. varchar 可以替代 tinytext
  3. 如果存储的数据大于64K,就必须使用到 mediumtext/longtext
  4. varchar(255+) 和 text 在存储机制是一样的
  5. varchar(65535+) 和 mediumtext 在存储机制是一样的

需要特别注意varchar(255)不只是255byte ,实质上有可能占用的更多。

特别注意,varchar大字段一样的会降低性能,所以在设计中还是一个原则大字段要拆出去,主表还是要尽量的瘦小

参考原文:http://wubx.net/varchar-vs-text/