systemctl start vsftpd
scp ks7.cfg 192.168.1.5:/var/ftp/
yum -y install dhcp
vim /etc/dhcp/dhcpd.conf
subnet 192.168.1.0 netmask 255.255.255.0 {
range 192.168.1.10 192.168.1.200;
next-server 192.168.1.20;
option routers 192.168.1.254;
filename "pxelinux.0";}
dhclient -d eth0
yum -y install tftp-server
yum -y install syslinux-tftpboot.x86_64
/var/lib/tftpboot
mkdir pxelinux.cfg
rpm -ql syslinux | grep pxelinux.0
cp /usr/share/syslinux/pxelinux.0 /var/lib/tftpboot/
mkdir /var/lib/tftpboot/rhel7
lftp 192.168.1.254:/ansible/images/pxeboot>
get vmlinuz initrd.img isolinux.cfg
yum -y install tftp
systemctl start dhcpd
96 ss -ltun
97 systemctl start tftp
system-config-kickstart
tftp 192.168.1.5 -c get pxelinux.0
/var/www/html
ss -anputl | grep dns
477 killall dnsmasq
default vesamenu.c32
timeout 600
label linux
menu label ^Install CentOS 7
kernel vmlinuz
append initrd=initrd.img ks=ftp://192.168.1.19/ks7.cfg console=ttyS0,115200n8
实验目的:搭建一个高可用,高并发的SNS类网站
虚拟机讲解,演示,一台企业中真实的服务器是什么样子的。
kickstart 文件解说,配置 PXE 网络装机环境 (kickstart 文件见附件 conf/ks7.ks)
学生需要使用该配置文件安装虚拟机
pxe 配置
dhcpd 配置详情见附件 (dhcpd/dhcpd.conf,subnet-192.168)
vsftp 配置详情见附件 (vsftpd.conf)
tftpboot 配置详情见附件 (tftpboot/pxelinux.cfg/default,centos_menu)
简易配置软件 dnsmasq.conf 简介
实验一:
修改 ks7.ks 配置文件,配置自己的 pxe 环境,配置 yum 源,安装 guest 操作系统
学生实验在 KVM 中完成
virt-install 安装 guest os
virt-install \
--connect qemu:///system --virt-type kvm \
--name demo --memory 2048 --cpu host --vcpus 2 --os-variant centos7.0 \
--network bridge=vbr0 \
--disk path=/var/lib/libvirt/images/demo.qcow2,bus=scsi \
--boot menu=on,useserial=on --nographics --pxe
virsh xml 配置文件定义,bridge 配置
配置文件详见 demo.xml
克隆虚拟机
qemu-img create -b background.qcow2 -f qcow2 node.img
sed 's,demo,node,' demo.xml >node.xml
virsh -c qemu:///system define node.xml
virsh -c qemu:///system start --console node
实验二:
以新安装的系统为模板,安装 Linux + Nginx + mysql + php (fastcgi)
Nginx 安装编译参数(rpm 详见 spec 文件)
添加 web 用户和组
groupadd -g 1000 web
useradd -u 1000 -g 1000 web -s /sbin/nologin
添加编译依赖库
yum install openssl-devel pcre-devel readhline-devel zlib-devel
./configure --prefix=/usr/local/nginx \ # 安装路径
--with-http_ssl_module \ # 开启 ssl 模块 支持https
--with-http_v2_module \ # 支持 http_v2 协议
--with-http_realip_module \ # 获取客户端真实 ip
--with-http_stub_status_module \ # 查看服务器工作状态
--without-mail_pop3_module \ # 禁用 pop3 模块
--without-mail_imap_module \ # 禁用 imap 模块
--without-mail_smtp_module \ # 禁用 smtp 模块
--with-pcre # 开启 pcre 正则表达式支持
配置文件 nginx.conf
user web web;
worker_processes auto;
worker_rlimit_nofile 16384;
events {
use epoll;
worker_connections 8192;
}
pid /var/run/nginx.pid;
php 安装编译参数(rpm 详见 spec 文件)
./configure --prefix=/usr/local/php --with-config-file-path=/etc \ # 安装及配置文件路径
--with-fpm-user=web --with-fpm-group=web \ # 用户和组设置
--enable-fd-setsize=65535 --disable-ipv6 \ # 禁用 ipv6,和设置 openfile
--without-sqlite3 --without-pdo-sqlite \ # 禁用 sqlite
--enable-fpm \ # 打开 fpm 模式支持
--enable-sockets --enable-sysvsem --enable-sysvshm --enable-sysvmsg --enable-shmop --enable-mbstring --enable-zip --enable-bcmath --enable-ftp --enable-soap --with-mhash --with-pcre-regex --with-pcre-dir --with-readline --with-zlib --with-curl --with-openssl --with-iconv --with-gd --with-png-dir --with-jpeg-dir --with-freetype-dir --with-xpm-dir \ # php功能特性
--enable-mysqlnd --with-mysqli=mysqlnd --with-pdo-mysql=mysqlnd # 打开 mysql 支持
php-fpm 配置文件
[global]
pid = /var/run/php-fpm.pid
error_log = /var/log/weblog/php-fpm.log
log_level = warning
emergency_restart_threshold = 10
emergency_restart_interval = 1d
process.max = 2048
daemonize = yes
rlimit_files = 65535
user = web
group = web
listen = /var/run/php-fpm.sock
listen.backlog = 1024
listen.owner = web
listen.group = web
listen.mode = 0660
pm = ondemand
pm.max_children = 2048
pm.process_idle_timeout = 60s;
pm.max_requests = 2048
request_terminate_timeout = 180
nginx fastcgi 配置
location ~ ^/(.+\.php)$ {
fastcgi_pass unix:/var/run/php-fpm.sock;
fastcgi_index index.php;
include fastcgi.conf;
}
验证配置 info.php
<?PHP
phpinfo();
?>
#platform=x86, AMD64, or Intel EM64T
#version=DEVEL
# Install OS instead of upgrade
install
# Keyboard layouts
keyboard 'us'
# Root password
rootpw --iscrypted lxqk4My6q5YyQ
# System timezone
timezone Asia/Shanghai
# Use network installation
url --url="ftp://192.168.1.254/centos7"
# System language
lang en_US.UTF-8
# Firewall configuration
firewall --disabled
# System authorization information
auth --useshadow --passalgo=sha512
# Use text mode install
text
# Installation logging level
logging --level=warning
# Run the Setup Agent on first boot
firstboot --disable
# SELinux configuration
selinux --disabled
# Do not configure the X Window System
skipx
# Network information
network --device=bootif --onboot=on --hostname=localhost --bootproto=bootp --noipv6
# Reboot after installation
reboot
# System bootloader configuration
bootloader --location=mbr
# Clear the Master Boot Record
zerombr
# Partition clearing information
clearpart --all --initlabel
# Disk partitioning information
part /boot --asprimary --fstype=xfs --size=512
part / --asprimary --fstype=xfs --size=1 --grow
%packages --nobase
@Core --nodefaults
-iwl3160-firmware
-iwl6000g2b-firmware
-iwl2030-firmware
-iwl7265-firmware
-iwl1000-firmware
-iwl4965-firmware
-iwl2000-firmware
-iwl3945-firmware
-alsa-tools-firmware
-aic94xx-firmware
-iwl135-firmware
-iwl7260-firmware
-iwl6050-firmware
-iwl6000g2a-firmware
-iwl5000-firmware
-ivtv-firmware
-iwl100-firmware
-iwl5150-firmware
-iwl105-firmware
-iwl6000-firmware
-alsa-firmware
-postfix
-audit
-tuned
chrony
psmisc
net-tools
screen
vim-enhanced
tcpdump
lrzsz
ltrace
strace
traceroute
whois
bind-utils
tree
mlocate
rsync
lsof
lftp
patch
diffutils
cpio
time
nmap
socat
man-pages
rpm-build
createrepo
%end
%pre
%end
%post --interpreter=/bin/bash
rm -f /etc/yum.repos.d/*.repo
cat >/etc/yum.repos.d/local.repo <<'EOF'
[local_repo]
name=CentOS-$releasever - Base
baseurl=ftp://192.168.1.254/centos7
enabled=1
gpgcheck=1
EOF
rpm -import ftp://192.168.1.254/centos7/RPM-GPG-KEY-CentOS-7
yum erase -y NetworkManager NetworkManager-libnm kexec-tools firewalld-filesystem polkit
sed 's,^CRONDARGS=.*,&"-m off",' -i /etc/sysconfig/crond
sed 's,^\(OPTIONS=\).*,\1"-4",' -i /etc/sysconfig/chronyd
sed 's,^server .*,&\ncmdallow 127.0.0.1,' -i /etc/chrony.conf
sed 's,^#\(terminfo xterm \x27is.*\),\1\nterm xterm,' -i /etc/screenrc
cat >>/etc/sysconfig/network <<'EOF'
IPV6INIT="no"
NETWORKING="yes"
NOZEROCONF="yes"
EOF
echo -e "# ::1\t\tlocalhost localhost.localdomain localhost6 localhost6.localdomain6" >/etc/hosts
echo -e "127.0.0.1\tlocalhost localhost.localdomain localhost4 localhost4.localdomain4" >>/etc/hosts
echo -e 'export TZ='Asia/Shanghai' PYTHONSTARTUP="/usr/lib64/python2.7/pystartup.py" TMOUT=7200' >/etc/profile.d/environ.sh
echo -e "blacklist acpi_pad\nblacklist power_meter" >/etc/modprobe.d/blacklist.conf
cat >/usr/lib64/python2.7/pystartup.py <<'EOF'
#!/usr/bin/python
# -*- coding:utf_8 -*-
#from __future__ import print_function
from rlcompleter import readline
readline.parse_and_bind("tab: Complete")
EOF
cat >/etc/sysctl.d/70-system.conf <<'EOF'
net.ipv4.ip_forward = 1
net.ipv4.ip_default_ttl = 255
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 0
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2
kernel.sysrq = 16
vm.swappiness = 0
EOF
# config vimrc
cat >>/etc/vimrc<<'EOF'
set wrapscan
set noautoindent
set showmatch
set binary
set noswapfile
set ignorecase " Do case insensitive matching
set foldmethod=syntax
set foldlevel=100
filetype plugin off
EOF
sed -e 's,^#\(Port\).*,\1 10022,' \
-e 's,^#\(ListenAddress 0.0.0.0\),\1,' \
-e 's,^#\(PermitRootLogin\).*,\1 yes,' \
-e 's,^#\(MaxAuthTries\).*,\1 3,' \
-e 's,^#\(UseDNS\).*,\1 no,' -i /etc/ssh/sshd_config
cat >/etc/sysconfig/network-scripts/ifcfg-eth0 <<'EOF'
# Generated by dracut initrd
DEVICE="eth0"
ONBOOT="yes"
IPV6INIT="no"
IPV4_FAILURE_FATAL="no"
NM_CONTROLLED="no"
TYPE="Ethernet"
BOOTPROTO="dhcp"
EOF
%end
subnet 192.168.1.0 netmask 255.255.255.0 {
option routers 192.168.1.254;
option subnet-mask 255.255.255.0;
option domain-name-servers 192.168.1.254;
option ntp-servers 192.168.1.254;
filename "/gpxelinux.0";
next-server 192.168.1.254;
pool {
range dynamic-bootp 192.168.1.10 192.168.1.240;
default-lease-time 3600;
max-lease-time 72000;
allow unknown-clients;
}
}
#
# DHCP Server Configuration file.
# see /usr/share/doc/dhcp*/dhcpd.conf.example
# see dhcpd.conf(5) man page
#
ddns-update-style none;
ignore client-updates;
default-lease-time 14400;
max-lease-time 86400;
allow bootp;
allow booting;
local-address 192.168.1.254;
local-port 67;
include "/etc/dhcp/subnet-192.168";
/usr/local/nginx/conf/nginx.conf
include fastcgi.conf;
/usr/local/nginx/sbin/nginx
/usr/local/php/etc/php-fpm.d/www.conf
listen = 127.0.0.1:9000
systemctl start php-fpm.service
http://192.168.1.17/info.php
apachectl -t
systemctl start httpd
vim /etc/httpd/conf/httpd.conf
/var/www/html/info.php
apachectl start
详细步骤,恢复步骤
1,备份xtrabackkup
2.新的服务器上做slave,不设置read-only
业务低谷时期观察直接服务器上更新远程服务器
再停止mysql服务
修改配置文件
[root@apache html]# cat /etc/resolv.conf
# Generated by NetworkManager
nameserver 172.40.1.10
今天主要实验内容为压力测试与架构分离调整
常用的优化手段有
动静分离
读写分离
管理分离
nginx 增加状态监测
location /nginx-status {
allow 192.168.0.0/16;
deny all;
stub_status on;
access_log off;
}
php-fpm 增加状态监测
php-fpm.d/www.conf
pm.status_path = /php_status
nginx.conf
location ~ ^/(.+\.php|php_status)$ {
fastcgi_pass unix:/var/run/php-fpm.sock
fastcgi_index index.php;
include fastcgi.conf;
}
apache bench 安装与使用
apache 自带的压力测试工具,简单易用,大并发的时候需要自己查询错误结果
yum install httpd-tools
ab [option] http://url
支持 get post 自定义头等
-c 并发数量
-n 请求总数
-H 自定义请求头
-p post 文件
web bench 安装与使用
Webbench是一个在linux下使用的非常简单的网站压测工具。它使用fork()模拟多个客户端同时访问我们设定的URL,测试网站在压力下工作的性能,最多可以模拟3万个并发连接去测试网站的负载能力
安装依赖包:yum install ctags
make
使用
./webbench -r -t 60 -c 200 -2 http://url
-r 发送刷新缓存要求
-t 测试时间
-c 并发数量
-2 使用 http1.1,长连接
-h 帮助信息
wrk 压力测试软件
优势是支持线程,能更好的发挥多核的优势
安装也很简单,直接 make 即可
-c 表示的是并发
-d 测试持续的时间
-t 来控制线程数(缺省值为 2)
/wrk -c 200 -d 10 -t 5 http://url
php质数计算例子
<?php
$n = 0;
$start = 1;
$end = 50000;
for($num = $start; $num <= $end; $num++) {
if ( $num == 1 ) continue;
for ($i = 2; $i <= sqrt($num); $i++) {
if ($num % $i == 0) continue 2;
}
$n++;
}
print_R($n."\n");
?>
netstat 与 ss
tcp状态统计
ss -ant|awk '{A[$1]++}END{for(a in A)print A[a],a}'
数据库创建 库,表
php 查询数据库压力测试
导入 mydb.sql
压测 testmysql.php
静态页面压力测试
t.html
常用执行使用简介:
查看一个程序执行的时间,总时间,内核态时间,用户态时间
time cmd
查看内存使用情况
free
查看系统进程情况
top & ps
%CPU 上次更新到现在的CPU时间占用百分比
%MEM 程序执行占用内存百分比
virt 是虚拟内存
res 是常驻内存
shr 是共享内存
进程状态 R S D T Z X
R 可执行状态
S 可中断的睡眠状态
D 不可中断状态(怨妇)
T 暂停或跟踪
t 跟踪调试状态
Z 退出态,没有销毁(僵尸,可使用 signal SIGCONT 找其 PPID 超度)
X 退出态,被销毁
内存使用统计
ps -eo cmd,%cpu|awk '{A[$1]+=$NF}END{for(a in A)if(A[a])print a,A[a]|"column -t"}'
tcp 连接状态统计
ss -ant|awk '{A[$1]++}END{for(a in A)print a,A[a]}'
tcp的三次握手四次断开与状态
1. 客户端独有的:(1)SYN_SENT (2)FIN_WAIT1 (3)FIN_WAIT2 (4)CLOSING (5)TIME_WAIT
2. 服务器独有的:(1)LISTEN (2)SYN_RCVD (3)CLOSE_WAIT (4)LAST_ACK
3. 共有的: (1)CLOSED (2)ESTABLISHED
LISTEN - 侦听来自远方TCP端口的连接请求;
SYN-SENT - 在发送连接请求后等待匹配的连接请求;
SYN-RECEIVED - 在收到和发送一个连接请求后等待对连接请求的确认;
ESTABLISHED - 代表一个打开的连接,数据可以传送给用户;
FIN-WAIT-1 - 等待远程TCP的连接中断请求,或先前的连接中断请求的确认;
FIN-WAIT-2 - 从远程TCP等待连接中断请求;
CLOSE-WAIT - 等待从本地用户发来的连接中断请求;
LAST-ACK - 等待原来发向远程TCP的连接中断请求的确认;
TIME-WAIT - 等待足够的时间以确保远程TCP接收到连接中断请求的确认;
CLOSED - 没有任何连接状态;
CLOSING - 同时发起关闭状态,从 FIN-WAIT-1 --> CLOSING --> TIME-WAIT
iostat 监控磁盘IO状态
yum install sysstat
iptraf 软件包简单使用
mysql 安装到其他主机,在进行压力测试对比
主1.15从1.14 1.13
昨天已经分离了 mysql,今天首先搭建 mysql 主从集群
yum -y install perl-JSON
yum -y install mysql-community-*.rpm
systemctl start mysqld
systemctl enable mysqld
grep password /var/log/mysqld.log
mysql -hlocalhost -uroot -p
vim /etc/my.cnf
systemctl restart mysqld
server_id=2
validate_password_policy=0
validate_password_length=6
log-bin=master2
binlog-format="mixed"
set global validate_password_policy=0;
set global validate_password_length=6;
alter user root@"localhost" identified by"123456";
change master to
master_host="192.168.1.15",
master_user="yaya",
master_password="123456",
master_log_file="master1.000001",
master_log_pos=437;
start slave;
show slave status\G;
安装 mariadb
yum install mariadb mariadb-server
配置 my.cnf,添加参数
bind-address = 0.0.0.0
symbolic-links = 0
server-id = 10
log_bin = mysql-bin
binlog-format = statement
relay-log = relay-log
read_only = 1
relay_log_purge = 0
innodb_file_per_table
修改 server-id 参数,后启动数据库
id=$(ip -o a s dev eth0|grep -Po "(?<=inet 192.168.4.)\d+")
sed "s,^\(server-id\t= \).*,\1${id}," -i /etc/my.cnf
启动服务
systemctl start mariadb
添加用户,开启主从同步
m01:
reset master;
create user 'repl'@'%' IDENTIFIED BY 'lper';
grant replication client,replication slave on *.* to repl@'%';
node{1..3}
reset slave;
change master to master_host='192.168.4.10',master_user='repl',master_password='lper';
start slave;
# 在 master 上配置 root 登录权限及密码
drop database test;
use mysql;
truncate db;
delete from user where User="";
delete from user where User="root" limit 2;
update user set Host="::1" where User="root" and Host="%";
update user set Host="127.0.0.1" where User="root" and Host="localhost";
update user set password=password('toor') where User="root";
flush privileges;
# 至此,mysql 主从已经创建完成
创建库、表及测试数据
读写分离
实现读写分离方式:
1、程序代码兼容,对除 select 以外的操作在 master 上执行,select 在 slave 上执行
2、中间件读写分离,对应用端透明
mycat 读写分离和分布式架构中间件,Mycat 使用 java 开发,由于使用了JDK7的一些特性,所以必须 JDK7 或更高版本.
安装依赖包
yum install java-1.8.0-openjdk
配置一个用户用来读,一个用户用来执行写操作
create user 'read_user'@'%' IDENTIFIED BY 'user_read';
grant select on *.* to 'read_user'@'%';
找一台机器安装 mycat 中间件,不建议复用
mycat 解压拷贝到 /usr/local/ 下
修改配置文件 schema.xml
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1">
</schema>
<dataNode name="dn1" dataHost="localhost1" database="mydb" />
<dataHost name="localhost1" maxCon="1000" minCon="10" balance="3"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<!-- can have multi write hosts -->
<writeHost host="m01" url="192.168.4.10:3306" user="root" password="toor">
<!-- can have multi read hosts -->
<readHost host="node1" url="192.168.4.11:3306" user="read_user" password="user_read" />
<readHost host="node2" url="192.168.4.12:3306" user="read_user" password="user_read" />
<readHost host="node3" url="192.168.4.13:3306" user="read_user" password="user_read" />
</writeHost>
</dataHost>
</mycat:schema>
配置文件注意事项:
conf/server.xml 可以不修改,但要注意
<property name="schemas">TESTDB</property>
虚拟库名称,要和后面对应
schemas是这个用户下的逻辑数据库可以有多个逻辑数据库可以用“,”逗号隔开
用户名和密码是连接 mycat 的用户名和密码,与 mysql 实例的用户名密码无关
mycat默认的普通连接端口是8066,管理连接端口是9066
schema:逻辑数据库
dataNode:节点
dataHost:节点对应的读库写库的地址和连接
balance指的负载均衡类型,目前的取值有4种:
balance="0", 不开启读写分离机制,所有读操作都发送到当前可用的writeHost上。
balance="1",全部的readHost与stand by writeHost参与select语句的负载均衡
balance="2",所有读操作都随机的在writeHost、readhost上分发。
balance="3",所有读请求随机的分发到wiriterHost对应的readhost执行,writerHost不负担读压力
switchType指的是切换的模式,目前的取值也有4种:
switchType='-1' 表示不自动切换
switchType='1' 默认值,表示自动切换
switchType='2' 基于MySQL主从同步的状态决定是否切换,心跳语句为 show slave status
switchType='3' 基于MySQL galary cluster的切换机制(适合集群)(1.4.1),心跳语句为 show status like 'wsrep%'
WriteType参数设置:
writeType=“0”, 所有写操作都发送到可用的writeHost上。
writeType=“1”,所有写操作都随机的发送到readHost。
writeType=“2”,所有写操作都随机的在writeHost、readhost分上发。
配置完成以后连接 mycat 查询
mysql -uroot -p123456 -h192.168.4.20 -P 8066 -e 'select @@hostname;'
多查询几次,可以看到轮询效果
读写分离了,mycat 单点故障, mysql master 单点故障怎么解决 ?
官方推荐高可用方案
+-------------+ +-----------+ +--------------------------+
| keepalived | | +-----+ | | +--------+ +--------+ |
|------------ | | |mycat| | ==> | |mysql(M)|<==>|mysql(M)| |
| +-------+ | | +-----+ | | +--------+ +--------+ |
| |haproxy|=>| ==> | | | MHA或其他多主高可用方案 |
| +-------+ | | +-----+ | |-~-~-~-~-~-~~~~-~-~-~-~-~-|
client --> vip | |高| | | |mycat| | ==> | +--------+ +--------+ |
| |可| | | +-----+ | | |mysql(S)| 从 |mysql(S)| |
| |用| | | | | +--------+ 库 +--------+ |
| +-------+ | | +-----+ | | +--------+ 集 +--------+ |
| |haproxy|=>| ==> | |mycat| | ==> | |mysql(S)| 群 |mysql(S)| |
| +-------+ | | +-----+ | | +--------+ +--------+ |
+-------------+ +-----------+ +--------------------------+
# 安装 haproxy 和 keepalived
yum install haproxy keepalived
haproxy 配置
listen mysql_3306 *:3308
mode tcp
option tcpka
balance leastconn
server mycat_01 192.168.4.15:8066 check inter 3000 rise 1 maxconn 1000 fall 3
server mycat_02 192.168.4.20:8066 check inter 3000 rise 1 maxconn 1000 fall 3
keepalived 配置,vip 配置
global_defs {
router_id mycat
}
vrrp_instance Mycat {
state BACKUP
interface eth0
track_interface {
eth0
}
virtual_router_id 150
priority 200
nopreempt
advert_int 5
authentication {
auth_type PASS
auth_pass test_mycat
}
virtual_ipaddress {
192.168.4.150/24 brd 192.168.4.255 dev eth0 label eth0:1
}
}
NFS 搭建
nfs 用来解决数据共享问题,配置文件 exports
/var/webroot 192.168.1.0/24(rw,all_squash,anonuid=1000,anongid=1000,async)
客户机添加配置文件 fstab
192.168.1.16:/var/webroot /var/webroot nfs defaults,proto=tcp,nosuid,noexec,nodev,noatime,nodiratime,intr,rsize=65536,wsize=65536 0 0
php session 共享 (redis)
1、redis 数据库安装
adduser -s /sbin/nologin -d /var/lib/redis redis
make MALLOC=libc
make PREFIX=/usr/local/redis install
mkdir -p /usr/local/redis/conf
cp redis.conf /usr/local/redis/conf/
修改配置文件
bind 192.168.1.18
port 6379
dir /var/lib/redis
启动脚本 redis.service
[Unit]
Description=Redis In-Memory Data Store
After=network.target
[Service]
User=redis
Group=redis
Type=simple
ExecStart=/usr/local/redis/bin/redis-server /usr/local/redis/conf/redis.conf
ExecStop=/usr/local/redis/bin/redis-cli shutdown
Restart=always
RestartSec=42s
[Install]
WantedBy=multi-user.target
2、安装 php redis 扩展
cd phpredis
git checkout 3.1.6
./configure --enable-redis --with-php-config=/usr/local/php/bin/php-config
make
cp .libs/redis.so /usr/local/php/lib/php/extensions/
编辑 php.ini 加载配置
extension_dir = "/usr/local/php/lib/php/extensions"
extension=redis
验证配置
php -m |grep redis
3、添加配置,让 php session 使用 redis
修改 session.save_handler = files 为 session.save_handler = redis
修改 ;session.save_path = "/tmp" 为 session.save_path = "tcp://192.168.1.18:6379"
使用 php 脚本测试
<?PHP
echo "<pre>";
session_id('test-redis-session');
session_start();
if(isset($_GET["d"])) {
foreach($_SESSION as $sid => $value){
unset($_SESSION[$sid]);
}
session_destroy();
}
if(isset($_GET["w"])) {
$_SESSION['a']=1;
$_SESSION['b']=2;
$_SESSION['c']=3;
}
print_R(session_id().":\n");
print_R($_SESSION);
echo "</pre>"."\n";
?>
redis 服务器高可用
redis集群实现大概有以下几种方式:
1.redis-cluster, 官方提供的集群搭建方案(过于重量级,比较适合后期数据量较大的时候的使用)
2.redis+keepalive 虚拟IP,多台配置非常复杂,不宜维护,需要 slaveof no one 脚本
3.redis+zookeeper 需要引入zookeeper,对现有代码变动较大
4.redis+sentinel redis自带监控中间件
1、配置三台 redis 服务器
配置主从关系,在 slave 上添加配置
slaveof 192.168.1.18 6379
添加哨兵监控 sentinel.conf
修改配置文件 sentinel.conf
bind 0.0.0.0
port 26379
protected-mode no
daemonize yes
sentinel monitor mymaster 192.168.1.18 6379 2
分别在主,从上启动 sentinel
bin/redis-sentinel conf/sentinel.conf
连接 26379 校验配置
查看 master 信息
redis-cli -h 192.168.1.18 -p 26379
INFO sentinel
也可以写成系统服务
[Unit]
Description=Redis Monitor
After=redis.service
[Service]
Type=forking
ExecStart=/usr/local/redis/bin/redis-sentinel /usr/local/redis/conf/sentinel.conf
ExecStop=/usr/local/redis/bin/redis-cli -p 26379 shutdown
Restart=always
RestartSec=42s
[Install]
WantedBy=multi-user.target
客户端兼容问题
客户端程序(如PHP程序)连接redis时需要ip和port,但redis-server进行故障转移时,主是变化的,所以ip地址也是变化的
客户端程序如何感知当前主redis的ip地址和端口呢?
redis-sentinel提供了接口,请求任何一个sentinel,发送SENTINEL get-master-addr-by-name <master name>就能得到当前主redis的ip和port。
解决方案1:
程序兼容,优势:扩展性好,运维成本低
劣势:开发成本高,连接变成 2 次
解决方案2:
vip 漂移,优势:程序端无感知,架构不需要改变
劣势:集群庞大时配置管理复杂,运维成本高
方案2:
增加配置切换脚本 sentinel.conf
sentinel client-reconfig-script mymaster /usr/local/redis/conf/reconfig.sh
reconfig.sh
#!/bin/bash
# args=(<master-name> <role> <state> <from-ip> <from-port> <to-ip> <to-port>)
# mymaster leader start old.ip old.port new.ip new.port
logger -p local0.info -t redis "${@:-NULL}"
vip="192.168.1.100/32"
read oldip newip <<<"$4 $6"
if $(ip -o a s |grep -q ${oldip:-0.0.0.0});then
/sbin/ifconfig eth0:1 down &>/dev/null
elif $(ip -o a s|grep -q ${newip:-0.0.0.0});then
/sbin/ifconfig eth0:1 ${vip}
/sbin/arping -q -c 3 -A ${vip%/*} -I eth0
fi