在php中对一个有五万多个元素的数组进行遍历同时做一些简单的逻辑运算,发生耗时居然达到了13秒之多,通过排发现耗时的操作都是在strtotime上,使用strtotime把字符串“2012-02-22 10:07:34”转化为秒形式。开始以为就是strtotime的效率有问题,后来突然想起来,如果在PHP 5中,如果没有显式的设置timezone,php会有一个警告信息,猜测造成strtotime耗时的原因就是php需要处理警告,在php.ini中设置date.timezone = PRC 后在测试,果然不需要那么久了。
总结:在php 5后需要设置timezone,否则可能在进行日期、时间操作函数造成性能问题,另外在错误日志会出现大量的警告信息。
Replica Set 节点类型分为三种:
- standard:常规节点,它存储一份完整的数据副本,参与选举投票,有可能成为primary节点;
- passive:存储了完整的数据副本,参与投票,不能成为primary节点;
- arbiter:仲裁节点,只参与投票,不接收复制的数据,也不能成为primary节点。
本文配置使用2个常规节点和一个arbiter节点,arbiter节点由于不同步数据,所以负载会很小,部署对硬件没有太大的要求。
假设192.168.1.211、192.168.1.212为常规节点,192.168.1.68为arbiter节点。三个节点上的mongodb都是用下面的配置文件,文件存放在/etc/mongodb.cnf:
dbpath = /data/db/
logpath = /data/log/m.log
logappend = true
port = 27017
fork = true
directoryperdb = true
journal = true
replSet = test
rest = true
其中replSet 的 Id 为 test,这个值对应initiate中的”_id”,使用rest参数后可以在web管理界面中显示Replica Set中其他mongodb实例的信息。
使用命令
/usr/local/mongodb/bin/mongod --config /etc/mongodb.cnf
分别启动三个机器上的mongodb实例,使用mongodb客户端登陆两个常规节点中的任何一个,执行如下命令:
rs.initiate(
{"_id" : "test",
"members" : [
{"_id" : 1, "host" : "192.168.1.211"},
{"_id" : 2, "host" : "192.168.1.212"},
{"_id" : 3, "host" : "192.168.1.68", "arbiterOnly" : true}
]
});
或
rs.initiate(
{"_id" : "test",
"members" : [
{"_id" : 1, "host" : "192.168.1.211"},
{"_id" : 2, "host" : "192.168.1.212"}
]
});
rs.addArb('192.168.1.68');
可以使用rs.conf()查看配置情况,rs.status()查看各个节点的状态,经过一小段时间后,他们会选一台作为PRIMARY,其他的常规节点为SECONDARY,同时在js shell中看到提示符从“>”变为对应的 “PRIMARY>” 或 “SECONDARY>” 或 “ARBITER>”。可以在PRIMARY是通过rs.stepDown()来切换PRIMARY,执行此命令后会在剩余的常规节点选一个来充当PRIMARY。
关于初始化中配置members的其他可选参数,可以到官网上查看,地址:http://www.mongodb.org/display/DOCS/Replica+Set+Configuration
Mongodb脚本:把命令行的内容保存到一个文件中,把该文件放在/usr/bin(或任何系统设置的PATH路径中)下,就可以直接用该文件来启动或停止服务了。
本人比较倾向把启动mongodb的参数放在配置文件中,直观且便于管理,例如把参数写入/etc目录下的mongodb.cnf文件中,参数设置如下:
#configuration Options for MongoDB
#
# For More Information, Consider:
# - Configuration Parameters: http://www.mongodb.org/display/DOCS/Command+Line+Parameters
# - File Based Configuration: http://www.mongodb.org/display/DOCS/File+Based+Configuration
dbpath = /data/db/
logpath = /data/log/m.log
logappend = true
#bind_ip = 127.0.0.1
port = 27017
fork = true
#auth = true
noauth = true
directoryperdb = true
journal = true
可以使用命令:
/usr/local/mongodb/bin/mongod --config /etc/mongodb.cnf
来启动mongodb,所以启动脚本就可以这么写
#!/bin/sh
/usr/local/mongodb/bin/mongod --config /etc/mongodb.cnf
假设该文件命名为mongodb-start,存放于/usr/bin下,现在就可以直接用mongodb-start来启动服务了,注意,该文件要有执行的权限。
停止mongodb服务脚步如下:
#!/bin/bash
pid=`ps -o pid,command ax | grep mongod | awk '!/awk/ && !/grep/ {print $1}'`;
if [ "${pid}" != "" ]; then
kill -2 ${pid};
fi
其实就是通过ps、grep、awk命令找到mongod的进程号,在通过kill来关闭mongod服务,当然查询进程号的命令还有很多,任取一种即可,例如:
ps -C mongod -f | grep mongod |tr -s ' ' | cut -d ' ' -f 2
或
ps aux | grep mongod | grep -v "grep" | awk -F" " '{print $2}'
NFS服务器端需要安装nfs-utils和portmap这两个安装包,同时要确保nfs、portmap服务启动。把需要共享出去的目录添加在/etc/exports文件中,格式为:
服务器上共享的目录 客户端主机名称1或IP1(参数1,参数2) 客户端主机名称2或IP2(参数3,参数4)
注意:可以在一条中设置多个客户端,也可以使用字码的方式来确定某一个网段的客户机,例如:192.168.1.0/24,参数和前面的ip之间没有空格,可以指定多个参数,可用的参数如下:
- rw:可读写的权限;
- ro:只读权限
- no_root_squash:客户端登陆 NFS 主机使用共享目录的使用者,如果是 root 的话,那么对于这个共享的目录来说,他就具有 root 的权限,这个参数可能造成安全隐患
- root_squash:客户端登陆 NFS 主机使用共享目录的使用者,如果是 root 的话,那么这个使用者的权限将被压缩成为匿名使用者,通常他的 UID 与 GID 都会变成 nobody 那个系统账号的身份;
- all_squash:不论客户端登陆 NFS 的使用者身份为何,他的身份都会被压缩成为匿名使用者,通常也就是 nobody ;
- anonuid:前面关于 *_squash 提到的匿名使用者的 UID 设定值,通常为 nobody,但是您可以自行设定这个 UID 的值,当然,这个 UID 必需要存在于您的 /etc/passwd 中;
- anongid:同 anonuid ,但是变成 group ID 就是了;
- sync:数据同步写入到内存与硬盘当中;
- async:数据会先暂存于内存当中,而非直接写入硬盘。
需要说明的是通过rw设置的读写权限还需要根据当前登录的用户来判断,例如使用参数(rw,root_squash),假设服务器的上的目录owner是用户 test ,且目录权限是744,这样的话,客户端mount上的共享文件还是没有写的权限。对于权限这一块比较搞人,最简单的办法是使用参数(rw,no_root_squash),这样,只要客户端是使用root登陆的,那么它mount上的共享目的就有一切权限了。
例如把服务器端目录/data/nfs-dir-192.168.1.211共享给ip为192.168.1.211的客户端,配置如下:
/data/nfs-dir-192.168.1.211 192.168.1.211(rw,sync,no_root_squash)
这样就配置完成了,启动portmap和nfs服务(service port start、service nfs start 或 /etc/init.d/portmap start、/etc/init.d/nfs start),可以通过命令exportfs -v查看共享的目录。修改了配置文件后,在不重启nfs服务的情况下也可以使用exportfs -r来使新的配置生效。
客户端使用mount命令就可以把服务器端的共享目录mount到本地,例如把上述服务器端的目录mount到本地的/data目录上:
mount -t nfs 192.168.1.68:/data/nfs-dir-192.168.1.211/ /data
可以把上述命令加入到/etc/rc.local中,这样重启后会自动挂载服务器的共享目录到本地。
按照常理,把如下命令
/usr/local/mongodb/bin/mongod --dbpath=/data/db/ --fork --logpath=/data/log/m.log --directoryperdb
放在/etc/rc.local文件中就可以实现开机自启动了,第一次重启机器发现mongodb顺利启动了,再次重启机器后,通过ps没有查看到相应mongod进程,也就是启动失败了。原因是由于重启机器,导致非正常停止mongod服务,mongod.lock中还记录了上次运行的进程号,为了数据的安全需要执行 /usr/local/mongodb/bin/mongod –repair,当然如果直接把mongod.lock文件删除也可以重新启动了,例如:
/usr/local/mongodb/bin/mongod --repair
/usr/local/mongodb/bin/mongod --dbpath=/data/db/ --fork --logpath=/data/log/m.log --directoryperdb
或
rm -rf /data/db/mongod.lock
/usr/local/mongodb/bin/mongod --dbpath=/data/db/ --fork --logpath=/data/log/m.log --directoryperdb
注意上述启动Mongodb都是没有增加journal参数,如果带了此参数就不会那么麻烦了,例如
/usr/local/mongodb/bin/mongod --dbpath=/data/db/ --fork --logpath=/data/log/m.log --directoryperdb --journal
就可以了,就算是非正常重启机器,mongodb也会根据日志去修复数据库的。
另外,如果mongodb的数据目录是通过mount的NFS文件夹,自启动好像有问题的。
python的int型最大值和系统有关,32位和64位系统看到的结果是不一样,分别为2的31次方减1和2的63次方减1,可以通过sys.maxint查看此值。
python2.4版本以后,如果int的值超出范围不会溢出,而是内部转换为long,找了很久似乎没有从long型强制转换成int,这里所说的int取值范围是和java里一致,即用四个字节表示。代码如下:
def longToInt(value):
if value > 2147483647 :
return (value & (2 ** 31 - 1))
else :
return value
通过测试,在32位和64位上运算结果一致,另外2 ** 31 – 1换成常量2147483647对性能有微小的提升。
PyMongo库提供了python操作mongodb的接口,如果要用python来操作mongodb,就必须安装PyMongo。安装有很多方法,这里介绍两种。
源码安装:
PyMongo的源码存放在git库中,可以使用git下载到本地,git的安装参照:http://www.netingcn.com/centos-git.html,安装命令如下:
git clone git://github.com/mongodb/mongo-python-driver.git pymongo
cd pymongo/
python setup.py install
使用easy_install安装:
easy_install是一个工具,不是系统自带,需要安装,它的作用类似于Php中的pear,或者Ruby中的gem,或者Perl中的cpan。安装命令如下:
wget -q http://peak.telecommunity.com/dist/ez_setup.py
python ez_setup.py
使用安装PyMongo命令为:
easy_install pymongo
由于软件源中没有,就不能使用yum来安装,不过通过源码安装也很简单。
git下载地址:http://code.google.com/p/git-core/downloads/list,我下载的是git-1.7.9.tar.gz ,下载命令:
wget http://git-core.googlecode.com/files/git-1.7.9.tar.gz
然后执行:
tar -xvf git-1.7.9.tar.gz
cd git-1.7.9/
./configure
make && make install
就可以了,git依赖zlib-devel,openssl-devel,perl,cpio,expat-devel,gettext-devel这些包,如果configure报错,通过yum安装缺失的依赖包即可。
假设有两台linux主机A和B,当A连接B时不需要输入密码,实现方法是在A主机上使用ssh-keygen命令生成一对公私钥,默认存储路径为~/.ssh/,同相对应的公钥内容追加到到B主机上~/.ssh/authorized_keys文件中即可。具体操作如下:
连接上A主机,使用如下命令:
ssh-keygen -t rsa
回车会让你输入存放公私钥的路径和名称,默认存放在~/.ssh/目录下
接下来输入一个口令,用来保护这个私钥,如果此处你输入了口令,则在连接你上传公钥的机器时会问你要这个密码的,如果口令为空,就可以直接连接上,没有口令很不安全的,一旦有人复制了你的passphrase,那么他就可以不用密码登录上了。
把公钥上传到B主机,命令如下:
cat 公钥文件 | ssh 用户@192.168.1.9 "cat - >> ~/.ssh/authorized_keys"
注意,如果不存在~/.ssh文件夹,需要手工创建,同时需要设置目录的访问权限。
至此,就完成免密码登陆,这时使用ssh,scp命令就不需要输入B主机的密码了。
查看cpuinfo中是否有lm,如果有lm表示支持64位,lm的意思是long mode,具体命令如下:
cat /proc/cpuinfo | grep flags
检查输出里面是否有 lm 字符
或
cat /proc/cpuinfo | grep flags | grep lm | wc -l
输出结果大于 0 表示支持64位