-
Dec23
MySQL Replication基本原理
Posted in MySQL, 数据库管理, 高可用性, 505 views
-
1、复制进程
Mysql的复制(replication)是一个异步的复制,从一个Mysql instace(称之为Master)复制到另一个Mysql instance(称之Slave)。实现整个复制操作主要由三个进程完成的,其中两个进程在Slave(Sql进程和IO进程),另外一个进程在Master(IO进程)上。
要实施复制,首先必须打开Master端的binary log(bin-log)功能,否则无法实现。因为整个复制过程实际上就是Slave从Master端获取该日志然后再在自己身上完全顺序的执行日志中所记录的各种操作。
复制的基本过程如下:
1)、Slave上面的IO进程连接上Master,并请求从指定日志文件的指定位置(或者从最开始的日志)之后的日志内容;
2)、Master接收到来自Slave的IO进程的请求后,通过负责复制的IO进程根据请求信息读取制定日志指定位置之后的日志信息,返回给Slave的IO进程。返回信息中除了日志所包含的信息之外,还包括本次返回的信息已经到Master端的bin-log文件的名称以及bin-log的位置;
3)、Slave的IO进程接收到信息后,将接收到的日志内容依次添加到Slave端的relay-log文件的最末端,并将读取到的Master端的bin-log的文件名和位置记录到master-info文件中,以便在下一次读取的时候能够清楚的高速Master“我需要从某个bin-log的哪个位置开始往后的日志内容,请发给我”;
4)、Slave的Sql进程检测到relay-log中新增加了内容后,会马上解析relay-log的内容成为在Master端真实执行时候的那些可执行的内容,并在自身执行。
实际上在老版本的Mysql的复制实现在Slave端并不是两个进程完成的,而是由一个进程完成。但是后来发现这样做存在较大的风险和性能问题,主要如下:
首先,一个进程就使复制bin-log日志和解析日志并在自身执行的过程成为一个串行的过程,性能受到了一定的限制,异步复制的延迟也会比较长。
另外,Slave端从Master端获取bin-log过来之后,需要接着解析日志内容,然后在自身执行。在这个过程中,Master端可能又产生了大量变化并声称了大量的日志。如果在这个阶段Master端的存储出现了无法修复的错误,那么在这个阶段所产生的所有变更都将永远无法找回。如果在Slave端的压力比较大的时候,这个过程的时间可能会比较长。
所以,后面版本的Mysql为了解决这个风险并提高复制的性能,将Slave端的复制改为两个进程来完成。提出这个改进方案的人是Yahoo!的一位工程师“Jeremy Zawodny”。这样既解决了性能问题,又缩短了异步的延时时间,同时也减少了可能存在的数据丢失量。当然,即使是换成了现在这样两个线程处理以后,同样也还是存在slave数据延时以及数据丢失的可能性的,毕竟这个复制是异步的。只要数据的更改不是在一个事物中,这些问题都是会存在的。如果要完全避免这些问题,就只能用mysql的cluster来解决了。不过mysql的cluster是内存数据库的解决方案,需要将所有数据都load到内存中,这样就对内存的要求就非常大了,对于一般的应用来说可实施性不是太大。
2、复制实现级别
Mysql的复制可以是基于一条语句(Statement level),也可以是基于一条记录(Row level),可以在Mysql的配置参数中设定这个复制级别,不同复制级别的设置会影响到Master端的bin-log记录成不同的形式。
Row Level:日志中会记录成每一行数据被修改的形式,然后在slave端再对相同的数据进行修改。
优点:在row level模式下,bin-log中可以不记录执行的sql语句的上下文相关的信息,仅仅只需要记录那一条记录被修改了,修改成什么样了。所以row level的日志内容会非常清楚的记录下每一行数据修改的细节,非常容易理解。而且不会出现某些特定情况下的存储过程,或function,以及trigger的调用和触发无法被正确复制的问题。
缺点:row level下,所有的执行的语句当记录到日志中的时候,都将以每行记录的修改来记录,这样可能会产生大量的日志内容,比如有这样一条update语句:update product set owner_member_id = ‘b’ where owner_member_id = ‘a’,执行之后,日志中记录的不是这条update语句所对应额事件(mysql以事件的形式来记录bin-log日志),而是这条语句所更新的每一条记录的变化情况,这样就记录成很多条记录被更新的很多个事件。自然,bin-log日志的量就会很大。尤其是当执行alter table之类的语句的时候,产生的日志量是惊人的。因为Mysql对于alter table之类的表结构变更语句的处理方式是整个表的每一条记录都需要变动,实际上就是重建了整个表。那么该表的每一条记录都会被记录到日志中。
Statement Level:每一条会修改数据的sql都会记录到 master的bin-log中。slave在复制的时候sql进程会解析成和原来master端执行过的相同的sql来再次执行。
优点:statement level下的优点首先就是解决了row level下的缺点,不需要记录每一行数据的变化,减少bin-log日志量,节约IO,提高性能。因为他只需要记录在Master上所执行的语句的细节,以及执行语句时候的上下文的信息。
缺点:由于他是记录的执行语句,所以,为了让这些语句在slave端也能正确执行,那么他还必须记录每条语句在执行的时候的一些相关信息,也就是上下文信息,以保证所有语句在slave端杯执行的时候能够得到和在master端执行时候相同的结果。另外就是,由于Mysql现在发展比较快,很多的新功能不断的加入,使mysql得复制遇到了不小的挑战,自然复制的时候涉及到越复杂的内容,bug也就越容易出现。在statement level下,目前已经发现的就有不少情况会造成mysql的复制出现问题,主要是修改数据的时候使用了某些特定的函数或者功能的时候会出现,比如:sleep()函数在有些版本中就不能真确复制,在存储过程中使用了last_insert_id()函数,可能会使slave和master上得到不一致的id等等。由于row level是基于每一行来记录的变化,所以不会出现类似的问题。
从官方文档中看到,之前的Mysql一直都只有基于statement的复制模式,直到5.1.5版本的Mysql才开始支持row level的复制。从5.0开始,Mysql的复制已经解决了大量老版本中出现的无法正确复制的问题。但是由于存储过程的出现,给Mysql的复制又带来了更大的新挑战。另外,看到官方文档说,从5.1.8版本开始,Mysql提供了除Statement Level和Row Level之外的第三种复制模式:Mixed,实际上就是前两种模式的结合。
在Mixed模式下,Mysql会根据执行的每一条具体的sql语句来区分对待记录的日志形式,也就是在Statement和Row之间选择一种。新版本中的Statment level还是和以前一样,仅仅记录执行的语句。而新版本的Mysql中队row level模式也被做了优化,并不是所有的修改都会以row level来记录,像遇到表结构变更的时候就会以statement模式来记录,如果sql语句确实就是update或者delete等修改数据的语句,那么还是会记录所有行的变更。
3、复制常用架构
Mysql复制环境90%以上都是一个Master带一个或者多个Slave的架构模式,主要用于读压力比较大的应用的数据库端廉价扩展解决方案。因为只要master和slave的压力不是太大(尤其是slave端压力)的话,异步复制的延时一般都很少很少。尤其是自slave端的复制方式改成两个进程处理之后,更是减小了slave端的延时。而带来的效益是,对于数据实时性要求不是特别的敏感度的应用,只需要通过廉价的pc server来扩展slave的数量,将读压力分散到多台slave的机器上面,即可解决数据库端的读压力瓶颈。这在很大程度上解决了目前很多中小型网站的数据库压力瓶颈问题,甚至有些大型网站也在使用类似方案解决数据库瓶颈。
一个Master带多个slave的架构实施非常简单,多个slave和单个slave的实施并没有太大区别。在Master端并不care有多少个slave连上了master端,只要有slave进程通过了连接认证,向他请求binlog信息,他就会按照连接上来的io进程的要求,读取自己的binlog信息,返回给slave的IO进程。对于slave的配置细节,在Mysql的官方文档上面已经说的很清楚了,甚至介绍了多种实现slave的配置方法。
Mysql不支持一个Slave instance从属于多个Master的架构。就是说,一个slave instance只能接受一个master的同步源,听说有patch可以改进这样的功能,但没有实践过。Mysql AB之所以不实现这样的功能,主要是考虑到冲突解决的问题。
Mysql也可以搭建成dual master模式,也就是说两个Mysql instance互为对方的Master,也同时为对方的Slave。不过一般这种架构也是只有一端提供服务,避免冲突问题。因为即使在两边执行的修改有先后顺序,由于复制的异步实现机制,同样会导致即使在晚做的修改也可能会被早做的修改所覆盖,就像如下情形:
时间点 Mysql A Mysql B
1 更新x表y记录为10
2 更新x表y记录为20
3 获取到A日志并应用,更新x表的y记录为10(不符合期望)
4 获取B日志更新x表y记录为20(符合期望)这样,不仅在B库上面的数据不是用户所期望的结果,A和B两边的数据也出现了不一致的情况。除非能将写操作根据某种条件固定分开在A和B两端,保证不会交叉写入,才能够避免上面的问题。
用 Flock 浏览器 创建 -
No Comments »
-
Dec21
kill某个用户的所有session
Posted in DBA脚本, 数据库管理, 598 views
-
kill_all_session_by_username.sh
用于杀掉Oracle数据库中某个用户的所有session#!/bin/sh
if [ $# -ne 1 ] ;
then
echo "Usage: $0 <Username>";
echo "WARNING: the <Username> MUST in upper case.";
exit 1;
fiusername=$1
echo $usernamefunction_get_info(){
username=$1sqlplus / as sysdba <<EOF
select username,sid,serial# from v\$session where username = '$username';
EXIT
EOF
}function_get_info ${username} |awk '/^'${username}'/ { print "alter system kill session '\''" $2 "," $3 "'\'' ; "} '
sql_killsession=`function_get_info |awk '/^'${username}'/ { print "alter system kill session '\''" $2 "," $3 "'\''; "} '`
echo $sql_killsessionsqlplus / as sysdba <<EOF
#$sql_killsession
EXIT
EOF用 Flock 浏览器 创建标签: oracle, killsession
-
No Comments » kill session oracle script shell 用户
-
Dec20
Hudson环境变量
Posted in 持续集成, 质量管理, 软件配置管理, 769 views
-
Hudson在运行中,存在多个环境变量,可以将版本号等信息传递给Ant、Phing等第三方软件。
这里是环境变量列表:- BUILD_NUMBER: The current build number, such as "153"
- BUILD_ID: The current build id, such as "2005-08-22_23-59-59" (YYYY-MM-DD_hh-mm-ss)
- JOB_NAME: Name of the project of this build, such as "foo"
- BUILD_TAG: String of "hudson-${JOBNAME}-${BUILD_NUMBER}". Convenient to put into a resource file, a jar file, etc for easier identification.
- EXECUTOR_NUMBER: The unique number that identifies the current executor (among executors of the same machine) that's carrying out this build. This is the number you see in the "build executor status", except that the number starts from 0, not 1.
- JAVA_HOME: If your job is configured to use a specific JDK, this variable is set to the JAVA_HOME of the specified JDK. When this variable is set, PATH is also updated to have $JAVA_HOME/bin.
- WORKSPACE: The absolute path of the workspace.
- HUDSON_URL: Full URL of Hudson, like http://server:port/hudson/
- SVN_REVISION: For Subversion-based projects, this variable contains the revision number of the module.
- CVS_BRANCH: For CVS-based projects, this variable contains the branch of the module. If CVS is configured to check out the trunk, this environment variable will not be set.
用 Flock 浏览器 创建 -
No Comments » ci hudson phing scm 持续集成
-
Dec18
MooseFS 维护
Posted in 分布式, 系统管理, 548 views
-
一、启动MooseFS集群
最安全的启动MooseFS集群(避免任何读或写的错误数据或类似的问题)的方式是按照以下命令步骤:
1.启动mfsmaster进程
2.启动所有的mfschunkserver进程
3.启动mfsmetalogger进程(如果配置了mfsmetalogger)
当所有的chunkservers连接到MooseFS master后,任何数目的客户端可以利用mfsmount去挂接被export的文件系统。(可以通过检查master的日志或是CGI监视器来查看是否所有的chunkserver被连接)。二、停止MooseFS集群
安全的停止MooseFS集群:
1.在所有的客户端卸载MooseFS 文件系统(用umount命令或者是其它等效的命令)
2.用mfschunkserver –s命令停止chunkserver进程
3.用mfsmetalogger –s命令停止metalogger进程
4.用mfsmaster –s命令停止master进程三、MooseFS chunkservers的维护
假如每个文件的goal(目标)都不小于2,并且没有under-goal文件(这些可以用mfsgetgoal –r和mfsdirinfo命令来检查),那么一个单一的chunkserver在任何时刻都可能做停止或者是重新启动。以后每当需要做停止或者是重新启动另一个chunkserver的时候,要确定之前的chunkserver被连接,而且要没有under-goal chunks。四、MooseFS元数据的备份
通常元数据有两部分的数据
1.主要元数据文件metadata.mfs,当mfsmaster运行的时候会被命名为metadata.mfs.back
2.元数据改变日志changelog.*.mfs,存储了过去的N小时的文件改变(N的数值是由BACK_LOGS参数设置的,参数的设置在mfschunkserver.cfg配置文件中)。
主要的元数据文件需要定期备份,备份的频率取决于取决于多少小时changelogs储存。元数据changelogs应该实时的自动复制。自从MooseFS 1.6.5,这两项任务是由mfsmetalogger守护进程做的。五、MooseFS master的恢复
一旦mfsmaster崩溃(例如因为主机或电源失败),需要最后一个元数据日志changelog并入主要的metadata中。这个操作时通过mfsmetarestore工具做的,最简单的方法是:
mfsmetarestore -a
如果master数据被存储在MooseFS编译指定地点外的路径,则要利用-d参数指定使用,如:
mfsmetarestore -a -d /storage/mfsmaster六、从备份恢复MooseFS master
为了从备份中恢复一个master,需要做:
1、安装一个mfsmaster
2、利用同样的配置来配置这台mfsmaster(利用备份来找回mfsmaster.cfg),可见配置文件也是需要备份的。
3、找回metadata.mfs.back文件,可以从备份中找,也可以中metalogger主机中找(如果启动了metalogger服务),然后把metadata.mfs.back放入data目录,一般为${prefix}/var/mfs。
4、从在master宕掉之前的任何运行metalogger服务的服务器上拷贝最后metadata文件,然后放入mfsmaster的数据目录。
5、利用mfsmetarestore命令合并元数据changelogs,可以用自动恢复模式mfsmetarestore –a,也可以利用非自动化恢复模式,语法如下:
mfsmetarestore -m metadata.mfs.back -o metadata.mfs changelog_ml.*.mfs用 Flock 浏览器 创建标签: moosefs, 分布式, filesystem
-
1 Comment » mfs moosefs 分布式 存储
-
Dec18
MooseFS各元素主要配置文件
Posted in 分布式, 操作系统, 系统管理, 714 views
-
1、master
主服务器
Metadata is stored in memory of the managing server and simultaneously is being saved on disk (as a periodically updated binary file and immediately updated incremental logs). The main binary file as well as the logs are replicated to metaloggers (if present).Metadata元数据存储在master服务器的内存中,同时也保存在磁盘上(作为一个定期更新的二进制文件,并实时的更新changelog日志)。如果存在metaloggers的话,主要的二进制文件以及日志也复制到metaloggers中。
How much CPU/RAM resources are used?
消耗多少CPU和内存资源In our environment (ca. 500 TiB, 25 million files, 2 million folders distributed on 26 million chunks on 70 machines) the usage of chunkserver CPU (by constant file transfer) is about 15-20% and chunkserver RAM usually consumes about 100MiB (independent of amount of data).
在我们的测试环境中(大约500 TiB的数据,250万份文件,200万文件夹,分成260万块分布在70机器上),chunkserver的CPU使用情况为(持续的文件传输)约为15-20%同时chunkserver内存使用100MiB(和数据量的多少无关)。
The master server consumes about 30% of CPU (ca. 1500 operations per second) and 8GiB RAM. CPU load depends on amount of operations and RAM on number of files and folders.
master服务器消耗约30%的CPU(每秒钟约1500次操作)和8G的内存。 CPU负载取决于操作的次数,内存的使用取决于文件和文件夹的个数。
File data is divided to fragments (chunks) of maximum size 64MB each which are stored as files on selected disks on data servers (chunkservers). Each chunk is saved on different computers in a number of copies equal to a "goal" for the given file.
文件数据是按块为单位(块的最大大小64MB以上)存储在数据服务器(chunkservers)上指定磁盘上。如果设置的goal的存储分数和机器个数相同,不同的块儿会存储在每一个机器上。
What sort of sizing is required for the Master server?
对Master主服务器有什么需求?The most important factor is RAM of mfsmaster machine, as the full file system structure is cached in RAM for speed. Besides RAM mfsmaster machine needs some space on HDD for main metadata file together with incremental logs.
最重要的因素就是mfsmaster机器的内存,因为整个文件系统结构都缓存到内存中以便加快访问速度。除了内存mfsmaster机器还需要一定硬盘大小用来存储Metadata数据和增长的日志文件。The size of the metadata file is dependent on the number of files (not on their sizes). The size of incremental logs depends on the number of operations per hour, but length (in hours) of this incremental log is configurable.
Metadata文件的大小是取决于文件数的多少(而不是他们的大小)。changelog日志的大小是取决于每小时操作的数目,但是这个时间长度(默认是按小时)是可配置的。1 million files takes approximately 300 MiB of RAM. Installation of 25 million files requires about 8GiB of RAM and 25GiB space on HDD.
100万文件大约需要300M内存。25百万份文件大约需要8GiB内存和25GiB硬盘空间。master主要文件
mfsmaster.cfg
configuration file for MooseFS master process参数说明如下:
#WORKING_USER和WORKING_GROUP:是运行master server的用户和组;
#SYSLOG_IDENT:是master server在syslog中的标识,也就是说明这是由master server产生的;
#LOCK_MEMORY:是否执行mlockall()以避免mfsmaster 进程溢出(默认为0,即否);
#NICE_LEVE:运行的优先级(如果可以默认是 -19; 注意: 进程必须是用root启动);
#EXPORTS_FILENAME:被挂接目录及其权限控制文件的存放位置
#DATA_PATH:metadata files and lock file存放路径,此目录下大致有以下文件:metadata,changelog,sessions,stats,lock。
#BACK_LOGS:metadata的change log文件数目(默认是 50);
#REPLICATIONS_DELAY_INIT:(initial delay in seconds before starting replications)初始延迟复制的时间(默认是300s);
#REPLICATIONS_DELAY_DISCONNECT:(replication delay in seconds after chunkserver disconnection) chunkserver断开后复制延迟(默认是3600s);
# MATOML_LISTEN_HOST:用于metalogger连接的IP地址(默认是*,代表任何IP);
# MATOML_LISTEN_PORT:监听metalogger请求的端口地址(默认是9419);
# MATOCS_LISTEN_HOST:用于chunkserver连接的IP地址(默认是*,代表任何IP);
# MATOCS_LISTEN_PORT:监听chunkserver连接的端口地址(默认是9420);
# MATOCU_LISTEN_HOST:用于客户端挂接连接的IP地址(默认是*,代表任何IP);
# MATOCU_LISTEN_PORT:监听客户端挂载连接的端口地址(默认是9421);
# CHUNKS_LOOP_TIME :(Chunks loop frequency in seconds)chunks的回环频率(默认是:300秒);
# CHUNKS_DEL_LIMIT:(Maximum number of chunks to delete in one loop)在一个loop中可以删除chunks的最大数 (默认:100)
# CHUNKS_WRITE_REP_LIMIT:(Maximum number of chunks to replicate to one chunkserver in one loop)在一个loop里复制到一个chunkserver的最大chunk数目(默认是1)
# CHUNKS_READ_REP_LIMIT:(Maximum number of chunks to replicate from one chunkserver in one loop)在一个loop里从一个chunkserver复制的最大chunk数目(默认是5)
# REJECT_OLD_CLIENTS:弹出低于1.6.0的客户端挂接(0或1,默认是0)mfsexports.cfg
MooseFS access control file
地址可以指定的几种表现形式:所有ip,单个ip,IP网络地址/位数掩码,IP网络地址/子网掩码,ip段范围。权限部分:
ro 只读模式共享
rw 读写方式共享
alldirs 许挂载任何指定的子目录
maproot 映射为root,还是指定的用户
password 指定客户端密码.mfsmaster.lock
lock file of running MooseFS master process
mfsmaster.lock文件记录正在运行的MooseFS 的主进程metadata.mfs, metadata.mfs.back
MooseFS filesystem metadata image
metadata.mfs, metadata.mfs.back是MooseFS文件系统的元数据metadata的镜像changelog.*.mfs
MooseFS filesystem metadata change logs (merged into metadata.mfs once per hour)
changelog.*.mfs 是MooseFS文件系统元数据的改变日志(每一个小时合并到metadata.mfs中一次)The size of the metadata file is dependent on the number of files (not on their sizes). The size of incremental logs depends on the number of operations per hour。
Metadata文件的大小取决于文件数(而不是他们的大小),Changelog的大小取决于每小时的操作次数。2、metalogger
主要文件:
mfsmetalogger.cfg# WORKING_USER = mfs
# WORKING_GROUP = mfs
# SYSLOG_IDENT = mfsmetalogger
# LOCK_MEMORY = 0
# NICE_LEVEL = -19
# DATA_PATH = /usr/local/mfs/var/mfs
# BACK_LOGS = 50META_DOWNLOAD_FREQ = 1 # metadata download frequency in hours (default is 24, at most BACK_LOGS/2) 。metadata元数据下载间隔时间(默认是24小时,单位是小时,至多是BACK_LOGS的1/2)
# MASTER_RECONNECTION_DELAY = 5 # delay in seconds before trying to reconnect to master after disconnection。在失去连接之后延迟多少秒重新连接master
MASTER_HOST = 192.168.5.230
# MASTER_PORT = 9419
# MASTER_TIMEOUT = 60 # timeout (in seconds) for master connections。Master连接超时时间(单位是秒)
# deprecated, to be removed in MooseFS 1.7
# LOCK_FILE = /var/run/mfs/mfsmetalogger.lock
.mfsmetalogger.lockchangelog_ml.*.mfs
MooseFS filesystem metadata change logs (backup of master change log files)
changelog_ml.*.mfs是MooseFS文件系统的元数据的changelog日志(备份的Master 的Master的changelog日志。)metadata.ml.mfs.back
Latest copy of complete metadata.mfs.back file from MooseFS master.
metadata.ml.mfs.back是从Master主机上下载的最新的完整metadata.mfs.back的拷贝sessions.ml.mfs
Latest copy of sessions.mfs file from MooseFS master.
sessions.ml.mfs是从master下载的最新的sessions.mfs文件拷贝。3、chunker
主要文件:
mfschunkserver.cfg# WORKING_USER = mfs
# WORKING_GROUP = mfs
# SYSLOG_IDENT = mfschunkserver
# LOCK_MEMORY = 0
# NICE_LEVEL = -19
# DATA_PATH = /usr/local/mfs/var/mfs
# MASTER_RECONNECTION_DELAY = 5 (delay in seconds before trying to reconnect to master after disconnection)在失去连接之后延迟多少秒重新连接master
MASTER_HOST = 192.168.5.230 元数据服务器的名称或地址,可以是主机名,也可以是ip地址。只要数据存储服务器能访问到元数据服务器就行。
# MASTER_PORT = 9420
# MASTER_TIMEOUT = 60
# CSSERV_LISTEN_HOST = * #IP address to listen on for client (mount) connections (* means any) 允许挂载的客户端连接的IP地址(*允许全部)
# CSSERV_LISTEN_PORT = 9422
# CSSERV_TIMEOUT = 5 #timeout (in seconds) for client (mount) connections
客户端挂载连接的超时时间(单位为秒)
# HDD_CONF_FILENAME = /usr/local/mfs/etc/mfshdd.cfg #分配给MFS使用的磁盘空间配置文件的位置
# HDD_TEST_FREQ = 10 #chunk test period in seconds 块的测试期(单位为秒)
# deprecated, to be removed in MooseFS 1.7
# LOCK_FILE = /var/run/mfs/mfschunkserver.lock
# BACK_LOGS = 50mfshdd.cfg
list of directories (mountpoints) used for MooseFS storage (one per line; directory prefixed by * character causes given directory to be freed by replicating all data already stored there to another locations) Lines starting with # character are ignored as comments。mfschunkserver.lock
lock file of running MooseFS chunkserver process4、mfsclient(mount)
用 Flock 浏览器 创建标签: moosefs, 分布式, filesystem
-
No Comments » mfs moosefs 分布式 存储
-
Dec15
“我就差一个编程的”
Posted in 创业, 新视野, 461 views
-
"I Just Need a Programmer"
http://www.cs.uni.edu/~wallingf/blog/archives/monthly/2010-12.html#e2010-12-01T15_45_40.htm
作为我们大学计算机系的系主任,我经常收到一些声称得到了能造就下一个奇迹的好主意的人的来信和电话。这些电话有的十分的有趣!打电话的人有时是一位急切的创业者,醉心于他的想法,认为那是一个能取代Google,超越Facebook,或者是能改变当前的商业面貌,变革整个互联网的好想法。有时打电话的人不是我们学校的,有时是我们大学工商科目、大多是主修商业的学生;年轻人的电话都透露出了富有感染力的创业热情。他们希望能改变这个世界,他们需要我去帮助他们!他们就差一个编程的。
他们需要有人能接受他们的想法,把这个想法转变成PHP,SQL,HTML,CSS,Java和Javascript代码。这些创业者知道他们现在缺少什么。我是否应该找一两个计算机专业的学生加入他们的项目,帮他们实现呢?
大多数他们这样的项目永远找不到计算机专业的学生来实现。有很多的原因。学生们都在忙于课程和生活。大多数计算机专业的学生都有了他们喜欢的工作。他们的工作是付现金的(如果不是拿不了的情况下),这比一个不确定的将来才会有的财富的许诺来说对学生们更有吸引力。这些想法和点子对其他人来说并不像对想出他们的这些创业者那样令人兴奋,不像这些创业者由于担心会产生创世纪的成就而坐卧不安。
很多这样有想法的人由于找不到计算机专业的学生或其他编程人员而一而再、再而三的联系我,希望能从我这得到好消息。年轻的创业者们会越来越泄气。他们希望其他人也能像他们一样为这样的想法而激动。(乐观的年轻人呀!)我一直希望他们能找到什么人帮助他们把想法变成现实。这个过程会是令人兴奋的。他们也能从中学到很多东西。
当然,他们似乎也从来没有想到自己是可以去学编程的。
前段时间,我在微博上聊了几句关于接到这些电话的事情。Andrei Savu用简单的语句对于遇到的这些现象进行了总结:@wallingf 这就是说,他们把软件开发者当作一种工具。产品 = 行动 != 点子
我在最近写的一篇博客里详细的谈论了这个问题,一个产品的价值来源于拥有一个想法和执行这个想法的组合。你单具备了前者或只有执行后者的能力都不太有价值。你必须把它们组合到一起。
很多“手握绝世好想法的人”都倾向于认为大多数或全部的价值都来源于创造出了这个想法。程序员只是一个工具,就像个鸡毛掸子,拿起来就可以掸灰。编程是个小事情,不是吗?
另一方面,一些程序员乐意认为大多数或所有的价值都来源于实施了这个想法。可是你不能去实施你还没有的想法呀。这就好像我和我的同事们围坐在一盘左宗棠鸡前惋惜我们失去的财富。可实际上没有人失去。财富从未与我们为邻。事实上我们缺少一个致命的条件。没有时间机器或其它机器能使时光倒流。
我仍然希望这些身负好点子的人中,一些人自己该会编程,或想去学编程,这样他们就可以自己来实现自己的想法。这样,他们也可以有机会知道只有超人有力量什么不做也能把理想变为现实。在过去,学习计算机编程是使用计算机的人的必然后果。可遗憾的是,现在全变了。如今使用计算机的必然后果看起来是可以让人接触到一些自己也许认识,也许不认识的人或者只是看看Youtube视频。
哦,想想吧,如果你发现了一个能够赛过Google和Facebook的好想法,那将会是什么样子。时不时的,我非常想告诉那些给我打电话的创业者,他们的想法基本上不会有改变这个世界的希望。但是我没有,至少有两个理由。第一,他们并没有想征求我的意见。第二,总有一段时间后会有另外一个微软或Google出现来改变这个世界。谁又能想到这会是无数想法中的哪一个?如果我和我的同事能够重新回到2000年,去告诉我们的年轻人有关Facebook的事,这些年轻人会有足够的远见来坐下来开发出这个网站吗?
我猜不会。我如何能知道哪一个会是能够改变这个世界的好想法呢?开发出来,努力工作,用你的手指把想法变成人们需要和想要的东西。把程序开发出来的能力是这些有想法的人缺少的一个必要因素。他们去寻找有这种能力的人,这很对。我很想知道,如果每个人都能够把自己的想法变成现实,这个世界将会变成什么样子。
用 Flock 浏览器 创建 -
1 Comment » idea 开发 执行
-
Nov16
nginx几个uri变量的区别
Posted in Web服务器, 系统管理, 656 views
-
在nginx中有几个关于uri的变量,包括$uri $request_uri $document_uri,下面看一下他们的区别 :
$request_uri: /stat.php?id=1585378&web_id=1585378
$uri /stat.php
$document_uri: /stat.php -
1 Comment » nginx uri url
-
Nov02
技术文化和惨淡命运——怀念中国雅虎
Posted in 新视野, 案例与思考, 476 views
-
本文转载自豆瓣dreamer的日记
很早就想写这么一篇文章了。我离开中国雅虎已经一年有余,在中国雅虎工作的那段时光是我最珍贵的回忆之一,和以前的同事吃饭聊天的时候也经常会怀念一下中国雅虎,怀念得多了,就觉得不如写篇文章好好回顾一下。很多事情虽然已经过去,但有些话不说出来,到底意难平。
从2008年7月份毕业之后加入了中国雅虎,到2009年9月份跟着中国雅虎工程技术部全体人员“被跳槽”到淘宝,我在中国雅虎只呆了一年多的时间。这个时间并不长,甚至可以说短得可怜,所以我或许不是写这篇文章的最佳人选。但是,中国雅虎给我的是人生第一份工作,凭着初生牛犊对社会的好奇心,我对公司的文化、技术、架构、流程包括产品设计等各个方面都有浓厚的兴趣和广泛的了解,从这个方面来说,由我来写这篇文章也是合适的。而且最重要是,我愿意把它们写出来。
在进入正文之前,先开诚布公地声明一下:众所周知,中国雅虎是阿里巴巴的一个子公司,所以文中我也不必遮遮掩掩地用“某电子商务公司”来代替。而且我对阿里巴巴这个公司有意见,不代表我对阿里巴巴的员工有意见,如果伤了某些人的感情,先说声抱歉,请您发扬一下风格,在这里也“拥抱变化”一下。
正文:
我在 2007 年底通过校园招聘拿到了中国雅虎的 offer ,但实际上在我2008年7月份入职的时候,中国雅虎的品牌虽然还在,公司却已经在7月9日和口碑网合并了,改名叫做“雅虎口碑”。尽管这样,到现在为止我还是厚着脸皮说自己原来是雅虎的,因为那里让我着迷和真心喜欢的东西全部都是紫色的,而不是橙色的。
雄厚的技术实力
中国雅虎最好的一个地方就是它和 Yahoo 全球共享同一个技术平台,那是一个有十几年历史的技术平台。Yahoo 的技术文化不如 Google 的工程师文化那么有名,但 Yahoo 在相当长的一段时间内都是互联网的旗帜,吸引了全球大量的技术牛人加入,Yahoo 的技术平台就是他们的知识、经验和心血日积月累的成果。尽管阿里巴巴收购了中国雅虎,但是在技术方面并没有对中国雅虎做出太大的改造(幸好没有改造),所以就工程师来说,每天更多接触到的还是 Yahoo 的东西,而不是阿里巴巴的东西,对我影响最大的也正是这些东西。
一、Linux 和开源文化
之前一个中国雅虎的同事,他是工作了几年之后才来中国雅虎,有一次他说:“雅虎是我见过的最尊重 Linux 的一家公司”。什么叫做尊重 Linux 呢 ? 不是在服务器上装个 Linux 跑 Apache 就叫做尊重 Linux 。在雅虎很多同事日常都使用 Linux 操作系统办公,即使有一些人使用 Windows, 也都是使用 pietty 或者 Xshell 等工具远程连接到开发机器上使用 VIM 做开发。不只是日常工作,在雅虎全球的技术体系中,产品的上线和发布也都借鉴了 Linux 包管理的方式:所有的产品都会被打成包放在一个专门的服务器上,产品的部署和升级就变成了简单的装包操作,绝对不会出现最后上线的时候文件路径出错等低级问题。Yahoo 的技术平台是深深扎根于 Linux 和开源文化的。
大型互联网公司一般都会使用开源的产品,同时也向社区贡献代码。Google 和 Facebook 经常将自己研发的成熟产品开源,Yahoo 当然也不例外。而且 Yahoo 不仅仅给社区贡献代码,它在设计方面也拥抱了开源文化,将多年研究总结的设计模式库共享了出来。在 Yahoo 内部,很多代码都是存放在 CVS 里面的,并没有限制读的权限,任何员工都可以查看里面的代码,这对于那些小团队内部代码都不敢共享防员工如防贼的公司来说应该是非常不可思议的。另外, Yahoo 的工程师也经常出现在各种技术会议上,分享自己项目的架构、流程和经验。虽然这些更多都是 Yahoo 全球技术团队做的事情,但是对于他们那种开放共享的精神我们是非常认同并且向往的,你会觉得做一个工程师很自豪,而不会觉得自己是民工、做技术没前途。这种认同感和成就感乍看上去没什么,但实际上它决定了你对技术的追求和态度,也会影响你以后在职业上的选择。
二、浓厚的技术氛围
虽然2008年的时候中国雅虎已经被折腾得快不像样了(这点后面细说),不过那个时候还是有浓厚的技术氛围的。让我印象深刻的一件事情是 Google Chrome 浏览器刚发布的时候,大家都立刻下载下来使用,但由于公司内网的一些问题无法打开网页。当我正打算把 Chrome 卸载了的时候,忽然发现公司邮件列表里面已经有人发邮件给出了详细的解决方案。从这件小事可以看出公司大部分工程师都不是那种只知道完成工作的人,而是随时关注新技术和业界动态的人。当时中国雅虎还是有很多牛人没有离开,大家也喜欢在邮件列表里面谈论技术,经常能看到精彩的讨论和解答。最让我兴奋的是,无论我遇到什么技术问题都不用慌张,即使无法 Google 到答案也可以从同事那里获取到帮助,而且大家也愿意回答技术问题,这对于我这样一个基础很差技术又烂的菜鸟来说真是天大的福气。
中国雅虎还有做技术分享的文化,如果有哪位同事想要分享一下最近学习到的技术,就可以自己预订一个会议室然后向所有的工程师发送会议邀请,有时候还会有一系列非常系统的课程,我就参加过长达十几个课时的 UED 培训,完全改变了我对 Web Develop 的认识。很多公司应该都鼓励员工做技术分享,但在中国雅虎几乎每次技术分享都会把会议室坐的满满当当,可见大部分工程师都还是想要不断提高自己的技术能力。直到离开雅虎之后我才明白这种普遍的学习热情有多么难得。我想,业界之所以到处流传着“程序员做到30岁最好转管理”之类的忠告,应该就是因为大部分公司都缺乏这种良好的技术氛围吧。
三、庞大的知识库
入职的前几天,我每天的工作就是看文档,不是类似“PHP技术手册”那种文档,而是一些 Yahoo 内部的工具手册。Yahoo 内部的文档非常齐全和详细,光是 Yinst 这款工具的使用手册就长达几十页。Yahoo 内部是用 Twiki 做知识管理的,这个知识库经过十多年的积累已经非常庞大,从入门到提高,从 PHP 到 C ,从前端到后端……应有尽有,而且几乎 Yahoo 全球所有子公司的技术资料都是开放浏览的,没有任何乱七八糟的权限设置和保密限制。有这么一个宝藏在,再加上好的学习氛围,如果你想要提高自己的能力的话,总是可以提高。当初我想从 PHP 工程师转做 Web Developer 的时候,就先把 Twiki 上 UED 部门的所有资料看了一遍,受益匪浅。
国内大部分互联网公司都是没有太多技术积累的,因为大部分产品的开发都只追求开发速度,并不会特别追求技术上的极致,就更不要提文档这种东西了。也正因为如此,从中国雅虎出来看到其它公司的知识库的时候总有不过瘾的感觉,可能也只有像 Google, 微软(MSFT,26.95,+1.07%)和 Facebook 这样的公司才会有像 Yahoo 那样的知识库吧。在和之前一些同事吃饭聊天的时候,大家也总是会怀念那个无所不包完全开放的 Twiki ,好像少了一个忠实的朋友一样。我们由衷地尊敬那些在完成工作之余还愿意总结项目经验并花时间写 Twiki 的工程师们。
四、完善的流程
第一次参与项目开发的时候,我的 Leader 领了一个 MM 过来说:“这位是项目的 QA 负责人”,我当时愣了一下:“呃…… QA 是做什么的?” 尽管在大学里我也在实验室做过一些项目,但那些项目基本上都是我自己负责所有的事情,完全没有分工和流程的概念,所以也不知道 QA 是负责产品测试工作的。进入中国雅虎之后,我才第一次接触到商业产品的开发流程,不过由于那个时候中国雅虎已经半死不活,我也没有受到有关流程的入职培训,以至于在做了好几个项目之后才真正熟悉了完整的流程。
中国雅虎的开发流程沿袭了 Yahoo 的开发流程,乍看之下很平常,对于已经熟悉的工程师来说还显得枯燥,但后来我特别留心了这套流程之后,非常惊奇于它的严谨和高效,所以这里要详细说明一下。Yahoo 的内部生产线分为三个相互独立的环境:开发环境、测试环境和生产环境(即线上环境)。这三个环境虽然独立,但它们的配置都会尽量保持一致,这样就可以保证开发完成的产品不会因为环境不同而出现问题。在开发的时候,我们会在开发环境中搭建虚拟环境,开发完毕之后开发工程师会自己在虚拟环境里面测试,保证没有大的问题,然后就会把所有相关文件打包上传到雅虎全球统一放置产品包的地方。上传完毕之后,就会发邮件通知 QA 部门相关人员,邮件内容里面要写明产品在测试环境的部署步骤:需要安装哪些包、是否需要修改数据库等等。然后 QA 就会开始测试,如果发现 BUG 就会写到 Bugzilla 中,指派给相应的开发工程师,开发工程师就会在开发环境中定位BUG并修正,修正一些BUG之后就会再次打包升级产品的版本,然后QA 会将新的软件包部署到测试环境验证之前的 BUG 并报告新的 BUG 。整个测试过程中可能要发布好多个版本,直到所有 BUG 被修正为止。修正完毕所有的 BUG 之后,开发工程师就会填写上线申请,Ops 看到申请之后就会安排一个时间把产品部署到生产环境。一般来说,生产环境不止会有一台机器,所以 Ops 会先从生产环境摘下一台机器部署,部署完毕之后会告知 QA 和开发工程师,然后 QA 和开发工程师就会修改 Hosts 文件,配置域名指向那台机器进行线上的测试,如果测试没有问题,那么就会把软件包部署到生产环境中所有的机器上,完成上线;否则就进行回滚,取消这次上线,也不会影响到线上的用户。
整个流程大概就是这样,但是要特别注意的是以下几点:1. 开发工程师只能接触开发环境。他所能做的就是在开发环境中开发、改 BUG 和打包上传。如果他去测试环境中修改 BUG,就很有可能忘记修改开发环境中的相应代码,这可能会导致产品测试通过但是上线之后却发现大的问题。 2. 产品“封版”之后就不可以做任何改动,如果有改动,即使只改动了一点所有功能也要重新测试一遍。所有的 BUG 都修改完毕之后的那个版本就会进行“封版”,那就标志着这个产品随时可以准备上线了。如果真的发现了新的 BUG 要修改的话,那么修改之后就需要重新打包重新走一遍完整的测试流程,只有这样才能够保证就算修改代码过程中引入了新的 BUG 也不会被遗漏。 3. 上线手册要详细。开发工程师要详细写明每一个步骤,不只是说明性的文字,还要把具体的安装和修改命令完整地放上去,如果写得好的话,那么 Ops 的同事只需要把上线手册里面的命令逐行复制到服务器上运行就可以完成上线。
这样的流程有什么好处呢? 首先,它最大地降低了上线风险。因为开发工程师不能接触到测试环境,只能打包让QA测试,所以完整经过测试的产品上线之后基本不会有什么问题,况且上线的时候我们也要先部署到一台机器上进行测试之后才会决定是否上线,即使上线不成功也可以在不影响用户的情况下回滚。中国雅虎的上线极少会出现问题,很多时候我们上线到半夜只是因为那个时间段用户访问量最小,而不是说焦头烂额地忙活几个小时一直到半夜才上线成功。其次,它使得各个部门职责分明。开发工程师和 QA 通过 Bugzilla 沟通,和 Ops 通过上线手册沟通,因为沟通渠道唯一而且清晰,所以就可以完全责任到人,出了问题也很容易定位到具体环节。比如说,如果产品测试通过之后在上线的时候出现了问题,那么基本就可以确定是 Ops 操作失误或者上线手册没有写好。职责分明之后很多事情也变得有条理,大家就可以各司其职、专注本职工作并且合作愉快,开会的时候也可以明确知道需要哪些人参加。
完善、清晰的流程从根本上解决了一些问题,创建了一个非常好的环境,这样我们就可以把心思都放在如何开发和测试上面,而不用担心诸如“如何上线才能不出错”等琐碎的事情。所以尽管中国雅虎的高层那么不靠谱,我工作得还是很开心,因为这个流程保证了管理层再怎么乱开发也不会乱。记得那时候很喜欢改 BUG ,有时候改得兴起会把之前版本遗留的 miss BUG 一并改掉,加班也是颇有兴致,不是很能明白为什么网上大部分程序员讨厌加班讨厌得要死。现在我明白了。
五、自动化工具
工欲善其事,必先利其器。如果没有那么多好用的自动化工具,那么 Yahoo 的流程就不可能如此完善。Yahoo 内部有很多非常好用的工具,而且这些工具都有非常齐全的文档,也可以在 Twiki 上找到不少相关资料。这些工具之所以在 Yahoo 会起到那么大的作用,是因为 Yahoo 全球所有的技术团队都在使用它们,Yahoo 所有的服务器上也是默认安装了这些工具。这些工具就形成了一套全球 Yahoo 工程师通用的话语体系,可以想象它们帮助 Yahoo 节省了多少沟通成本。
由于考虑到服务器的安全问题,Yahoo 的这些工具的使用方法是对外保密的,这里我只简单说一下 Yinst 这款工具的强大。假如要把软件包 example_1_1_0.tar.gz 部署到 a1.yahoo.com ~ a10.yahoo.com ,那么只需要下面这样一行命令:
yinst install example_1_1_0.tar.gz -h a[1-10].yahoo.com
就可以完成整个上线过程。由于好奇的缘故,在上线的时候我比较喜欢跑到 Ops 那边看他们是如何操作的,然后发现其实他们在上线过程中执行的命令很少。因为工具好用,所以产品极少因为 Ops 这个环节出现问题,上线就变成一件比较轻松的事情。
中国雅虎的产品和业务确实不好,搜索不如百度(BIDU,107.15,-2.60%),新闻不如三大门户,“雅虎助手”是人人皆知的流氓软件,邮箱也出过丑闻,而且被 Gmail 和 QQ 邮箱远远抛在后面。中国雅虎最广为人知的也都是这些不光彩的事情,但这里我想让很多人知道,对于一个对技术还有追求的工程师来说,当时的中国雅虎真的是一个很好的工作环境。至少对于我自己来讲,我从 Yahoo 学到了太多太多的好东西,而且这些东西还只是 Yahoo 精华中的一小部分,如果不是阿里巴巴集团战略调整,我一定会在中国雅虎多呆两年。
中国雅虎之死
有个同事曾经说过:中国雅虎就是中国互联网的黄埔军校。虽然别的老牌互联网公司也为行业培养了不少人才,但是没有一个公司像中国雅虎这么悲情。很多中国雅虎的员工离职不是自己想走,而是不得不走,看着原来好好的一个公司变得完全没有前途,只好选择离开。
关注互联网的人应该都知道,在 2005 年的时候,阿里巴巴收购了中国雅虎的全部资产,并享有雅虎品牌及技术在中国的独家使用权。中国雅虎尽管之前也一直水土不服,但被阿里巴巴收购之后悲惨命运才刚刚开始。
关于中国雅虎的折腾史,大家可以去看一下这篇文章,里面说的已经很详细。从网站的变化就可以看出中国雅虎的摇摆不定,在阿里巴巴入主的这 4 年来,中国雅虎就换了 5 任总裁,每位新官上任后都会颁布新的战略,网站也会随之大变脸。“治大国若烹小鲜”,这么简单的道理我相信阿里巴巴的高层不可能不明白,就算大象可以跳舞,中国雅虎的舞姿是不是也太难看了点?由此可见,中国雅虎在阿里巴巴集团内部就是一个鸡肋,一个可有可无的品牌。
有一件事情完全可以说明马云对中国雅虎的态度。约在 2007 年前后,马云对雅虎中国资产进行了大幅度调整。在此期间,雅虎相册宣布关闭,从发出通知到服务关闭,前后不到 20 天。这种缺乏对用户起码的尊重的行为,导致相当一部分中国用户失去了存储其中的照片。而且它引发的用户对雅虎品牌的失望和不信任,对雅虎来说更是难以挽回的损失。大家都知道,“客户第一”一直都是阿里巴巴宣扬的核心价值观,难道雅虎相册的用户就不是客户?到底是马云铁了心要把雅虎品牌搞砸呢还是所谓的价值观只是口号?或者是两者皆有?
这几年中国雅虎的历史就是逐渐被瓜分的历史:搜索团队被调走,于是有了后来的淘宝网搜索引擎;IM 团队被独立出去,于是有了后来的阿里旺旺;挖走了广告搜索团队,于是有了后来的阿里妈妈;口碑网发展得不好,于是中国雅虎和口碑网合并,利用中国雅虎的品牌和技术支持口碑网;最后,中国雅虎的整个工程技术部都注入淘宝,原来的主要业务“雅虎关系”直接关闭并且推荐用户使用淘宝网的“淘江湖”。时至今日,中国雅虎已经气息奄奄,再无回天之力了。
我经常觉得,恩,马总在下一盘很大的棋,我们这些普通员工是不明白的。不然为什么“搞死中国雅虎”这个庞大的项目规划和施行得这么好?还是阿里巴巴一直在用实际行动考验中国雅虎员工的价值观呢?而且颇具讽刺意味的是,尽管马云费尽心思拿到了中国雅虎的搜索资源,最近却又和微软的 Bing 合作推出了 Etao 搜索,当初的那些搜索资源都用来做什么了呢?
还有一点不得不提的是中国雅虎和阿里巴巴之间的文化冲突。阿里巴巴一直都不能算一个真正的互联网公司,它只是以互联网作为工具,大部分业务的进行还是靠线下的销售。阿里巴巴最重视的是销售部门,整体的文化是销售文化,它所取得的成功也都只是商业上的成功,这也就从根本上决定了它不可能像 Google, Yahoo 和 Facebook 等这些真正的互联网公司具有理想主义色彩,也不可能成为优秀工程师向往的地方。马云自己也经常放言说要“超越沃尔玛(WMT,54.31,+0.26%)”,从来没有说过要超越 Google 之类的话,因为根本不在同一个领域,阿里巴巴更像一个传统的商业公司。我并不是说做电子商务的公司就不算互联网公司,同样是做电子商务,Amazon 就是互联网行业的领头羊,它非常重视技术,还是最早提供云计算服务的公司,它就是一家真正的“IT公司”。
而中国雅虎的技术资产全部来自美国 Yahoo ,工程技术部也继承了 Yahoo 的“技术文化”。“技术文化”偏重简单实用、冷静思考和解决问题;而“销售文化”则重视加油鼓劲,更喜欢喊口号,越热闹越好。我承认这两种文化都有它们的合理之处,但是强迫工程师接受那种“销售文化”就会有很多矛盾出现。阿里巴巴内部有时候玩得还比较过火,跳钢管舞倒也算了,但很多时候做游戏会直接让一个同事站到前面,然后轮流问他诸如“第一次用了多长时间”之类的问题。并不是所有人都喜欢这么玩儿的,“贱文化”和“骚文化” 的最大一个弊端就是很容易引起一些人的反感让他们觉得被侮辱,而公司不是经常倡导要对人才各尽其用么?为什么要用这样的文化把一些“思想保守”的人驱逐出去呢?我就听说过一些非常优秀的工程师因为这些东西而坚决不去参加公司的培训和集体活动,中国雅虎的很多人应该也是因为无法适应这种“销售文化”而出走的。
另外,当年和我一起通过校园招聘来到雅虎本来有不少人,在 2008 年 3 月份的时候我们还曾一起在北京参加了一个叫做“集结号”的新人培训。不过在我入职之后发现,有几个人直接被调动到了阿里巴巴在杭州的其它子公司,还有几个做搜索的同学虽然人在北京,签的却不是雅虎,而是什么“阿里巴巴集团搜索事业部”——当时雅虎的搜索部门已经被独立出去了。之后我也和那些最终没有来雅虎的同事聊过,他们都表示很郁闷,表示自己并不是很情愿去其它公司。这件事情让我感到很气愤,明明大家都是冲着中国雅虎来应聘的,为什么在发放 offer 之后又进行调动呢?当然,阿里巴巴肯定是做了一些说服工作让那些同事“自愿”服从调动的,但是那个刚好出现了金融危机工作比较难找,其它公司的招聘也早已结束,而且大家都是初出茅庐的学生,能不服从么? 那几个同事也实在是太光荣了,刚入职就完美表现了自己“拥抱变化”的价值观,KPI 应该给五分。
不只是新入职的员工,因为中国雅虎的业务变化频繁,平时也经常会出现内部调动,而中国雅虎在北京,调动的话就很有可能需要去杭州,这对于很多已经在北京安家的同事来说并不是一件小事。但不服从调动,就是价值观有问题。五十六种语言,汇成一句话:拥抱变化拥抱变化拥抱——变化。
在写这篇文章的时候,我不断提醒自己:我的目的是要让大家了解一下中国雅虎,千万不要写成针对阿里巴巴的檄文。但真实情况确实是那个样子,很多事情也是人人皆知,无法绕过去不说。相信很多人都还记得中国雅虎首页的那次糟糕的改版,把原来清爽干净的页面改成了屎黄色,据说这是当时的 CEO 金同学坐在设计师旁边亲自指导的结果。如果一个乡镇企业的老板非要外包公司的设计师把网页做成他想要的也罢了,但作为一个缺乏审美能力的 CEO 居然连“把设计的工作交给设计师”的觉悟都没有,实在让人觉得不可思议。就算是一心想要“去雅虎化”,也没有必要这么羞辱设计师们吧?
不知道为什么,有些东西不用每天灌输也深得大家认同,怎么折腾都无法斩草除根。我在雅虎的时候从来没有任何一个人和我们说“你们要热爱雅虎,要以雅虎为荣”之类的话,但是每次公司给员工发放印有雅虎 LOGO 的杯子或者背包的时候,大家总是一哄而上,疯抢干净。在中国雅虎和口碑网合并之后,因为担心以后再也领不到雅虎 LOGO 的笔记本等文具,不少同学都开始申请办公用品留作纪念。由这些事情就可以看出工程师们认同的到底是哪一种文化,大家自然会用脚投票。这些事情甚至让中国雅虎的一些非工程师同事也觉得难以理解。这种生命力强劲的外来文化可能也是阿里巴巴一直不满中国雅虎的原因。
真正的开放应该是同事之间开诚布公、乐于分享和坦然接受批评,而不是不分场合地讲荤段子,不是让别人站到前面然后问别人“第一次用的是什么姿势”;真正的“员工第二”是站在员工立场上考虑问题、虚心听取员工提出的问题,而不是在员工有意见的时候首先进行价值观教育,不是强迫员工拥抱不可理喻的变化;真正的对“用户体验”的重视是尊重用户、切身考虑用户感受,不是在年会上把某个子公司的总裁骂哭,不是为了巨额广告费用而在首页做弹窗,不是让员工为了 KPI 每隔几个月就想着改版;真正的“幸福感”是来自于发自内心的对公司的认同、对公司产品的成就感,而不是来自于整齐划一的口号和对某个人的崇拜,也不是来自于被灌输的“换个角度看世界”。脱离了原本的初衷,就算宣传得再好口号喊得再响亮,也不过是看上去很美的空洞的形式主义,这样的公司有什么底气去做“百年公司”呢?
技术的悲哀
有着世界级的研发实力却不得不悲惨收场,我想再没有人比中国雅虎的工程师更能强烈地意识到技术所能决定的事情实在是太少太少。在中国,互联网只是一个营销工具,“技术改变世界”也不过是一个笑话。那些商人们从来不相信“一个优秀的程序员抵得上一百个平庸的程序员”,却虚伪地把“我不懂技术但是尊重技术”挂在嘴边;他们整日想的不是创造价值,而是如何赚更多钱;他们更相信“廉价劳动力”所带来的成本优势,也总能把“技术密集型”的公司做成“劳动密集型”,以至于国内的互联网公司不是山寨就是血汗工厂,雇佣着大批大批会写代码的高级民工。这样的环境和氛围,暂且不说 Google 和 Apple 这样伟大的公司,什么时候我们才能有产生像 37Signals 和 The Omni Group 那样的小公司的土壤呢?
文章的最后,还是那句老话:他日江湖相逢,再当杯酒言欢。
各位雅虎人,多保重了。
-
No Comments » alibaba yahoo 文化 豆瓣 雅虎
-
Oct29
heartbeat ha.cf 中文注解
Posted in 操作系统, 系统管理, 高可用性, 629 views
-
#
# There are lots of options in this file. All you have to have is a set
# of nodes listed {"node ...} one of {serial, bcast, mcast, or ucast},
# and a value for "auto_failback".
# 这文件下面有很多的选项,你必须设置的有节点列表集{node ...},{serial,bcast,mcast,或ucast}中的一个,auto_failback的值
#
# ATTENTION: As the configuration file is read line by line,
# THE ORDER OF DIRECTIVE MATTERS!
# 注意:配置文件是逐行读取的,并且选项的顺序是会影响最终结果的。
#
# In particular, make sure that the udpport, serial baud rate
# etc. are set before the heartbeat media are defined!
# debug and log file directives go into effect when they
# are encountered.
# 特别注意,确保udpport,serial baud rate等配置在心跳检测媒体(heartbeat media)前!他们将影响debug和log file指令。
# 也就是是在定义网卡,串口等心跳检测接口前先要定义端口号。
#
# All will be fine if you keep them ordered as in this example.
# 如果你保持他们在此例子中的顺序的话一切都不会有问题。
#
# Note on logging:
# If all of debugfile, logfile and logfacility are not defined,
# logging is the same as use_logd yes. In other case, they are
# respectively effective. if detering the logging to syslog,
# logfacility must be "none".
# 记录日志方面的注意事项:
# 如果debugfile,logfile和logfacility都没有定义,日志记录就相当于use_logd yes。否则,他们将分别生效。如果要阻止记录日志到syslog,那么logfacility必须设置为“none”
#
# File to write debug messages to
# 写入debug消息的文件
#debugfile /var/log/ha-debug
#
#
# File to write other messages to
# 写入其他消息的文件
#logfile /var/log/ha-log
#
#
# Facility to use for syslog()/logger
# 用于syslog()/logger的设备
logfacility local0
#
#
# A note on specifying "how long" times below...
# 在下面指定多长时间时应该注意
# The default time unit is seconds
# 缺省的时间单位是秒
# 10 means ten seconds
# 10就代表10秒
#
# You can also specify them in milliseconds
# 1500ms means 1.5 seconds
# 你也可以指定他们以毫秒为单位
# 1500ms表示 1.5秒
#
# keepalive: how long between heartbeats?
# keepalive: 在heartbeat之间连接保持多久
#keepalive 2
#
# deadtime: how long-to-declare-host-dead?
# deadtime:
# If you set this too low you will get the problematic
# split-brain (or cluster partition) problem.
# See the FAQ for how to use warntime to tune deadtime.
# 如果这个时间值设置得太低可能会导致出现很难判断的问题,如何使用warntime来调节deadtime请查看FAQ。
#
#deadtime 30
#
# warntime: how long before issuing "late heartbeat" warning?
# See the FAQ for how to use warntime to tune deadtime.
#
#warntime 10
#
#
# Very first dead time (initdead)
#
# On some machines/OSes, etc. the network takes a while to come up
# and start working right after you've been rebooted. As a result
# we have a separate dead time for when things first come up.
# It should be at least twice the normal dead time.
# 在某些机器/操作系统等中,网络在机器重启后需要花一定的时间启动并正常工作。因此我们必须分开他们初次起来的dead time,这个值应该最少设置为两倍的正常dead time。
#
#initdead 120
#
#
# What UDP port to use for bcast/ucast communication?
# 用于bacst/ucast通讯的UDP端口
#
#udpport 694
#
# Baud rate for serial ports...
# 串口的波特率
#baud 19200
#
# serial serialportname ...
# serial 串口名称
#serial /dev/ttyS0 # Linux
#serial /dev/cuaa0 # FreeBSD
#serial /dev/cuad0 # FreeBSD 6.x
#serial /dev/cua/a # Solaris
#
#
# What interfaces to broadcast heartbeats over?
# 广播heartbeats的接口
#
#bcast eth0 # Linux
#bcast eth1 eth2 # Linux
#bcast le0 # Solaris
#bcast le1 le2 # Solaris
#
# Set up a multicast heartbeat medium
# 设置一个多播心跳介质
# mcast [dev] [mcast group] [port] [ttl] [loop]
#
# [dev] device to send/rcv heartbeats on 发送/接收heartbeats的设备
# [mcast group] multicast group to join (class D multicast address 224.0.0.0 - 239.255.255.255) 加入到的多播组(D类多播地址224.0.0.0 - 239.255.255.255)
# [port] udp port to sendto/rcvfrom udp(set this value to the same value as "udpport" above) 端口用于发送/接收udp(设置这个值跟上面的udpport为相同值)
# [ttl] the ttl value for outbound heartbeats. this effects how far the multicast packet will propagate. (0-255) Must be greater than zero.
# 外流的heartbeats的ttl值。这个影响多播包能传播多远。(0-255)必须要大于0 。
# [loop] toggles loopback for outbound multicast heartbeats.if enabled, an outbound packet will be looped back and received by the interface it was sent # on. (0 or 1) Set this value to zero.
# 为多播heartbeat开关loopback。如果enabled,一个外流的包将被回环到原处并由发送它的接口接收。(0或者1)设置这个值为0。
#
#mcast eth0 225.0.0.1 694 1 0
#
# Set up a unicast / udp heartbeat medium
# 配置一个unicast / udp heartbeat 介质
# ucast [dev] [peer-ip-addr]
#
# [dev] device to send/rcv heartbeats on 用于发送/接收heartbeat的设备
# [peer-ip-addr] IP address of peer to send packets to 包被发送到的对等的IP地址
#
#ucast eth0 192.168.1.2
#
#
# About boolean values...
# 关于boolean值
# Any of the following case-insensitive values will work for true:
# 下面的非大小写敏感的值将认为是true:
# true, on, yes, y, 1
# Any of the following case-insensitive values will work for false:
# 下面的非大小写敏感的值将认为是false:
# false, off, no, n, 0
#
#
#
# auto_failback: determines whether a resource will
# automatically fail back to its "primary" node, or remain
# on whatever node is serving it until that node fails, or
# an administrator intervenes.
# auto_failback: 决定一个resource是否自动恢复到它的primary节点,或者不管什么节点,都继续运行在上面直到节点出现故障或管# 理员进行干预。
#
#
# The possible values for auto_failback are:
# auto_failback 的可能值有:
# on - enable automatic failbacks
# on - 允许自动failbacks
# off - disable automatic failbacks
# off - 禁止自动failbacks
# legacy - enable automatic failbacks in systems where all nodes do not yet support the auto_failback option.
# legacy - 在所有节点都还不支持auto_failback的选项中允许自动failbacks
# auto_failback "on" and "off" are backwards compatible with the old "nice_failback on" setting.
# auto_failback "on"和"off"向后兼容旧的"nice_failback on"设置。
#
# See the FAQ for information on how to convert from "legacy" to "on" without a flash cut.
# (i.e., using a "rolling upgrade" process)
# 查看FAQ获取如何从"legacy"转为到"on"并不会闪断的信息。
#
#
# The default value for auto_failback is "legacy", which
# will issue a warning at startup. So, make sure you put
# an auto_failback directive in your ha.cf file.
# (note: auto_failback can be any boolean or "legacy")
# 缺省的auto_failback值是“legacy”,它在启动的时候会发送一个警告。因此,确保你在ha.cf文件中配置了auto_failback指令。
#
auto_failback on
#
#
# Basic STONITH support
# Using this directive assumes that there is one stonith
# device in the cluster. Parameters to this device are
# read from a configuration file. The format of this line is:
# 基本上STONITH支持
# 使用这个指令假设有一个stonith设备在集群中。这个设备的参数从一个配置文件中读取,这行的格式是:
#
# stonith <stonith_type> <configfile>
#
# NOTE: it is up to you to maintain this file on each node in the
# cluster!
# 注意:在集群中的每个节点上的这个文件都靠你去维护。
#
#stonith baytech /etc/ha.d/conf/stonith.baytech
#
# STONITH support
# You can configure multiple stonith devices using this directive.
# 你可以使用这个指令配置多个stonith设备:
# The format of the line is:
# 这行的格式是:
# stonith_host <hostfrom> <stonith_type> <params...>
#
# <hostfrom> is the machine the stonith device is attached to or * to mean it is accessible from any host.
# <hostfrom> 表示stonith设备联结到的机器或者用*来表示从任何主机都可以访问。
# <stonith_type> is the type of stonith device (a list of supported drives is in /usr/lib/stonith.)
# <stonith_type> 是stonith设备的类型(支持的设备的列表在/usr/lib/stonith中)
# <params...> are driver specific parameters. To see the format for a particular device, run:
# <params...> 是驱动指定的参数,要查看特定设备的格式,运行:
# stonith -l -t <stonith_type>
#
#
# Note that if you put your stonith device access information in
# here, and you make this file publically readable, you're asking
# for a denial of service attack
# 需要注意如果你将你的stonith设备的访问信息放在这里,并且你让这个文件开放读权限,那么你是在召唤一个DoS攻击。
#
# To get a list of supported stonith devices, run
# 要得到支持的stonith设备的列表,运行
# stonith -L
#
# For detailed information on which stonith devices are supported
# and their detailed configuration options, run this command:
# 要哪个stonith设备是支持的详细信息和它们详细的配置选项,运行这个命令:
# stonith -h
#
#stonith_host * baytech 10.0.0.3 mylogin mysecretpassword
#stonith_host ken3 rps10 /dev/ttyS1 kathy 0
#stonith_host kathy rps10 /dev/ttyS1 ken3 0
#
# Watchdog is the watchdog timer. If our own heart doesn't beat for
# a minute, then our machine will reboot.
# Watchdog是一个watchdog计时器,如果我们的心超过一分钟不跳,我们的机器将会reboot。
#
# NOTE: If you are using the software watchdog, you very likely
# wish to load the module with the parameter "nowayout=0" or
# compile it without CONFIG_WATCHDOG_NOWAYOUT set. Otherwise even
# an orderly shutdown of heartbeat will trigger a reboot, which is
# very likely NOT what you want.
# 注意:如果你使用软件watchdog,你很可能希望用参数“nowayout=0”来加载这个模块或编译它的时候去掉
# CONFIG_WATCHDOG_NOWAYOUT设置。否则,即使一个有序的关闭heartbeat也会触发重启,这很可能不是你想要的。
#
#watchdog /dev/watchdog
#
# Tell what machines are in the cluster
# 说明说明机器在这个集群里面
# node nodename ... -- must match uname -n
# node nodename ... --必须要匹配uname -n
#node ken3
#node kathy
#
# Less common options...
# 非常用的选项
# Treats 10.10.10.254 as a psuedo-cluster-member
# Used together with ipfail below...
# note: don't use a cluster node as ping node
# 将10.10.10.254看成一个伪集群成员,与下面的ipfail一起使用。
# 注意:不要使用一个集群节点作为ping节点
#
#ping 10.10.10.254
#
# Treats 10.10.10.254 and 10.10.10.253 as a psuedo-cluster-member
# called group1. If either 10.10.10.254 or 10.10.10.253 are up
# then group1 is up
# Used together with ipfail below...
# 将10.10.10.254和10.10.10.254看成一个叫group1的伪集群成员。如果10.10.10.254或10.10.10.253是up的,那么group1为up
# 与下面的ipfail一起使用。
#
#ping_group group1 10.10.10.254 10.10.10.253
#
# HBA ping derective for Fiber Channel
# Treats fc-card-name as psudo-cluster-member
# used with ipfail below ...
# 用于Fiber Channel的HBA ping指令,将fc-card-name看成是伪集群成员,与下面的ipfail一起使用。
#
# You can obtain HBAAPI from http://hbaapi.sourceforge.net. You need
# to get the library specific to your HBA directly from the vender
# To install HBAAPI stuff, all You need to do is to compile the common
# part you obtained from the sourceforge. This will produce libHBAAPI.so
# which you need to copy to /usr/lib. You need also copy hbaapi.h to
# /usr/include.
# 你可以从http://hbaapi.sourceforge.net获取HBAAPI,你需要从vender获得用于你的HBA指令的特定的库来安装HBAAPI。
# 你所需要做的是编译你从sourceforge获得的通用部分,它会生成libHBAAPI.so,然后你要将它拷贝到/usr/lib目录。同时
# 你也要吧hbaapi.h拷贝到/usr/include 。
#
# The fc-card-name is the name obtained from the hbaapitest program
# that is part of the hbaapi package. Running hbaapitest will produce
# a verbose output. One of the first line is similar to:
# Apapter number 0 is named: qlogic-qla2200-0
# Here fc-card-name is qlogic-qla2200-0.
# fc-card-name是从hbaapitest程序获取的名字,它是hbaapi包的一部分。运行hbaapitest将生成一个冗长的输出,其中第一行类似:
# Apapter number 0 is named: qlogic-qla2200-0
# 在这里fc-card-name是qlogic-qla2200-0
#
#hbaping fc-card-name
#
#
# Processes started and stopped with heartbeat. Restarted unless
# they exit with rc=100
# 与heartbeat一起启动和停止的进程。重启,除非它们的以rc=100退出。
#
#respawn userid /path/name/to/run
#respawn hacluster /usr/lib/heartbeat/ipfail
#
# Access control for client api
# default is no access
# 用于客户端api的访问控制,缺省为不可访问。
#
#apiauth client-name gid=gidlist uid=uidlist
#apiauth ipfail gid=haclient uid=hacluster###########################
#
# Unusual options.
# 非常选项
###########################
#
# hopfudge maximum hop count minus number of nodes in config
#hopfudge 1
#
# deadping - dead time for ping nodes 上面设置的用来ping的节点的死亡时间
#deadping 30
#
# hbgenmethod - Heartbeat generation number creation method,Normally these are stored on disk and incremented as needed.
# hbgenmethod - Heartbeat产生数字的生产方法。通常执行存储在磁盘上并在需要时进行增量。
#
#hbgenmethod time
#
# realtime - enable/disable realtime execution (high priority, etc.) defaults to on
# realtime - 允许/禁止实时执行(高优先级)缺省为on
#realtime off
#
# debug - set debug level .defaults to zero
# debug - 设置debug等级,缺省为0
#debug 1
#
# API Authentication - replaces the fifo-permissions-based system of the past
# APT认证 - 代替以前的fifo-permission-base系统
#
# You can put a uid list and/or a gid list.If you put both, then a process is authorized if it qualifies under either the uid list, or under the gid list.
# 可以放上一个uid列表和/或gid列表。如果两个都放,那么符合uid列表或gid列表中的进程都将通过验证
#
#
# The groupname "default" has special meaning. If it is specified, then
# this will be used for authorizing groupless clients, and any client groups
# not otherwise specified.
# 组名“default”有特定的意思。如果它被指定,那么它将用于验证无组的客户端和任何没有另外指定的客户组
#
# There is a subtle exception to this. "default" will never be used in the
# following cases (actual default auth directives noted in brackets)
# 这是一个复杂的表达式,“default”将从不用于下面的情况(现实中缺省的验证指令记录在括号中)
# ipfail (uid=HA_CCMUSER)
# ccm (uid=HA_CCMUSER)
# ping (gid=HA_APIGROUP)
# cl_status (gid=HA_APIGROUP)
#
# This is done to avoid creating a gaping security hole and matches the most likely desired configuration.
# 它避免生成一个安全漏洞缺口并匹配到了可能很多人最渴望的配置。
#
#apiauth ipfail uid=hacluster
#apiauth ccm uid=hacluster
#apiauth cms uid=hacluster
#apiauth ping gid=haclient uid=alanr,root
#apiauth default gid=haclient# message format in the wire, it can be classic or netstring,
# default: classic
# 网线中的信息格式,可以是classic或netstring
#
#msgfmt classic/netstring
#
# Do we use logging daemon?
# If logging daemon is used, logfile/debugfile/logfacility in this file
# are not meaningful any longer. You should check the config file for logging
# daemon (the default is /etc/logd.cf)
# more infomartion can be fould in http://www.linux-ha.org/ha_2ecf_2fUseLogdDirective
# Setting use_logd to "yes" is recommended
# 我们是否使用记录监控?
# 如果使用了记录监控,此文件里面的logfile/debugfile/logfacility将不再有意义。你应该检查在配置文件中是否有记录监控(缺省为/etc/logd.cf)
# 更多的信息可以在http://www.linux-ha.org/ha_2ecf_2fUseLogdDirective中找到。推荐配置use_logd为yes。
#
# use_logd yes/no
#
# the interval we reconnect to logging daemon if the previous connection failed
# default: 60 seconds
# 如果前一个连接失败了,我们再次连接到记录监控器的间隔。
#conn_logd_time 60
#
#
# Configure compression module
# It could be zlib or bz2, depending on whether u have the corresponding
# library in the system.
# 配置压缩模块
# 它可以为zlib或bz2,基于我们的系统中是否有相应的库。
#
#compression bz2
#
# Confiugre compression threshold
# This value determines the threshold to compress a message,
# e.g. if the threshold is 1, then any message with size greater than 1 KB
# will be compressed, the default is 2 (KB)
# 配置压缩的限度
# 这个值决定压缩一个信息的限度,例如:如果限度为1,那么任何大于1KB的消息都会被压缩,缺省为2(KB)
#compression_threshold 2用 Flock 浏览器 创建 -
No Comments » cib crm ha ha.cf heartbeat
-
Oct28
heartbeat CRM管理程序功能示例
Posted in 操作系统, 系统管理, 高可用性, 773 views
-
heartbeat 2.x使用CRM进行集群资源和管理的工作,除了提供hb_gui图形管理工具外,还可以使用crm_resource程序进行管理。以下内容截取自:分享:heartbeat 2.x style的配置,供参考。
1)查看所有资源
crm_resource -L
2)查看资源跑在哪个节点上
crm_resource -W -r runhttpd.sh_2
resource runhttpd.sh_2 is running on: server1
crm_resource -W -r runhttpd.sh_2
resource runhttpd.sh_2 is NOT running
4)启动/停止资源
crm_resource -r runhttpd.sh_2 -p target_role -v started
crm_resource -r runhttpd.sh_2 -p target_role -v stopped5)查看资源在cib.xml中的定义
crm_resource -x -r runhttpd.sh_2
6)将资源从当前节点移动向另个节点
crm_resource -M -r runhttpd.sh_2
7)将资源移向指定节点
crm_resource -M -r runhttpd.sh_2 -H c001n02
允许资源回到正常的节点
crm_resource -U -r runhttpd.sh_2
引用NOTE: the values of resource_stickiness and default_resource_stickiness may mean that it doesnt move back. In such cases, you should use -M to move it back and then run this command.9)将资源从CRM中删除
crm_resource -D -r runhttpd.sh_2 -t primitive
10)将资源组从CRM中删除
crm_resource -D -r my_first_group -t group
11)将资源从CRM中禁用
crm_resource -p is_managed -r runhttpd.sh_2 -t primitive -v off
12)将资源从新从CRM中启用
crm_resource -p is_managed -r runhttpd.sh_2 -t primitive -v on
13)Resetting a failed resource after having been manually cleaned up
crm_resource -C -H c001n02 -r runhttpd.sh_2
14)检查所有节点上未在CRM中的资源
crm_resource -P
15)检查指定节点上未在CRM中的资源
crm_resource -P -H c001n02
引用Querying a parameter of a resource. Say the resource is the following:
<primitive id="example_mail" class="ocf" type="MailTo" provider="heartbeat">
<instance_attributes id="example_mail_inst">
<attributes>
<nvpair id="example_mail_inst_attr0" name="email" value="root"/>
<nvpair id="example_mail_inst_attr1" name="subject" value="Example Failover"/>
</attributes>
</instance_attributes>
</primitive>You could query the email address using the following:
crm_resource -r example_mail -g email16)设置资源的某个属性
crm_resource -r example_mail -p email -v "myemailaddress@somedomain.com"
用 Flock 浏览器 创建标签: heartbeat, crm, crm_resource, ha
-
No Comments » cib crm ha ha.cf heartbeat

Comments