判断远端主机死活,发送飞信短信通知[原创]

Posted: 2009年4月28日星期二
写了个脚本判断远端主机的死活,每隔5分钟检查一次,远端主机是否正常,如死掉了就发送飞信短信到管理员手机上,若管理员不处理,每隔5分钟发一次。脚本内容如下:

#!/bin/sh
IP=172.16.10.100
healthcheck(){
ping -c 1 -w 1 $IP > /dev/null
return $?
}
send_message(){
curl -d username=15000000000 -d password=123456 -d sendto=15000000000 -d message="远端主机$IP已经down掉了" http://sms.api.bz/fetion.php
}
while true; do
while healthcheck; do
echo "health ok!"
sleep 300
done
echo "fail over!"
send_message
sleep 300
done

说明:curl中的几个参数进行说明一下文中采用了http://sms.api.bz的web发送接口,通过curl post数据到http://sms.api.bz,username是飞信的用户名,password是飞信的密码,sendto是发送到飞信好友手机(要发送飞行短信,只能发送给飞信的好友用户)。下面就是一个循环,每隔300秒进行检查,当服务器死掉后,自动发送短信到飞信的好友手机上,如服务器一直没有起来,就每隔300秒再进行一次检查,发送1条报警短信。

感谢http://sms.api.bz提供web发送接口。

搭建Tokyo Tyrant的故障转移

Posted: 2009年4月27日星期一
以前写了一篇关于tokyo tyrant的replication实现了高可靠性,文中最后说了它的几个缺点,本文中将通过tokyo tyrant更高级的特性,故障转移机制,解决这些问题。本文介绍tokyo tyrant的的故障转移机制,有点像lvs的主从机制。当主DB down掉的时候,自动的把备份DB转为主db,提供服务,而不需要人工的干预。同时采用tokyo tyrant的replication机制,保证数据完整性的同时,还具有遇到故障自动切换主从服务器,实现高可靠性。
下面是一个tokyo tyrant的故障转移的实例,现看实现原理图

在同一台机器上打开3个窗口。
在终端A中创建主DB更新log文件夹
mkdir /tmp/ulog-a
在终端A中启动服务ttserver -port 1978 -ulog /tmp/ulog-a -sid 1 -mhost localhost -mport 1979 -rts /tmp/a.rts /tmp/casket-a.tch
在终端B中创建辅DB更新log文件夹mkdir /tmp/ulog-b
在终端B中启动辅DBttserver -port 1979 -ulog /tmp/ulog-b -sid 2 -mhost localhost -mport 1978 -rts /tmp/b.rts /tmp/casket-b.tch
在终端C中对主DB插入测试数据tcrmgr put -port 1978 localhost TTTest TestByZLJ
在终端C中查询主DBtcrmgr get -port 1978 localhost TTTest
在终端C中查询辅DBtcrmgr get -port 1979 localhost TTTest
模拟主DB down掉,在终端A中按下Ctrl+C
在终端C中对辅db进行数据插入操作tcrmgr put -port 1979 localhost test TTTest
在终端C中对辅DB进行数据检索操作tcrmgr get -port 1979 localhost test
在终端A中重新启动主DBttserver -port 1978 -ulog /tmp/ulog-a -sid 1 -mhost localhost -mport 1979 -rts /tmp/a.rts /tmp/casket-a.tch
在终端C中对主DB进行数据检索tcrmgr get -port 1978 localhost test
最后查询得到的结果还是TTTest,在对辅DB进行插入操作的时候主DB已经down掉了,而当主DB重新起来后,对主DB再次进行查询得到了我们想要的结果。也就是说主DB重新起来后自动的从辅DB进行数据同步操作,保证数据的完整性,同时也为SA有时间去处理这类故障。

使用kickstart批量安装Linux

Posted: 2009年4月26日星期日
作为一名SA,在工作当中会经常安装Linux操作系统,对多台服务器配置同样的环境。如果一个个去安装,一台台去配置,那是一件吃力不讨好的事情。现只要你有一台安装好的Linux,要安装的服务器能支持pxe网络启动安装,所有的服务器能组建在一个局域网,几十台服务器不到半个小时不仅安装好系统同时也完成基本的配置。在Redhat系列操作系统中有个叫Kickstart软件,它的作用是的按照事先设计好的方式自动安装操作系统。最常见的方式是网络安装,也可以采用CDROM或硬盘安装。本文主要介绍Kickstart的网络安装。其中kickstart网络安装方式支持nfs,ftp,http的方式进行安装。本文中实例是通过nfs的方式安装centos,同样适合于安装redhat,fedora等操作系统。
本文的实施方案的拓扑图如下所示
                 ┌────────┐
                 │  Boot Server   │
                 │(DHCP TFTP NFS)│
                 └────┬───┘
                          │
                ┌────┴───┐
                │      Switch   │
                └────┬───┘
                         │
          ┌───────┴───────┐
          │                            │
  ┌───┴───┐              ┌───┴───┐
  │  Client(PxE)│              │  Client(PxE)│
  └───────┘              └───────┘实施步骤
1.配置启动服务器
2.配置安装方案
3.启动待安装服务器,进行系统安装

配置启动服务器
启动服务器的目的是帮助待安装机器上启动Red Hat Linux安装程序。启动服务器上需要搭建一个DHCP 服务器和一个TFTP 服务器,一个nfs用来传输网络镜像文件。前者是为了给待安装机器分配IP地址,后者则是提供了一个让待安装机器下载启动镜像的途径。
首先配置DHCP服务
1) 安装DHCP服务器包(RPM包名:dhcpd)。
2)配置服务器IP地址
3) 编辑DHCP服务器配置文件 /etc/dhcp.conf。

ddns-update-style interim;
ignore client-updates;
allow booting;
allow bootp;

subnet 192.168.0.0 netmask 255.255.255.0 {
    option routers            192.168.0.1;
    option subnet-mask        255.255.255.0;
    option domain-name-servers    192.168.0.1;
    range dynamic-bootp 192.168.0.128 192.168.0.254;
    default-lease-time 21600;
    max-lease-time 43200;
    #deny unknown-clients;

    #group pxe {
        next-server 192.168.0.4;
        filename "/centos/pxelinux.0";
        #host client { hardware ethernet 00:00:00:00:00:00; fixed-address 192.168.0.100; }
     }     
}

注:如需给指定的服务器进行安装的话,就去掉上面的注释。
    简单说一下文中的注释,deny unknown-clients;拒绝给为授权机器分配IP地址
    next-server 指定启动服务器地址,filename指定启动文件地址。
    host client为mac地址为00:00:00:00:00:00的client服务器指定IP地址为:192.168.0.100.

4) 给启动服务器配置一个IP,这个IP必须在DHCP服务器定义的子网内。
5) 启动DHCP服务。
service dhcpd start

配置TFTP服务器(如没有安装xinetd软件包,先安装这个软件包)

1) 安装TFTP服务器包(RPM包名:tftpd)。
2) 编辑TFTP 服务器的配置文件 /etc/xinetd.d/tftp。配置文件如下:

service tftp
{
    socket_type     = dgram
    protocol        = udp
    wait            = yes
    user            = root
    server          = /usr/sbin/in.tftpd
    server_args     = -s /tftpboot
    disable         = no
}

这里选定了/tftpboot为TFTP 服务器的根目录位置。
3)启动TFTP服务
service xinetd start
4)建立存放Linux安装程序的内核/根文件系统文件的目录
mkdir /tftpboot/centos
复制Centos光盘的/isolinux目录下Linux安装程序内核/根文件系统文件initrd.img 和vmlinuz到
/tftpboot/centos
5)将启动镜像文件pxelinux.0复制到TFTP服务器根目录。
启动镜像pxelinux.0可以在syslinux安装包里获得。安装好syslinux安装包后,将pxelinux.0复制到/tftpboot/centos
cp /usr/lib/syslinux/pxelinux.0 /tftpboot/centos
启动镜像pxelinux.0文件在执行过程中,会读取配置文件以确定它应该载入什么Linux内核文件来运行。所有的配置文件都放在启动服务器的/tftpboot/centos/pxelinux.cfg/目录下。
建立启动配置文件存放文件夹mkdir /tftpboot/centos/pxelinux.cfg
6)建立启动配置文件default

default centos5
label centos5
kernel vmlinuz
append load initrd=initrd.img ksdevice=eth0 ks=nfs:192.168.0.4:/home/centos/ks.cfg devfs=nomount


配置nfs
配置nfs共享目录,nfs的配置文件为/etc/exports
/home/centos *(ro,no_root_squash)
启动nfs相关服务
service portmap start
service nfs start
确认共享目录成功了
showmount -e localhost
若得到结果包含/home/centos * ,说明成功配置好nfs

配置安装方案
配置文件为/home/centos/ks.cfg

text
install
repo --name=epel --baseurl=http://download.fedora.redhat.com/pub/epel/5/x86_64/
nfs --server=192.168.0.4 --dir=/home/centos/
keyboard us
lang en_US
key --skip
xconfig --defaultdesktop=GNOME --depth=8 --resolution=640x480
network --bootproto=dhcp --device=eth0 --onboot=on
#network --bootproto=dhcp --device=eth1 --onboot=on
rootpw --iscrypted $1$Sl6MDA1O$Z2HRda3FpCmaSRqrmD.gD0
user --name test --homedir /home/test --iscrypted --password=$1$IXb255iK$wZq/pCb2o70P1F8pXnI6P/ --shell=/bin/bash --groups=test,wheel
firewall --disabled
auth --useshadow --enablemd5
selinux --disabled
timezone --isUtc Asia/Shanghai
bootloader --location=mbr
logging --level=info

clearpart --all --drives=sda
part /boot --bytes-per-inode=4096 --fstype="ext3" --size=150
part swap --bytes-per-inode=4096 --fstype="swap" --size=2048
part pv.01 --size=1 --grow
volgroup lvm pv.01
logvol / --vgname=lvm --size=20480 --name=root
logvol /var --vgname=lvm --size=20480 --name=var
logvol /tmp --vgname=lvm --size=20480 --name=tmp
logvol /data --vgname=lvm --size=1 --grow --name=data
reboot

%packages
@editors
@development-libs
@base
@development-tools
-firstboot-tui
ntp
net-snmp-utils
net-snmp-libs
net-snmp
openssl-devel
nrpe
nagios-plugins
nagios-plugins-all

%post --log=/mnt/sysimage/root/anaconda-post.log --erroronfail
/bin/cat << EOF >/etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0
BOOTPROTO=none
HWADDR=`ifconfig eth0 |grep HWaddr |awk '{print $5}'`
ONBOOT=yes
NETMASK=`ifconfig eth0|sed -e 's/^.*Mask:\([^ ]*\)$/\1/p' -e d`
IPADDR=`ifconfig eth0|sed -e 's/^.*inet addr:\([^ ]*\).*$/\1/p' -e d`
GATEWAY=`netstat -rn|grep eth0|awk '{print $2}' | grep -v 0.0.0.0`
TYPE=Ethernet
EOF
echo "nameserver 192.168.0.1" > /etc/resolv.conf

#disable ipv6
sed -i '/NETWORKING_IPV6=/s/yes/no/' /etc/sysconfig/network
echo "alias net-pf-10 off" >> /etc/modprobe.conf
echo "alias ipv6 off" >> /etc/modprobe.conf
/sbin/chkconfig --level 35 ip6tables off

### Setting to ssh
/usr/bin/patch /etc/ssh/sshd_config << EOF
13c13
< #Port 22
---
> Port 30000
39a40
> PermitRootLogin no
60c61
< PasswordAuthentication yes
---
> PasswordAuthentication no
110c111
< #UseDNS yes
---
> UseDNS no
EOF
/sbin/restorecon /etc/ssh/sshd_config

/bin/mkdir ~test/.ssh
/bin/chmod 700 ~test/.ssh
/bin/cat << EOF > ~test/.ssh/authorized_keys
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA3NhtQhIrjeJy5WIlohdTn9SooaTsxpSiBljhx189b08DyC3xALH6R87RvX7+6jwJF/TqzwhZ495HTDfl7en98Dp97Xi8tYibPm9E3QBil9PGG+952flgVxTZZvS+D/rJ/7vuIp8iAiO9u3JUsZWP7X0dIaNhrnVfL31juk8I/EippzzMkjzUeRg62UizCxVD7AynwnqAsPdr6kcv9MGAZOvg7lDMv2Orbgsl0nakwtt+jmtQPGziLW+nQFVlHXTekmiJ2bDfURlRDWaegOftD+qGN3pIjO1TFCxgZccagYAVg1Jm+mFHIMIlmwpTcmBXO9DjjAhj6BXVbBNArqU5lQ== test@test.com
EOF
/bin/chmod 644 ~test/.ssh/authorized_keys
/bin/chown -R test:test ~test/.ssh/

### disable not wheel group user use su chang to root
sed -i '6s/^#auth/auth/g' /etc/pam.d/su

### Setting SNMP
/bin/cat << EOF > /etc/snmp/snmpd.conf
com2sec localhost localhost COMMUNITY_STRING
com2sec localnet 192.168.0.0/24 COMMUNITY_STRING

group test v1 localhost
group test v2c localhost
group test v1 localnet
group test v2c localnet

view all included .1 80

access test "" any noauth exact all none none
access test "" any noauth exact all all none

disk / 100000
EOF
/sbin/restorecon /etc/snmp/snmpd.conf

### disable CTRL-ALT-DELETE
/usr/bin/patch /etc/inittab << EOF
32c32,33
< ca::ctrlaltdel:/sbin/shutdown -t3 -r now
---
> #ca::ctrlaltdel:/sbin/shutdown -t3 -r now
> ca::ctrlaltdel:ca::ctrlaltdel:/usr/bin/logger 'CTRL-ALT-DELETE trap is disabled'
EOF
/sbin/restorecon /etc/inittab

### vim
/bin/sed -i "8 s/^/alias vi='vim'/" /root/.bashrc
/bin/echo 'syntax on' > /root/.vimrc

### ntp time set
/bin/echo '15 3 * * * /usr/sbin/ntpdate 192.168.0.4 > /dev/null 2>&1' >> /var/spool/cron/root

### Setting nagios monitor
/bin/cat << EOF > /etc/nagios/nrpe.cfg
log_facility=daemon
pid_file=/var/run/nrpe.pid
server_port=5666
#If you want monitor to oracle please change nrpe_uset and nrpe_group to oracle user an oracle group
nrpe_user=nrpe
nrpe_group=nrpe
allowed_hosts=192.168.0.4
dont_blame_nrpe=0
debug=0
command_timeout=60
connection_timeout=300
command[check_ping]=/usr/lib64/nagios/plugins/check_ping -H 172.16.10.13 -w 500,10% -c 1000,25%
command[check_load]=/usr/lib64/nagios/plugins/check_load -w 9.0,7.0,6.0 -c 10.0,8.0,7.0
command[check_disk_root]=/usr/lib64/nagios/plugins/check_disk -w 20% -c 10% -p /
command[check_disk_var]=/usr/lib64/nagios/plugins/check_disk -w 20% -c 10% -p /var
command[check_disk_tmp]=/usr/lib64/nagios/plugins/check_disk -w 20% -c 10% -p /tmp
command[check_swap]=/usr/lib64/nagios/plugins/check_swap.pl -w 50% -c 10%
command[check_zombie_procs]=/usr/lib64/nagios/plugins/check_procs -w 5 -c 10 -s Z
command[check_total_procs]=/usr/lib64/nagios/plugins/check_procs -w 150 -c 200 -s RSZDT
command[check_users]=/usr/lib64/nagios/plugins/check_users -w 3 -c 5
command[check_ssh]=/usr/lib64/nagios/plugins/check_ssh -H 127.0.0.1 -p 65508
command[check_ntp]=/usr/lib64/nagios/plugins/check_ntp -H 172.16.10.13 -w 1 -c 2
#Check Oracle Start
#command[check_oracle_tns]=/usr/lib64/nagios/plugins/check_oracle --tns oracle_tns_name
#command[check_oracle_db]=/usr/lib64/nagios/plugins/check_oracle --db oracle_sid
#command[check_oracle_login]=/usr/lib64/nagios/plugins/check_oracle --login oracle_tns_name
#command[check_oracle_cache]=/usr/lib64/nagios/plugins/check_oracle --cache oracle_tns_name DB_username DB_passwd 80 90
#command[check_oracle_tablespace]=/usr/lib64/nagios/plugins/check_oracle --tablespace oracle_tns_name DB_username DB_passwd tab 90 80
#Check Oracle End
#command[check_http]=/usr/lib64/nagios/plugins/check_http -H 127.0.0.1
#command[check_dig]=/usr/lib64/nagios/plugins/check_dig -H 127.0.0.1 -l zhliji2.blogspot.com
#command[check_smtp]=/usr/lib64/nagios/plugins/check_smtp -H 127.0.0.1
#command[check_pop]=/usr/lib64/nagios/plugins/check_pop -H 127.0.0.1
#command[check_imap]=/usr/lib64/nagios/plugins/check_imap -H 127.0.0.1 -p 143
#command[check_clamd]=/usr/lib64/nagios/plugins/check_clamd -H /tmp/clamd.socket
#command[check_amavisd]=/usr/lib64/nagios/plugins/check_tcp -H 127.0.0.1 -p 10024
#command[check_spamd]=/usr/lib64/nagios/plugins/check_tcp -H 127.0.0.1 -p 783
#command[check_mysql]=/usr/lib64/nagios/plugins/check_mysql -H 127.0.0.1 -u root -p mysql root's password
EOF
/sbin/chkconfig nrpe on

###Setting IPtables
cat << EOF > /etc/sysconfig/iptables
*filter
:INPUT DROP [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [1:140]
:ping - [0:0]
-A INPUT -p icmp -m icmp --icmp-type 8 -m state --state NEW -j ping
-A INPUT -i lo -j ACCEPT
-A INPUT -s 192.168.0.0/255.255.255.255.0 -i eth0 -j ACCEPT
-A INPUT -i eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i eth0 -p icmp -m icmp --icmp-type 0 -j ACCEPT
-A INPUT -i eth0 -p icmp -m icmp --icmp-type 3 -j ACCEPT
-A INPUT -i eth0 -p icmp -m icmp --icmp-type 3/4 -j ACCEPT
-A INPUT -i eth0 -p icmp -m icmp --icmp-type 4 -j ACCEPT
-A INPUT -i eth0 -p icmp -m icmp --icmp-type 11 -j ACCEPT
-A INPUT -i eth0 -p icmp -m icmp --icmp-type 12 -j ACCEPT
-A INPUT -i eth0 -p icmp -m icmp --icmp-type 14 -j ACCEPT
-A INPUT -i eth0 -p icmp -m icmp --icmp-type 16 -j ACCEPT
-A INPUT -i eth0 -p icmp -m icmp --icmp-type 18 -j ACCEPT
-A INPUT -i eth0 -p tcp -m tcp --dport 30000 -j ACCEPT
-A INPUT -i eth0 -p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG FIN,PSH,URG -j DROP
-A INPUT -i eth0 -p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG FIN,SYN,RST,PSH,ACK,URG -j DROP
-A INPUT -i eth0 -p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG FIN,SYN,RST,ACK,URG -j DROP
-A INPUT -i eth0 -p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG NONE -j DROP
-A INPUT -i eth0 -p tcp -m tcp --tcp-flags SYN,RST SYN,RST -j DROP
-A INPUT -i eth0 -p tcp -m tcp --tcp-flags FIN,SYN FIN,SYN -j DROP
-A ping -p icmp -m icmp --icmp-type 8 -m limit --limit 1/sec -j RETURN
-A ping -p icmp -j REJECT --reject-with icmp-port-unreachable
COMMIT
*nat
:PREROUTING ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT
EOF

###disable serverices
for i in `ls /etc/rc3.d/S*`
do
CURSRV=`echo $i|cut -c 15-`
case $CURSRV in
crond | irqbalance | microcode_ctl | network | random | iptables |sshd | syslog | snmpd | nagios | nrpe )
;;
*)
chkconfig --level 235 $CURSRV off
;;
esac
done

说明:上面的脚本比较的长,它不仅完成了系统安装,还完成了一些共通的初始化配置。
下面简单介绍一下里面的几个比较重要的参数
repo --name=epel --baseurl=http://download.fedora.redhat.com/pub/epel/5/x86_64/
为方便安装时能配置好nagios监控我在安装时添加了一个额外的安装源epel,进行安装安装nrpe。如果你没有网络可以不设定这个选项。
rootpw --iscrypted $1$Sl6MDA1O$Z2HRda3FpCmaSRqrmD.gD0
设定root的秘密为:123456
user --name test --homedir /home/test --iscrypted --password=$1$IXb255iK$wZq/pCb2o70P1F8pXnI6P/ --shell=/bin/bash --groups=test,wheel
建立一个普通用户,用户名为test,组为test和wheel,密码为123456。
clearpart --all --drives=sda
清除第一块磁盘上的所有数据,它下面的参数是分区参数
分区采用普通分区加lvm两者方式混合分区
其中/boot分区为150M,swap分区为2G
根分区,var,tmp分区分别为20G,剩余的磁盘空间全部给data分区

%packages部分为要安装的软件
其中@开头的部分为软件组,-开头的为不要安装的软件包,什么都不加就代表要安装的单独软件包

%post --log=/mnt/sysimage/root/anaconda-post.log --erroronfail
这一部分是安装软件后的配置,所有配置失败的部分都进行log记录,log文件存放在/root/anaconda-post.log
/bin/cat << EOF >/etc/sysconfig/network-scripts/ifcfg-eth0
这一部分为设置它的网卡,由于最初设置的为dhcp方式分配的方式,现实中我们使用的服务器一般为固定IP
通过这几个脚本,自动把dhcp设定的IP地址转为固定IP地址

### Setting to ssh
这一部分为设定ssh,为安全起见,通过脚本更改ssh的默认端口为30000,禁止root用户远程登录,同时设定登录方式为采用密钥的方式,最后一部分是为test用户设定一个密钥,这个密钥我们平时可以通过puttygen的工具,生成的密钥,把公钥的内容粘贴这就行了。

### disable not wheel group user use su chang to root
禁止非wheel组的用户通过su命令切换到root用户

### Setting SNMP
这一部分时建立设定snmp的配置文件,我们通常会用监控软件对服务器进行监控,比如说,
通过cacti等类似的软件对服务器进行流量监控,就需要snmp服务。为方便我在这也加上了

### disable CTRL-ALT-DELETE
这一部分是禁止按下CTRL-ALT-DELETE组合键后服务器重启

### vim
这一部分是方便用vi的一些参数

### ntp time set
这一部分设定服务器的时间同步,每天3:15分跟时间服务器192.168.0.4进行时间同步

### Setting nagios monitor
这一部分时设定服务器监控,脚本比较的全,包括大部分常见的应用服务。

###Setting IPtables
这一部分是设定防火墙,只对外开放ssh端口,同时加了一些网络工具参数

### disable serverices
去掉不必要的服务,只保留必须的服务。

把centos的镜像文件放置到启动服务器的/home/centos目录下,把待安装服务器设定从网卡启动,就可以完成安装。

搭建Tokyo Tyrant replication

Posted: 2009年4月24日星期五
介绍了Tokyo Tyrant(以下简称tt)的备份和还原,保证了数据完整性,由于它不是实时备份,因而不能保证数据的完整性,当磁盘坏掉了,而这时数据没有备份,因而导致数据的不完整性。
为解决上述问题,大家知道mysql中有个replication机制可以解决数据的完整性,同样tt也有replication机制保证数据的完整性,具体实现方法,数据库服务器把本机的更新log,分批次的实时传输到别的数据库服务器,传输更新log的服务器就是我们常说的主服务器,接收更新log的服务器就是我们常说的辅服务器。replication的好处就是,管理者配置好服务器,
主辅DB服务器自动保持数据的一致性。当主服务器down后,可以把辅服务器变为主服务器
提供服务,而保证不间断服务,同时也使管理员有时间重新为辅服务器添加一个新辅服务器,重新搭建replication。
具体实现方法见下图

通过上图看到,平时辅服务器几乎不接受请求,因而造成资源浪费,特别在大压力的情况下
主服务器的负荷很重,而辅服务器几乎没有负荷。由于主服务器的数据几乎是同步的,可以采用读写分离的方式,分散服务器的压力。这也是许多高负荷系统对DB采取的一种方式。
具体实现如下图


下面通过一个实例来介绍通过tt实现replication
在同一台机器上启动3个终端
在终端A中创建主DB更新log文件夹
mkdir /tmp/ulog-master
在终端A中启动服务
ttserver -port 1978 -ulog /tmp/ulog-master /tmp/casket-master.tch
在终端A中创建辅DB更新log文件夹
mkdir /tmp/ulog-master
在终端B中启动辅DB
ttserver -port 1979 -ulog /tmp/ulog-slave -mhost localhost -mport 1978 -rts /tmp/slave.rts /tmp/casket-slave.tch
在终端C中对主DB插入测试数据
tcrmgr put -port 1978 localhost TTTest TestByZLJ
在终端C中查询主DB
tcrmgr get -port 1978 localhost TTTest
在终端C中查询辅DBtcrmgr get -port 1979 localhost TTTest
查询主DB跟查询辅DB得到同样的结果‘TTTestByZLJ’,虽然只是对主db进行了数据插入操作
但是查询辅db得到了同样的结果,这样的话就不用担心服务器磁盘坏了没有备份了。
但是replication也不是万能的,它也有它的缺点,主DB与辅DB的之间的传输有数10微秒到数100微秒的延迟,在大并发下,延迟期间,主DB down掉了,有可能在延迟时产生的数据就丢失了。同时主DB down掉以后,它不能自动的切换到辅DB,而需要人工的参与,不能实现自动化运维。

Tokyo Tyrant备份和还原

Posted:
人为的误操作,机器的不可靠性导致数据的丢失,这是会经常发生在我们的身边。为减少数据的丢失,定期的备份可以解决部分数据丢失的可能。

Tokyo Tyrant(以下简称tt)提供备份还原机制实现高可靠性的功能。
只需要简单简单的把数据库文件进行拷贝,就能完成备份功能,具体实现方法见下图

下面通过简单的实例进行测试:
在同一台机器上启动2个终端,在终端A中启动服务
ttserver /tmp/casket.tch
在终端B中插入测试数据
tcrmgr put localhost TTTest TestByZLJ
在终端B中查询刚刚插入的测试数据
tcrmgr get localhost TTTest
在终端B中备份数据库文件
tcrmgr copy localhost /tmp/backup.tch
模拟服务down掉,在终端A中按下ctrl-c键
模拟数据库文件丢失,在终端A中删除数据库文件
rm /tmp/casket.tch
还原数据库文件
cp /tmp/backup.tch /tmp/casket.tch
在终端A中重新启动服务
ttserver /tmp/casket.tch
在终端B中检索数据
tcrmgr get localhost TTTest
最后我们得到的结果还是:TestByZLJ,说明成功的还原了数据
以上只是通过简单的文件复制完成了数据备份与还原,这种方法有它的缺点就是,在上面的文件备份过程中更新的数据有可能就得不到还原。下面将通过另外一个功能解决以上的缺点
在mysql 可以通过binary log的方式恢复数据,oracle也有redo log的方式恢复数据,
tt同样也有通过更新log的方式恢复数据,也就是说,所有对db的更新操作在log中都有操作记录,通过tt自有的log还原数据机制能把数据还原回来。
下面通过简单的实例进行测试:
在同一台机器上启动2个终端,建立一个目录用来保持log
mkdir /tmp/ulog
在终端A中启动服务ttserver -ulog /tmp/ulog /tmp/casket.tch
在终端B中插入测试数据
tcrmgr put localhost TTTest TestByZLJ
在终端B中查询刚刚插入的测试数据
tcrmgr get localhost TTTest
模拟服务down掉,在终端A中按下ctrl-c键
模拟数据库文件丢失,在终端A中删除数据库文件
rm /tmp/casket.tch
备份更新log文件
mv /tmp/ulog /tmp/ulog-back
在终端A中重新启动服务
ttserver /tmp/casket.tch
通过更新log还原数据
tcrmgr restore localhost /tmp/ulog-back
在终端B中检索数据
tcrmgr get localhost TTTest
最后我们得到的结果还是:TestByZLJ,说明成功的还原了数据。
它有个缺点:每次操作都有log记录,慢慢的文件就会变得越来越大,很容易磁盘用尽,可以通过备份数据库文件和保存部分更新log文件,两者一起解决这个问题,具体做法:定期备份数据文件和更新log,对很老的备份更新log进行删除,当需要还原数据时,先通过还原备份数据库文件,由于在还原数据时写入的数据会写更新log文件,还原后再通过更新log文件
进行还原数据库时写入的数据,就可以完全的还原数据,具体做法看下图

php操作Tokyo Cabinet与操作memcache效率比较

Posted: 2009年4月22日星期三
先说我的服务器环境,1G内存,双核Xeon 2.00的CPU,服务器采用rpm方式部署apahce,php
Tokyo Cabinet的安装方法及PHP操作Tokyo Cabinet方法请见上篇

在测试之前,先安装一个php模块--Benchmark,安装方法如下
/usr/local/php/bin/pear install Benchmark

下面写一个脚本分别对tokyo cabinet进行一万次插入,一万次查询,一万次更新
一万次删除操作
脚本的内容如下

include_once( 'Benchmark/Timer.php' );
$timer = new Benchmark_Timer();
include_once( 'Net/TokyoTyrant.php' );
$tt = new Net_TokyoTyrant();
$tt->connect( 'localhost', 1978 );
$timer->start();
for ( $i = 0; $i < 10000; $i++) $tt->put( 'test_'.$i, $i );
$timer->setMarker('TOKYO CABINET - INSERT 10,000 RECOREDS');
for ( $i = 0; $i < 10000; $i++) $tt->get( 'test_'.$i );
$timer->setMarker('TOKYO CABINET - SELECT 10,000 RECOREDS');
for ( $i = 0; $i < 10000; $i++) $tt->put( 'test_'.$i, $i );
$timer->setMarker('TOKYO CABINET - UPDATE 10,000 RECOREDS');
for ( $i = 0; $i < 10000; $i++) $tt->out( 'test_'.$i );
$timer->setMarker('TOKYO CABINET - DELETE 10,000 RECOREDS');
$timer->stop();
$timer->display();
$tt->close();
?>

执行脚本得到的结果如下图


下面对memcache进行测试,为测试方便在同一台机器上执行一下脚步
memcached -d -m 256 -l 127.0.0.1 -p 11211 -u root
以root用户对memcahe分配256M的内存,分配的端口号为11211
下面再写一个脚本分别对memcahe进行一万次插入,一万次查询,一万次更新
一万次删除操作,脚本内容如下:

include_once( 'Benchmark/Timer.php' );
$timer = new Benchmark_Timer();
$memcache = new Memcache;
$memcache->connect('localhost', 11211);
$timer->start();
for ( $i = 0; $i <10000; $i++ ) $memcache->set( 'test_'.$i, $i );
$timer->setMarker('MEMCACHE - INSERT 10,000 RECOREDS');
for ( $i = 0; $i <10000; $i++ ) $memcache->get( 'test_'.$i );
$timer->setMarker('MEMCACHE - SELECT 10,000 RECOREDS');
for ( $i = 0; $i <10000; $i++ ) $memcache->replace( 'test_'.$i, $i );
$timer->setMarker('MEMCACHE - UPDATE 10,000 RECOREDS');
for ( $i = 0; $i <10000; $i++ ) $memcache->delete( 'test_'.$i );
$timer->setMarker('MEMCACHE - DELETE 10,000 RECOREDS');
$timer->stop();
$timer->display();
$memcache->close();

?>

执行的结果如下:


从上面测试的结果来看,tokyo cabinet的速度非常快,比memcahe稍差。
在执行1万次操作所花费的时间在1.2s左右,而memcahe所花的时间比tokyo cabinet快了0.2秒,但是memcache down掉后数据全部丢失,而tokyo cabinet即使重启了,db文件不坏掉,数据就不会丢失。

PHP操作tokyo Cabinet

Posted:
上篇我介绍了tokyo Cabinet,这篇我介绍通过php操作tokyo cabinet。需要的工具有php扩展模块Net_Tokyo_Tyrant,Tokyo Tyrant。

首先安装Tokyo Cabinet,安装方法

curl -O http://tokyocabinet.sourceforge.net/tokyocabinet-1.4.16.tar.gz
./configure
make
make install

安装tokyotyrant

curl -O http://tokyocabinet.sourceforge.net/tyrantpkg/tokyotyrant-1.1.23.tar.gz
./configure
make
make install


为php添加Net_Tokyo_Tyrant模块

/usr/local/php/bin/pear channel-discover openpear.org
/usr/local/php/bin/pear install openpear/Net_TokyoTyrant-beta

现为beta版,当有正式版请使用

/usr/local/php/bin/pear install openpear/Net_TokyoTyrant


启动服务

/usr/local/sbin/ttservctl start

说明:启动后的监听的端口为1978

编写php文件

include_once 'Net/TokyoTyrant.php';
$tt = new Net_TokyoTyrant();
$tt->connect( 'localhost', 1978 );
$tt->put('test', 'PHP connet to Tokyo cabinet');
echo $tt->get('test');

$tt->close();
?>

执行刚刚的php文件,你将看到如下的文字
PHP connet to Tokyo cabinet
以上就完成第一个php对Tokyo cabinet的操作
当在memcache中保存数据时,重启memcache服务,所有的数据全部丢失
当在tokyo cabinet中保存数据时,服务器重启数据不丢失。
下面通过一个例子证明这点
/usr/local/sbin/ttservctl restart
编写php文件

include_once 'Net/TokyoTyrant.php';
$tt = new Net_TokyoTyrant();
$tt->connect( 'localhost', 1978 );
//$tt->put('test', 'PHP connet to Tokyo cabinet');
echo $tt->get('test');

$tt->close();
?>

执行php脚本,得到的结果还是
PHP connet to Tokyo cabinet
说明它的数据全部保存在磁盘上而不是内存中。
下期将推出,比较memcache与tokyo cabinet的执行效率

Tokyo Cabinet介绍

Posted: 2009年4月20日星期一
Tokyo Cabinet是由一个名叫平林幹雄的日本人开发的一个管理数据库程序库,作者开发了一系列的开源程序。包括:
Tokyo Cabinet
tokyotyrant
QDBM(Quick Database Manager),
Hyper Estraier(a full-text search system for communities),
Estraier(a personal full-text search system)
Diqt:Multilingual Dictionary Searcher等。
现工作于日本的第一大社交网站mixi。
Tokyo Cabinet是一个DBM数据库,在整个数据库中它既没有数据表的概念也没有数据类型的概念,它由一系列的key-value对的记录构成,key和vlaue既可以是二进制数据也可以为字符数据,它们的长度可以是任意长度的字节序列,所有的记录都保存在文件中。所有记录由hash表,b+树或定长的数组组成。
Tokyo Cabinet基于GNU Lesser General Public License协议发布,采用C语言开发,它可以运行在任何支持C99和POSIX平台上使用。
相比一般的DBM数据库有以下几个特点:空间小,效率高,性能高,可靠性高,多种开发语言的支持(现已提供C,Perl,Ruby,Java,Lua的API),支持64位操作系统。
它的官方首页是:http://tokyocabinet.sourceforge.net/index.html
最新版本:tokyocabinet-1.4.14

稍后我将推出他在mixi开发者blog上发表一系列有关于tokyocabinet的文档

Linux硬盘读写能力的测试

Posted: 2009年4月19日星期日
今天对公司的几种类型的服务器分别做了,硬盘读写能力的测试。
测试的机器分别是:

测试的环境:Centos 5.2 x86_64 ,文件系统Ext3。
测试的过程:
先测试
通过以下两个脚本分别对服务器进行10次操作
读测试:

for i in 1 2 3 4 5 6 7 8 9 10;
do
sleep 10;
echo $'\n' $i;
hdparm -tT /dev/sda;
done

得出的结果如下图(单位:MB/sec)



看不清楚,请点击,查看大图
写测试

for i in 1 2 3 4 5 6 7 8 9 10;
do
sleep 10;
echo $'\n' $i;
dd if=/dev/zero of=/tmp/hdparm_write$i.tmp ibs=1M obs=1M count=1024;
done

说明:
对几个参数进行说明
sleep 10;间隔10S,
ibs=1M 一次读入1M
obs=1M 一次写入1M,
共1024个1M文件,也就是1G
测试的结果如下图(单位:MB/sec

开贴了

Posted: 2009年4月18日星期六
申请了这个博客很久了,一直没有好好利用它,原本打算自己买台主机空间搭建一个blog,发现在国内架个blog还得申请icp认证,真麻烦。没有办法,还是好好利用免费的博客空间。从网上下个模版,稍微修改一下,就搭建了一个blog平台。今天开始发表自己的文章到blog,尽量做到不转贴,希望得到大家的支持,多多交流。