Becomin' Charles

算法 | LNMP | Flutter | Mac

Becomin' Charles

今天闲着没事,我将手机升级到iOS 8.1后,尝试了下国人出的越狱,据说,这是第一次由中国人率先出品了越狱的版本,盘古。

越狱过程流畅无比,但是看完越狱后的界面,一朵阴云已经浮上我的心头。在越狱的开始界面上,我明显去掉了“支持盘古,安装PP助手”的选项,然而越狱结果页面,赫然安装了PP助手。接着,我开始在Cydia中安装软件,莫名奇妙,突然打开了App Store,是游戏刀塔传奇的页面。

10分钟后,当App Store再次无故启动,定位到携程的页面的时候,我知道,我在自己的手机里,安装了一个巨大的流氓软件,而且还获得了root权限。我还傻傻的使用它的重置OpenSSH密码功能,我重置的任何密码,都会被它知道,不是么?

技术的运用,真的是存乎一心之间。盘古这种丧心病狂的行为,我已经不能多说什么了,你们势必在自取灭亡的道路上越走越远。以这种方式去运用技术来谋取商业利益,我也只能说,我羞于与这样的人为伍。

祝盘古早日倒闭。

我所在的企业,是一家中国知名互联网企业。我的团队,专门从事企业产品的研发。

说起大数据、机器学习,就像老师说的那样,这几个概念,真是一座山峰的不同侧面。其实从学术上看,这些东西难免高深难懂,有很多严谨的数学定义。但是,在企业的实践中,往往并没有那么神秘,也没有多难,我加入课程群,看到很多同学,都是在校学生,所以,我就在这里分享一下,我所在的企业,到底在哪些地方,用怎样的方法,运用了机器学习和数据挖掘。因为我也没有成体系学习过,只是入门选手,我就想到什么说什么了。

阅读全文 »

其实,这个是一类问题,在SVN里面,处理这个问题相对简单和直观,因为SVN的结构简单,只有工作副本和版本库副本两个副本,你要做的事情,无非就是处理工作副本,要么就是处理版本库副本。关于位置的概念,只有两个,工作副本,都是本地镜像,版本库副本,都在中心服务器上。commit能且只能保存在服务器上。回滚,本质上,只有两个情况,一个是没有commit,怎么回滚,一个是已经commit了,怎么回滚。

所以,在SVN中,回滚一个代码,事实上只有一个命令而已。svn revert。不指定版本号作为参数的话,就是放弃未提交的修改,指定版本号的话,就是回滚到指定的版本号(rev),但是实际上已经提交的更改,是不可以抹除的,你只能将一个文件回滚到某个过去的版本,然后重新提交来覆盖之前的变更。

到了Git里面,回滚这个事情,变复杂了。首先,我认为,工作副本的概念没有了,因为去中心化的设计,每个人本地硬盘上拥有的,都直接是版本库副本,没有所谓的本地副本的概念了,所有的人持有的都是版本库本身。就算在研发实践中,设置了中央版本库,但是中央版本库和本地版本库,在逻辑概念上是完全对等的。谁是中央,谁不是中央,其实是人为赋予的抽象地位。

另外一个显著的不同是,Git里的commit,都是直接提交到本地版本库的,这也就是commit速度飞快的原因。

在Git里,回滚这件事情,就一下子多出来好多的情况。

如果是一个人,直接通过git init在本地建立repository,不与任何人协作,有且仅有一个版本库。那么,情况只有两种:

  1. 未提交的变更
  2. 已经提交的变更

第一种情况,可以使用命令 git clean -fd ,来实现直接将所有的未提变化(untracked files)删除,-f的含义是force,强制,-d的意思是未提交的目录和文件都删除。

第二种情况,在单人开发的时候,也比较简单。很多处理方法,比如完全抹去这个commit(这在SVN里是做不到的),就像历史上从未发生过此事一样。要做到这一点,估计有好多种做法,但是我只掌握了一种,就是使用 git rebase -i HEAD2,这个命令的含义本身不是干这个事情的,只是我碰巧发现这么可以。-i的含义是interact,交互式,HEAD2的含义是,从最新的提交开始,显示两次提交的内容,然后你会在编辑页面看到两行提交的log,旧的在上面,新的在下面。如果你需要完全抹去最新的提交,就把下面的那行给删掉就行了。

这种情况下,根据我的实践经验来看,如果是一系列提交,要抹去中间的某个提交,十有八九不会顺利成功,原因也很简单,比如某a文件,你提交了10次,然后你想抹去第6次提交,那么git将极有可能不知道原来的第7次到第10次提交,应该怎么作用在a文件上,这时候,rebase过程被打断,你要手动处理冲突,才能完成任务。但是我想,一般我们不会干这种事情,因为,多数情况下,我们需要处理的都是最新几次连续的提交,比如想都放弃掉。

如果是跟他人协作开发的话,比如有一个管理员,设置了一个中央版本库,然后大家都以中央版本库的代码为基准,事情就将变得更加复杂一点,在上述两种情况之外,又会多出一些情况:

  1. 已经提交了,但是没有push到中央版本库
  2. 已经提交了,但是已经push到中央版本库

第一种情况,跟单人开发时候,第二种情况处理方法一样的。但是,你要非常小心的确认这件事情。该commit确实没有被push过。这种情况下,你甚至可以抹掉该commit,或者合并几个同样没有push的commit,都行。

第二种情况,你就要非常谨慎了。因为即使已经push过了,git不会阻止试图抹掉一个commit的行为,也不会阻止试图合并一些commit的行为。但是,你可能为此付出非常惨痛的代价,光是merge,就能累死你。这种情况下,我的建议,就是根本不要尝试去做。老老实实去checkout一个你认为没问题的版本,通过diff工具,将你想删掉的变更去掉,然后将这个作为一个新的commit附加到历史的洪流中。

如果你正在斯坦福、Coursera或者可汗学院学习在线课程,那么这种开始方式,已经很好了。

你可能还需要尽可能多地去学习数学(包括统计),因为数学是机器学习的基础。

我非常推荐的一本书是Programming Collective Intelligence。这本书的数学很浅,只需要基本理解Python就可以通读此书而没有什么障碍。如果你已经在学习大学级别的机器学习课程,你可能会觉得这本书对你来说太过基础了一点。

Programming Collective Intelligence: Building Smart Web 2.0 Applications: Toby Segaran

对于一些更高级的话题,你可以试试如下的书,基本按照需要数学知识的多少来排序:

Amazon.com: Risk Assessment and Decision Analysis with Bayesian Networks (9781439809105): Norman Fenton, Martin Neil: Books

Artificial Intelligence: A Modern Approach (3rd Edition): Stuart Russell, Peter Norvig: 9780136042594: Amazon.com: Books

Learning Bayesian Networks: Richard E. Neapolitan: 9780130125347: Amazon.com: BooksEdit

Quoar原帖

Updated:

另一个回帖的人,认为学习Machine Learning没那么简单,并提出该学科是一个高度交叉学科,想要深入,需要准备好很多先修课程的知识,包括但是不限于:

  1. 微积分。最好所有的知识都具备,极限(Limits),differentiation,integration。
  2. 线性代数。甚至要理解最简单的回归模型,都需要它的知识。通常是机器学习课程最先教的东西。
  3. 统计学。超级重要。机器学习其实是一族统计分析的方法,所以它是在统计学的根基上发展起来的。对所有的统计分析方法,有一个很好的掌握,是绝对必须的。
  4. 计算机科学基本知识。具体说,算法,包括数值算法(从牛顿法,到蒙特卡洛模拟技术)。这与机器学习在很多地方是重合的,而且经常被用于机器学习的一些基础算法。
  5. 编程。机器学习是一个应用学科,你需要掌握一门编程语言来运行算法。Python学习简单,在机器学习专家中,应用广泛。

想要把丢掉的东西捡起来,还是很辛苦啊,今天我就发现,我连char* 和 char []的区别都不知道。

1
2
3
4
5
6
7
8
9
10
11

#include

int main(int argc, char* argv[]) {
char* buf1 = "this is a test";
char buf2[] = "this is a test";
printf("size of buf1: %d\n", sizeof(buf1));
printf("size of buf2: %d\n", sizeof(buf2));
return 0;
}

结果是:

1
2
3
4
5

$ > ./main
size of buf1: 4
size of buf2: 15

购买了Linode的同学,一般都会在Linode上安装部署各类技术解决方案,解决程序员的信息查找和咨询访问问题。这类方案里,本人首推使用shadowsocks,简单、轻量、稳定易用。但是在某些特殊的场合,非VPN不能解决问题。在各式各类的VPN方案里,我首推L2TP over IPSec,协议加密,内容加密,给未来还是要留个出路的,不然都被扫出来封掉,那太悲催了,我不忍细想。

如果安装的的Debian系统,那么整个部署流程会很方便愉快,但是最近这个问题,困扰我将近半年之久了,就是这个突然不工作了,多方查找才知道,是openswan版本存在bug,导致不兼容,致使L2TP over IPSec的方案无法尽功。有问题的版本如下:

1
2
3
4
5
6
7
8
9
10

# aptitude show openswan
Package: openswan
State: installed
Automatically installed: no
Version: 1:2.6.37-3+deb7u1
Priority: optional
Section: net
Maintainer: Rene Mayrhofer

想要恢复正常也比较简单,降级即可:

1
2
3

# apt-get install openswan=1:2.6.37-3

将openswan的版本降级后,重启IPSec,一切恢复了正常,世界清净了!

如果购买Linode,可以考虑使用我的referral code,算是对我的支持,谢谢:f268347f24b5221e45c9a1048cb8b8db0f0c241a

在Mac上,管理命令行软件包,使用Homebrew,它的原理主要就是将软件安装在一个固定的目录,然后将二进制文件的路径,加入到系统的PATH中,
这样,系统就可以正确识别到命令。PATH的顺序会影响到系统搜索命令的顺序。

brew使用的/usr/local/bin默认已经在Mac系统的PATH里了,但是在最后面。通过 echo $PATH命令可以查看。

但是对于想要使用新版本的人来说,这就不方便了。所以,就要想办法调整PATH的顺序。

sudo vi /etc/paths

就可以在里面调整PATH的搜索顺序了,这个我特意去Linux系统里看了一下,不是这样的,看来是Mac系统特有的。
一般在Linux系统里调整PATH顺序都是在 .bash_profile或者 .bashrc里面,执行

export PATH=/usr/local/bin:$PATH

如果数据库只有一份,那就是数据存储的单点,对于要求可靠性的服务来说,就存在一个单点故障的可能性,这个时候,我们就要通过复制镜像,来解决单点故障。复制还有一个额外的好处,就是可以根据主从,做读写分离,这样,就不会在写入的时候,因为锁表,而降低MySQL的并发性能,所以MySQL复制是MySQL中非常基础的一种操作。

怎么配置

配置Master

首先,要做的是确定一个Master,对于充当Master的MySQL Server来说,需要一些特定的配置才能实现,一个是开启binlog,另一个是要设置server-id。

[mysqld] log_bin = mysql-bin server-id = 1

配置Slave

配置Slave,对于Slave来说,要配置的就是一个唯一的server-id。这个id不能跟Master相同,而且,多个Slave也不能相同。配置完毕后重启。

[mysqld] server-id = 2

创建User

在Master创建一个user,专门用于进行复制用途的。因为在Slave上,user和password会被用明文存储,所以,这个user的权限要尽可能的小,一定要不同于超级用户。

create user repl@'your.domain' identified by 'password'; grant replication slave on *.* to repl@'your.domain';

注意,这里第2句,grant语句,必须是赋权限给*.*的,因为replication slave权限是一个global privileges,所以,必须这样,如果想要限制权限在一个比较小的范围,不想复制所有的db的话,可以在my.cnf增加配置项replicate-do-db和binlog-do-db来限定数据库的范围。

获取Master的位置

在Master的数据库上,知行flush tables with read lock;语句,然后知行show master status;这时候,就可以看到当前的binlog文件名和当前知行的sql语句位置。将文件名和执行的位置都记录下来。

这时候,如果Master的数据库的内容非空的话,应该做的事情,就是使用mysqldump来导出数据。空数据库的话,就没必要做什么事情了。

建立连接

在上文空数据库的情况下,是很简单的,stop slave,直接在slave上使用change master to语句,将各项参数设置完毕后,就可以执行start slave了。

如果Master原来有数据,应该把刚才生成的dump文件,传送到slave上,然后首先stop slave,然后导入dump的数据,然后执行change master to语句,将刚刚dump前记录的bin文件和位置都设置正确,然后才能start slave,其实也不麻烦。

状态检查

在比较理想的世界里,到这里,我们的工作就结束了,但是,世界是不理想的,因为各种原因,这种replication的联系,经常会中断的。所以要时不时检查这个联系。

在Master上可以执行show master status看到的东西和上面看到的是一样的。

在Slave上可以执行show slave status,可以看到很多的信息和错误提示。一般情况下是没错的,一旦发生错误了,就应该从这里获取相应的信息来解决问题。