












新加坡地处亚洲马来半岛的最南端,北部与马来西亚接壤,南部与印度尼西亚隔海相望。
新加坡是世界上最小的国家之一,国土面积比香港还要小。然而,在如此“袖珍”的国度中却孕育着最丰富的异国文化。牛车水(唐人街)的中华风情、小印度的色彩斑斓、甘榜格南的中东特色、荷兰村的欧美风尚,无一不展现着这个移民国家多元的文化精粹。
素有“花园城市”的新加坡将自然之美与现代化都市完美结合,随处可见的花花草草一改人们对都市“钢铁泥墙”的印象。你可以踏上欢乐圣地圣淘沙岛玩遍数不尽数的游乐项目,也可以奔向拥有百余家商场的乌节路血拼购物。位于北部雨林中的日夜间动物园则是亲子游的首选。夜幕降临下的滨海湾,更是与地标金沙酒店和鱼尾狮像合影的好时机,搭上全球最高的飞行者摩天轮还能将整个滨海湾尽收眼底。
8.1凌晨的✈飞机,从上海浦东到新加坡,中途马来西亚吉隆坡转机。
一下飞机TAXI到酒店,中途感觉风景很好。真的是花园城市,非常适合移民。这边大部分人都会中文交流,只有少数的马来西亚人不会中文。
到新加坡皮克林宾乐雅酒店 (PARKROYAL On Pickering)已经14:00左右。


五星级酒店,服务员态度很好。这边的酒店都是15:00客人才退房。我们入住必须等到15:00只有才行。
虽然我的English很烂,但是酒店Check in 还是没有问题的。
新加坡消费很高,SHOPPING MALL里面一碗上档次的面都要20+新加坡币。

Linode商家我们肯定不算陌生,老季从开始接触VPS主机就接触的这家,早年这家机器可谓高富帅,而且相当的难买,至今也只能支持信用卡注册账户付款充值。早年Linode商家线路还算是比较优秀的,尤其是当初的日本JP1机房的速度比较适合建站,但是前一段时间彻底的取消下架。目前,Linode商家机房倒是蛮多的,而且7.17号上线印度孟买机房。
Linode VPS官方直达:https://www.linode.com/
看名称以为是亚洲机房速度估计可以,但是可以料想到肯定不是针对我们国内用户需求的,速度上肯定不会直连。应该是类似我们熟悉的一些商家在部署各地区的用户需求,比如印度机房应该是针对印度用户的,对于我们大部分网友来说需求不大,但是如果有印度项目的可能会有用到。
目前,Linode商家最低配置是1GB内存、25GB硬盘、1TB月流量5美金一个月。
我们使用官方提供的测试IP( speedtest.mumbai1.linode.com )测试速度,可以看到移动和联通勉强可用,电信的请看下图。

如果是安安稳稳的做站的话还是可以买的,如果想用来做别的事情不推荐。

今天说一下MySQL的主从复制如何做到?我们这里直接使用Docker来配置。
我们这里要做得是将jmysql2数据库容器自动同步jmysql数据库容器里的数据。
开始前务必将jmysql、jmysql2数据库及所有表内容同步。
docker run -d --name jmysql -v D:\mysqlData:/var/lib/mysql -p 3307:3306 -e MYSQL_ROOT_PASSWORD=jjjjjj mariadb
docker run -d --name jmysql2 -v D:\mysqlData2:/var/lib/mysql -p 3308:3306 -e MYSQL_ROOT_PASSWORD=jjjjjj --link jmysql mariadb这里建立的Mariadb的root密码均为:jjjjjj
jmysql2必须要添加 --link jmysql 参数 ,否则无法连接到jmysql服务器。
docker exec -it jmysql /bin/bash
docker exec -it jmysql2 /bin/bash
apt-get update ; apt-get install vim -y原理:mysql要做到主从复制,其实依靠的是二进制日志,即:假设主服务器叫A,从服务器叫B;主从复制就是
B跟着A学,A做什么,B就做什么。那么B怎么同步A的动作呢?现在A有一个日志功能,把自己所做的增删改查的动作
全都记录在日志中,B只需要拿到这份日志,照着日志上面的动作施加到自己身上就可以了。这样就实现了主从复制。
扩展:MYSQL还有一种日志叫做:慢日志
可以设置一个时间,那么所有执行时间超过这个时间的SQL都会被记录下来。这样就可以通过慢日志快速的找到网站中SQL的瓶颈来进行优化。
大家有时间可以研究一下,这里不多做介绍。
打开主服务器的mysql配置文件:my.conf
vi /etc/mysql/my.cnf加入如下代码:
server-id = 111
log_bin = /var/log/mysql/mariadb-bin
#binlog日志只记录指定库的更新
#binlog-do-db=db_name
#binlog日志不记录指定库的更新
#binlog-ignore-db=db_name
参数解释:
log-bin=mysql-bin //将mysql二进制日志取名为mysql-bin
binlog_format=mixed //二进制日志的格式,有三种:statement/row/mixed,具体分别不多做解释,这里使用mixed
server-id=111 //为服务器设置一个独一无二的id便于区分,这里使用ip地址的最后一位充当server-id
配置完成,:wq 保存,重启mysql
重启mysql命令:#
service mysqld restart同样的,进入从服务器,配置从服务器的my.cnf,重复步骤1即可,
唯一的区别是,server-id要改成从服务器的ip尾位,即server-id=1;其他两项是一样的,保存,并重启mySQL;
进入主服务器的mysql界面,命令:
mysql -u root -p 111111 //我这里mysql账号是root,密码是111111在mysql操作界面下,输入下面一行命令:
GRANT replication slave ON *.* TO 'slave'@'%' IDENTIFIED BY '111111'; 
show master status;
进入从服务器mysql,命令:
mysql -u root -p111111关闭slave(如果你以前配置过主从的话,一定要先关闭),命令:
stop slave;开始配置:输入下面代码即可:
change master to master_host="jmysql", master_user="slave", master_password='111111', master_log_file="mariadb-bin.000001" , master_log_pos=330;
参数解释:
MASTER_HOST : 设置要连接的主服务器的ip地址
MASTER_USER : 设置要连接的主服务器的用户名
MASTER_PASSWORD : 设置要连接的主服务器的密码
MASTER_LOG_FILE : 设置要连接的主服务器的bin日志的日志名称,即第3步得到的信息
MASTER_LOG_POS : 设置要连接的主服务器的bin日志的记录位置,即第3步得到的信息,(这里注意,最后一项不需要加引号。否则配置失败)
先在从服务器配置完成,启动从服务器,命令:
start slave;show slave status;上面两项均为yes,说明配置成功,否则,请重复前面的步骤。

ok,到这里MySQL的主从复制就配置完了,其实明白原理的话还是很简单的,
这里就不给大家测试了,大家配置完可以自己测试一下,有什么问题的话,


goto 操作符可以用来跳转到程序中的另一位置。该目标位置可以用目标名称加上冒号来标记,而跳转指令是 goto 之后接上目标位置的标记。PHP 中的 goto 有一定限制,目标位置只能位于同一个文件和作用域,也就是说无法跳出一个函数或类方法,也无法跳入到另一个函数。也无法跳入到任何循环或者 switch 结构中。可以跳出循环或者 switch,通常的用法是用 goto 代替多层的 break。
Note:
goto 操作符仅在 PHP 5.3及以上版本有效。
<?php
goto a;
echo 'Foo';
a:
echo 'Bar';以上例程会输出:
Bar
<?php
for($i=0,$j=50; $i<100; $i++) {
while($j--) {
if($j==17) goto end;
}
}
echo "i = $i";
end:
echo 'j hit 17';以上例程会输出:
j hit 17

前面我们写了关于Docker的一些内容,现在我们需要在容器中开启php对Memcached的扩展。网上找了一些资料,下面我们直接贴出命令行。
docker exec -it jphp-fpm /bin/bashjphp-fpm 是我们创建容器时给的容器名。
注意:我们这里使用的是 bitnami/php-fpm 的套件。
apt-get update -y && apt-get install -y pkg-config libmemcached-dev autoconf gcc make zlib1g zlib1g-dev vimpecl channel-update pecl.php.net && pecl install memcached通过phpinfo里Loaded Configuration File,我们看到php.ini的位置:/opt/bitnami/php/lib/php.ini
echo 'extension=memcached.so' >> /opt/bitnami/php/lib/php.inidocker restart jphp-fpm
今天在Docker容器中安装php-memcached扩展,报如下错误:
sh: make: not found
make 没安装,Linux(Debian、Ubuntu)终端中执行以下命令即可:
apt-get update
apt-get install makeCentos、Redhat下执行:
yum update
yum install make
create table select from 和 insert into table select from都是用来复制表,两者的主要区别为:
create table select from 要求目标表不存在,因为在插入时会自动创建。
insert into table select from 要求目标表存在,相当于复制插入。
备份表数据:
create table tmp_article_info as select * from article_info还原表数据:
insert into tmp_article_info select * from article_info只复制表结构:
create table tmp_article_info as select * from article_info where 1=0只复制表数据(如果两个表结构完全一样):
insert into tmp_article_info select * from article_info只复制表数据(如果两个表结构不一样,或者部分复制):
insert into tmp_article_info (column1,column2…) select column1,column2 from article_info
前面几篇我们学习了Docker的相关知识:
下面我们记录一下如何在系统重启之后,使Docker容器自动启动。
systemctl enable docker.service在运行docker容器时可以加如下参数来保证每次docker服务重启后容器也自动重启:
--restart=always–restart具体参数值详细信息:
no – 容器退出时,不重启容器;
on-failure – 只有在非0状态退出时才从新启动容器;
always – 无论退出状态是如何,都重启容器;
如果已经启动了则可以使用如下命令:
docker update --restart=always <CONTAINER ID>docker ps -a通过这里 STATUS 来判断是否已启动。

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
eee0acf086c8 nginx “nginx -g ‘daemon …” 3 hours ago Up 4 minutes 0.0.0.0:80->80/tcp jnginx
cf8ad8125a4c bitnami/php-fpm “php-fpm -F –pid …” 3 hours ago Up 5 minutes 9000/tcp jphp-fpm
ab6dea2ab176 memcached “docker-entrypoint…” 2 days ago Up 5 minutes 0.0.0.0:11211->11211/tcp jmemcached
f0df7b311a41 mariadb “docker-entrypoint…” 2 days ago Up 5 minutes 0.0.0.0:3306->3306/tcp jmysql

svn import project_dir(本地项目全路径) http://192.168.1.242:8080/svn/IOS/Ben/remote_dir(svn项目全路径) -m “必填, 不填此命令执行不会成功.”
注: 服务器上remote_dir若不存在, 会自动创建;
只会上传project_dir目录下的文件到remote_dir的目录下
import之后, project_dir并没有自动转化为工作目录, 需要重新checkout(后面会用到)
svn checkout http://192.168.1.242:8080/svn/IOS/remote_dir (svn项目全路径)project_dir(本地目录全路径) –username 用户名 –password 密码
svn checkout 简写:svn co
svn add file(文件名)
svn add *.php(添加当前目录下所有的php文件)
svn commit -m “LogMessage” [-N] [–no-unlock] PATH(如果选择了保持锁,就使用–no-unlock开关)
svn commit -m “提交当前目录下的全部在版本控制下的文件“ * ( *表示全部文件 )
例如:svn commit -m “add test file for my test” test.php
svn commit -m “提交我的测试用test.php“ -N –no-unlock test.php ( 保持锁就用–no-unlock开关 )
注意:必须带上-m参数,参数可以为空(””)
svn commit 简写:svn ci
svn update
svn update -r 修正版本 文件名
svn update 文件名
例如:
svn update (后面没有目录,默认将当前目录以及子目录下的所有文件都更新到最新版本)
svn update -r 200 test.cpp ( 将版本库中的文件 test.cpp 还原到修正版本(revision)200)
svn update test.php ( 更新与版本库同步 )
提交的时候提示过期冲突,需要先 update 修改文件,
然后清除svn resolved,最后再提交commit。
svn update 间写: svn up
1)svn status path(目录下的文件和子目录的状态,正常状态不显示)
【?:不在svn的控制中;M:内容被修改;C:发生冲突;A:预定加入到版本库;K:被锁定】
2)svn status -v path(显示文件和子目录状态)
第一列保持相同,第二列显示工作版本号,第三和第四列显示最后一次修改的版本号和修改人。
注:svn status、svn diff、svn revert这三条命令在没有网络的情况下也可以执行的,原因是svn在本地的.svn中保留了本地版本的原始拷贝。
svn status 简写:svn st
svn delete path -m “delete test fle”
例如:svn delete svn://192.168.1.1/pro/domain/test.php -m “delete test file”
推荐使用:
svn delete test.php
svn ci -m ‘delete test file‘
svn delete 简写:svn del/remove/rm
svn log path
svn log -l 3查看最新的三条记录
例如:svn log test.php
svn info path
例如:svn info test.php
svn diff path(将修改的文件与基础版本比较)
例如:svn diff test.php
svn diff -r m:n path(对版本m和版本n比较差异)
例如:svn diff -r 200:201 test.php
svn diff 简写:svn di
svn merge -r m:n path
例如:
svn merge -r 200:205 test.php(将版本200与205之间的差异合并到当前文件,但是一般都会产生冲突,需要处理一下)
svn help 全部功能选项
svn help ci 具体功能的说明
svn list path
显示path目录下的所有属于版本库的文件和目录
svn list 简写:svn ls
svn mkdir newdir
例如:
svn mkdir -m “Making a new dir.” svn://localhost/test/newdir
用法: 1、mkdir PATH…
2、mkdir URL…
创建版本控制的目录。
1、每一个以工作副本 PATH 指定的目录,都会创建在本地端,并且加入新增
调度,以待下一次的提交。
2、每个以URL指定的目录,都会透过立即提交于仓库中创建。
(在这两个情况下,所有的中间目录都必须事先存在)
注:添加完子目录后,一定要回到根目录更新svn update一下,不然在该目录下提交文件会提示“提交失败”
注:如果手动在checkout出来的目录里创建了一个新文件夹newsubdir,
再用svn mkdir newsubdir命令后,SVN会提示:
svn: 尝试用 “svn add”或 “svn add –non-recursive”代替?
svn: 无法创建目录“hello”: 文件已经存在
此时,用如下命令解决:
svn add –non-recursive newsubdir
在进入这个newsubdir文件夹,用ls -a查看它下面的全部目录与文件,会发现多了:.svn目录
再用 svn mkdir -m “添hello功能模块文件” svn://localhost/test/newdir/newsubdir 命令,
SVN提示:
svn: File already exists: filesystem ‘/data/svnroot/test/db’, transaction ‘4541-1’,
path ‘/newdir/newsubdir ‘
svn revert: 恢复原始未改变的工作副本文件 (恢复大部份的本地修改)。
用法: revert PATH…
注意: 本子命令不会存取网络,并且会解除冲突的状况。但是它不会恢复
被删除的目录
svn revert foo.c <- 丢弃对一个文件的修改
svn revert –recursive . <-恢复一整个目录的文件,. 为当前目录
svn switch (sw): 更新工作副本至不同的URL。
用法: 1、switch URL [PATH]
2、switch –relocate FROM TO [PATH…]
1、更新你的工作副本,映射到一个新的URL,其行为跟“svn update”很像,也会将
服务器上文件与本地文件合并。这是将工作副本对应到同一仓库中某个分支或者标记的
方法。
2、改写工作副本的URL元数据,以反映单纯的URL上的改变。当仓库的根URL变动
(比如方案名或是主机名称变动),但是工作副本仍旧对映到同一仓库的同一目录时使用
这个命令更新工作副本与仓库的对应关系。
svn switch 间写: svn sw
svn resolved: 移除工作副本的目录或文件的“冲突”状态。
用法: resolved PATH…
注意: 本子命令不会依语法来解决冲突或是移除冲突标记;
它只是移除冲突的相关文件,然后让 PATH 可以再次提交。
svn cat 目标[@版本]…如果指定了版本,将从指定的版本开始查找。
svn cat -r PREV filename > filename (PREV 是上一版本,也可以写具体版本号,这样输出结果是可以提交的)
svn —-version
1、svn mkdir branches
2、svn copy svn://server/trunk svn://server/branches/ep -m “init ep”
1、svn mkdir tags
2、svn copy svn://server/trunk svn://server/tags/release-1.0 -m “1.0 released”
使用发生的一些问题:
1、错误:
svn: Could not use external editor to fetch log message;
consider setting the $SVN_EDITOR environment variable or using the
–message (-m) or –file (-F) options
svn: None of the environment
variables SVN_EDITOR, VISUAL or EDITOR is set, and no ‘editor-cmd’
run-time configuration option was found
问题原因是:
没有设置svn编辑器的环境变量,主要是import、commit中填写comment要用
解决方法:
1、在 终端中 sudo vim /etc/bashrc 打开文件
加入:export SVN_EDITOR=vim
2、编辑完以后一般需要让配置文件立即生效,可执行命令:
source /etc/bashrc(也可以不进行这一步)
2、问题:
不小心提交了一些动态改变根本不需要的文件到svn服务器上
解决:
svn resolved filename 放弃对文件的修改,
svn ci -m “update” 提交所有文件
svn rm test.log 删除掉这个文件。
svn ci -m “update” 再次提交
3、发生冲突:
两人同时修改同一文件同一部分,先后提交,出现冲突
svn ci -m “update”
svn: Commit failed (details follow):
svn: Aborting commit: ‘test.log’ remains in conflict
解决:
A、放弃自己的更新,使用svn revert(回滚),然后提交。在这种方式下不需要使用svn resolved(解决)
B、放弃自己的更新,使用别人的更新。使用最新获取的版本覆盖目标文件,执行resolved filename并提交(选择文件—右键—解决)。
C、手动解决:冲突发生时,通过和其他用户沟通之后,手动更新目标文件。然后执行resolved filename来解除冲突,最后提交。
坚持使用自己的更新,找到.mine的文件名,恢复为原文件名,然后执行:
svn resolved file_name