Redis集群介绍:
Redis 集群是一个提供在多个Redis间节点间共享数据的程序集。Redis集群并不支持处理多个keys的命令,因为这需要
在不同的节点间移动数据,从而达不到像Redis那样的性能,在高负载的情况下可能会导致不可预料的错误.
Redis 集群通过分区来提供一定程度的可用性,在实际环境中当某个节点宕机或者不可达的情况下继续处理命令.
Redis 集群的优势:
自动分割数据到不同的节点上。
整个集群的部分节点失败或者不可达的情况下能够继续处理命令。
Redis 集群的主从复制模型:
为了使在部分节点失败或者大部分节点无法通信的情况下集群仍然可用,所以集群使用了主从复制模型,每个节点都会有N-1
个复制品. 在我们例子中具有A,B,C三个节点的集群,在没有复制模型的情况下,如果节点B失败了,那么整个集群就会以为
缺少5501-11000这个范围的槽而不可用.然而如果在集群创建的时候(或者过一段时间)我们为每个节点添加一个从节点A1,
B1,C1,那么整个集群便有三个master节点和三个slave节点组成,这样在节点B失败后,集群便会选B1为新的主节点继续
服务,整个集群便不会因为槽找不到而不可用了,不过当B和B1 都失败后,集群是不可用的.
搭建集群环境使用7001到7006搭建六个集群节点:
[root@server1 ~]# ls 使用tar zxf redis-4.0.8.tar.gz解压即可
redis-4.0.8 redis-4.0.8.tar.gz
[root@server1 ~]# cd /usr/local/
[root@server1 local]# ls
bin etc games include lib lib64 libexec sbin share src
[root@server1 local]# mkdir cluster
[root@server1 local]# cd cluster/
[root@server1 cluster]# ls
[root@server1 cluster]# mkdir 7001
[root@server1 cluster]# mkdir 7002
[root@server1 cluster]# mkdir 7003
[root@server1 cluster]# mkdir 7004
[root@server1 cluster]# mkdir 7005
[root@server1 cluster]# mkdir 7006
[root@server1 cluster]# cd
[root@server1 ~]# cd redis-4.0.8
[root@server1 redis-4.0.8]# cd src/
[root@server1 src]# cp redis-trib.rb /usr/local/bin/
[root@server1 src]# cd /usr/local/bin/
[root@server1 bin]# ls
master_ip_failover redis-check-aof redis-sentinel
master_ip_online_change redis-check-rdb redis-server
redis-benchmark redis-cli redis-trib.rb
[root@server1 bin]# cd
[root@server1 ~]# yum install -y ruby
[root@server1 ~]# ls
redis-4.0.1.gem redis-4.0.8.tar.gz
redis-4.0.8 rubygems-1.3.7-5.el6.noarch.rpm
[root@server1 ~]# yum install rubygems-1.3.7-5.el6.noarch.rpm
[root@server1 ~]# redis-trib.rb
/usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require': no such file to load -- redis (LoadError)
from /usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `require'
from /usr/local/bin/redis-trib.rb:25
[root@server1 ~]# ls
redis-4.0.1.gem redis-4.0.8.tar.gz
redis-4.0.8 rubygems-1.3.7-5.el6.noarch.rpm
[root@server1 ~]# rpm -q ruby 版本限制
ruby-1.8.7.352-12.el6_4.x86_64
[root@server1 ~]# ls
redis-4.0.1.gem redis-4.0.8.tar.gz rubygems-1.3.7-5.el6.noarch.rpm
redis-4.0.8 ruby-2.2.3-1.el6.x86_64.rpm
[root@server1 ~]# yum install ruby-2.2.3-1.el6.x86_64.rpm 安装高版本ruby(一种面向对象程序设计的脚本语言)
[root@server1 ~]# ls
libyaml-0.1.3-4.el6_6.x86_64.rpm redis-4.0.8.tar.gz
redis-4.0.1.gem ruby-2.2.3-1.el6.x86_64.rpm
redis-4.0.8 rubygems-1.3.7-5.el6.noarch.rpm
[root@server1 ~]# yum install libyaml-0.1.3-4.el6_6.x86_64.rpm -y
[root@server1 ~]# gem install --local redis-4.0.1.gem
Successfully installed redis-4.0.1
Parsing documentation for redis-4.0.1
Installing ri documentation for redis-4.0.1
Done installing documentation for redis after 1 seconds
1 gem installed
[root@server1 ~]# gem list --local
[root@server1 ~]# ls
libyaml-0.1.3-4.el6_6.x86_64.rpm redis-4.0.8.tar.gz
redis-4.0.1.gem ruby-2.2.3-1.el6.x86_64.rpm
redis-4.0.8 rubygems-1.3.7-5.el6.noarch.rpm
[root@server1 ~]# cd /usr/local/cluster/
[root@server1 cluster]# ls
7001 7002 7003 7004 7005 7006
[root@server1 cluster]# cd 7001/
[root@server1 7001]# ls
redis.conf
[root@server1 7001]# /etc/init.d/redis_6379 stop
Stopping ...
Redis stopped
现在我们已经有了六个正在运行中的 Redis 实例, 接下来我们需要使用这些实例来创建集群
[root@server1 7001]# ls
redis.conf
[root@server1 7001]# vim redis.conf
[root@server1 7001]# cat redis.conf
port 7001
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
daemonize yes
pidfile /usr/local/cluster/7001/redis.pid
logfile /usr/local/cluster/7001/redis.log
[root@server1 7001]# pwd
/usr/local/cluster/7001
[root@server1 7001]# ls
redis.conf
[root@server1 7001]# redis-server redis.conf
[root@server1 7001]# ls
appendonly.aof nodes.conf redis.conf redis.log redis.pid
[root@server1 7001]# cat redis.log 查看reid日志有很多警告
1145:C 12 Aug 10:07:28.842 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
1145:C 12 Aug 10:07:28.842 # Redis version=4.0.8, bits=64, commit=00000000, modified=0, pid=1145, just started
1145:C 12 Aug 10:07:28.843 # Configuration loaded
1146:M 12 Aug 10:07:28.844 * Increased maximum number of open files to 10032 (it was originally set to 1024).
1146:M 12 Aug 10:07:28.845 * No cluster configuration found, I'm b517a81b4ea86301002e9c237d73a1dd42440101
1146:M 12 Aug 10:07:28.877 * Running mode=cluster, port=7001.
1146:M 12 Aug 10:07:28.877 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
1146:M 12 Aug 10:07:28.877 # Server initialized
1146:M 12 Aug 10:07:28.877 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
1146:M 12 Aug 10:07:28.877 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.
1146:M 12 Aug 10:07:28.877 * Ready to accept connections
依次解决日志出现的警告信息:
[root@server1 7001]# echo 511 > /proc/sys/net/core/somaxconn
[root@server1 7001]# sysctl -w vm.overcommit_memory=1
vm.overcommit_memory = 1
[root@server1 7001]# vim /etc/sysctl.conf 写入配置文件永久生效
[root@server1 7001]# cat /etc/sysctl.conf | tail -n 1
vm.overcommit_memory = 1
[root@server1 7001]# echo never > /sys/kernel/mm/transparent_hugepage/enabled
[root@server1 7001]# ls
appendonly.aof nodes.conf redis.conf redis.log redis.pid
[root@server1 7001]# cp redis.conf ../7002
[root@server1 7001]# cp redis.conf ../7003
[root@server1 7001]# cp redis.conf ../7004
[root@server1 7001]# cp redis.conf ../7005
[root@server1 7001]# cp redis.conf ../7006
[root@server1 7001]# cd ..
[root@server1 cluster]# ls
7001 7002 7003 7004 7005 7006
[root@server1 cluster]# cd 7002
[root@server1 7002]# ls
redis.conf
[root@server1 7002]# vim redis.conf
[root@server1 7002]# cat redis.conf
port 7002
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
daemonize yes
pidfile /usr/local/cluster/7002/redis.pid
logfile /usr/local/cluster/7002/redis.log
[root@server1 7002]# redis-server redis.conf
[root@server1 7002]# ls
appendonly.aof nodes.conf redis.conf redis.log redis.pid
[root@server1 7002]# cd ..
[root@server1 cluster]# cd 7003
[root@server1 7003]# ls
redis.conf
[root@server1 7003]# vim redis.conf
[root@server1 7003]# cat redis.conf
port 7003
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
daemonize yes
pidfile /usr/local/cluster/7003/redis.pid
logfile /usr/local/cluster/7003/redis.log
[root@server1 7003]# redis-server redis.conf
[root@server1 7003]# ls
appendonly.aof nodes.conf redis.conf redis.log redis.pid
[root@server1 7003]# cd ..
[root@server1 cluster]# cd 7004
[root@server1 7004]# ls
redis.conf
[root@server1 7004]# vim redis.conf
[root@server1 7004]# cat redis.conf
port 7004
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
daemonize yes
pidfile /usr/local/cluster/7004/redis.pid
logfile /usr/local/cluster/7004/redis.log
[root@server1 7004]# redis-server redis.conf
[root@server1 7004]# ls
appendonly.aof nodes.conf redis.conf redis.log redis.pid
[root@server1 7004]# cd ..
[root@server1 cluster]# cd 7005
[root@server1 7005]# vim redis.conf
[root@server1 7005]# cat redis.conf
port 7005
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
daemonize yes
pidfile /usr/local/cluster/7005/redis.pid
logfile /usr/local/cluster/7005/redis.log
[root@server1 7005]# redis-server redis.conf
[root@server1 7005]# ls
appendonly.aof nodes.conf redis.conf redis.log redis.pid
[root@server1 cluster]# cd 7006
[root@server1 7006]# ls
redis.conf
[root@server1 7006]# vim redis.conf
[root@server1 7006]# cat redis.conf
port 7006
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
daemonize yes
pidfile /usr/local/cluster/7006/redis.pid
logfile /usr/local/cluster/7006/redis.log
[root@server1 7006]# redis-server redis.conf
[root@server1 7006]# ls
appendonly.aof nodes.conf redis.conf redis.log redis.pid
[root@server1 7006]# ps ax
[root@server1 7006]# redis-trib.rb create --replicas 1 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 127.0.0.1:7006
>>> Creating cluster
>>> Performing hash slots allocation on 6 nodes...
Using 3 masters:
127.0.0.1:7001
127.0.0.1:7002
127.0.0.1:7003
Adding replica 127.0.0.1:7005 to 127.0.0.1:7001
Adding replica 127.0.0.1:7006 to 127.0.0.1:7002
Adding replica 127.0.0.1:7004 to 127.0.0.1:7003
>>> Trying to optimize slaves allocation for anti-affinity
[WARNING] Some slaves are in the same host as their master
M: b517a81b4ea86301002e9c237d73a1dd42440101 127.0.0.1:7001
slots:0-5460 (5461 slots) master
M: a6f17371926c65f3663abb08b09c5e534ad3cad4 127.0.0.1:7002
slots:5461-10922 (5462 slots) master
M: 0e100779ef9039b7d1082d055d397e2d955a8281 127.0.0.1:7003
slots:10923-16383 (5461 slots) master
[root@server1 7006]# redis-trib.rb check 127.0.0.1:7001
>>> Performing Cluster Check (using node 127.0.0.1:7001)
M: b517a81b4ea86301002e9c237d73a1dd42440101 127.0.0.1:7001
slots:0-5460 (5461 slots) master
1 additional replica(s)
S: 6b65b5e799543daa8ad7c5ec2c37bb04f860002c 127.0.0.1:7005
slots: (0 slots) slave
replicates 0e100779ef9039b7d1082d055d397e2d955a8281
M: 0e100779ef9039b7d1082d055d397e2d955a8281 127.0.0.1:7003
slots:10923-16383 (5461 slots) master
1 additional replica(s)
M: a6f17371926c65f3663abb08b09c5e534ad3cad4 127.0.0.1:7002
slots:5461-10922 (5462 slots) master
1 additional replica(s)
S: dffd9fca6003425737114d68dfe8a343a32658db 127.0.0.1:7004
slots: (0 slots) slave
replicates a6f17371926c65f3663abb08b09c5e534ad3cad4
S: 62f34720497b2402bd25dddfe3f4d462c083c7b2 127.0.0.1:7006
slots: (0 slots) slave
replicates b517a81b4ea86301002e9c237d73a1dd42440101
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
[root@server1 7006]# cd
[root@server1 ~]# ls
libyaml-0.1.3-4.el6_6.x86_64.rpm redis-4.0.8.tar.gz
redis-4.0.1.gem ruby-2.2.3-1.el6.x86_64.rpm
redis-4.0.8 rubygems-1.3.7-5.el6.noarch.rpm
[root@server1 ~]# redis-cli -c -p 7001
127.0.0.1:7001> set name xfl
-> Redirected to slot [5798] located at 127.0.0.1:7002
OK
127.0.0.1:7002> get name
"xfl"
127.0.0.1:7002> quit
[root@server1 ~]# redis-cli -c -p 7006
127.0.0.1:7006> get name
-> Redirected to slot [5798] located at 127.0.0.1:7002
"xfl"
127.0.0.1:7002> quit
[root@server1 ~]# ps ax
1146 ? Ssl 0:01 redis-server *:7001 [cluster]
1168 ? Ssl 0:01 redis-server *:7002 [cluster]
1177 ? Ssl 0:01 redis-server *:7003 [cluster]
1186 ? Ssl 0:01 redis-server *:7004 [cluster]
1194 ? Ssl 0:01 redis-server *:7005 [cluster]
1203 ? Ssl 0:01 redis-server *:7006 [cluster]
1239 pts/0 R+ 0:00 ps ax
[root@server1 ~]# kill 1168
[root@server1 ~]# redis-cli -c -p 7006
127.0.0.1:7006> get name 依旧可以获取,因为会有从端出来顶替成为新的master
-> Redirected to slot [5798] located at 127.0.0.1:7004
"xfl"
127.0.0.1:7004> quit
[root@server1 ~]# redis-trib.rb check 127.0.0.1:7001
>>> Performing Cluster Check (using node 127.0.0.1:7001)
M: b517a81b4ea86301002e9c237d73a1dd42440101 127.0.0.1:7001
slots:0-5460 (5461 slots) master
1 additional replica(s)
S: 6b65b5e799543daa8ad7c5ec2c37bb04f860002c 127.0.0.1:7005
slots: (0 slots) slave
replicates 0e100779ef9039b7d1082d055d397e2d955a8281
M: 0e100779ef9039b7d1082d055d397e2d955a8281 127.0.0.1:7003
slots:10923-16383 (5461 slots) master
1 additional replica(s)
M: dffd9fca6003425737114d68dfe8a343a32658db 127.0.0.1:7004
slots:5461-10922 (5462 slots) master
0 additional replica(s)
S: 62f34720497b2402bd25dddfe3f4d462c083c7b2 127.0.0.1:7006
slots: (0 slots) slave
replicates b517a81b4ea86301002e9c237d73a1dd42440101
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
1146 ? Ssl 0:01 redis-server *:7001 [cluster]
1177 ? Ssl 0:01 redis-server *:7003 [cluster]
1186 ? Ssl 0:01 redis-server *:7004 [cluster]
1194 ? Ssl 0:01 redis-server *:7005 [cluster]
1203 ? Ssl 0:01 redis-server *:7006 [cluster]
1245 pts/0 R+ 0:00 ps ax
[root@server1 ~]# kill 1186
[root@server1 ~]# redis-cli -c -p 7006
127.0.0.1:7006> get name
(error) CLUSTERDOWN The cluster is down
127.0.0.1:7006> quit
[root@server1 7006]# cd ..
[root@server1 cluster]# cd 7002
[root@server1 7002]# redis-server redis.conf
[root@server1 7002]# cd ..
[root@server1 cluster]# cd 7004
[root@server1 7004]# redis-server redis.conf
[root@server1 7004]# ls
appendonly.aof dump.rdb nodes.conf redis.conf redis.log redis.pid
[root@server1 7004]#
重新检测恢复之后7004作为master,7002作为slave:
[root@server1 7004]# redis-trib.rb check 127.0.0.1:7001
>>> Performing Cluster Check (using node 127.0.0.1:7001)
M: b517a81b4ea86301002e9c237d73a1dd42440101 127.0.0.1:7001
slots:0-5460 (5461 slots) master
1 additional replica(s)
S: a6f17371926c65f3663abb08b09c5e534ad3cad4 127.0.0.1:7002
slots: (0 slots) slave
replicates dffd9fca6003425737114d68dfe8a343a32658db
M: dffd9fca6003425737114d68dfe8a343a32658db 127.0.0.1:7004
slots:5461-10922 (5462 slots) master
1 additional replica(s)
M: 6b65b5e799543daa8ad7c5ec2c37bb04f860002c 127.0.0.1:7005
slots:10923-16383 (5461 slots) master
1 additional replica(s)
S: 62f34720497b2402bd25dddfe3f4d462c083c7b2 127.0.0.1:7006
slots: (0 slots) slave
replicates b517a81b4ea86301002e9c237d73a1dd42440101
S: 0e100779ef9039b7d1082d055d397e2d955a8281 127.0.0.1:7003
slots: (0 slots) slave
replicates 6b65b5e799543daa8ad7c5ec2c37bb04f860002c
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
将两个master端杀死可以获取数据,这里需要解释一下,当过半的master被down掉之后一般是会毁坏整个集群状态的,这里我是第二次检测两个从端全部出来顶替主端,第一个是直接失败的:
1073 ? Ssl 0:00 redis-server *:7001 [cluster]
1078 ? Ssl 0:00 redis-server *:7002 [cluster]
1083 ? Ssl 0:00 redis-server *:7003 [cluster]
1088 ? Ssl 0:00 redis-server *:7004 [cluster]
1095 ? Ssl 0:00 redis-server *:7005 [cluster]
1102 ? Ssl 0:00 redis-server *:7006 [cluster]
1121 pts/0 R+ 0:00 ps ax
[root@server1 7004]# kill -9 1088
[root@server1 7004]# kill -9 1095
[root@server1 7004]# redis-cli -c -p 7006
127.0.0.1:7006> get name
-> Redirected to slot [5798] located at 127.0.0.1:7002
"xfl"
127.0.0.1:7002> get name
"xfl"
127.0.0.1:7002> get name
"xfl"
检测主从对应关系,已经变成了三个master端,一个slave端:
[root@server1 7004]# redis-trib.rb check 127.0.0.1:7001
>>> Performing Cluster Check (using node 127.0.0.1:7001)
M: b517a81b4ea86301002e9c237d73a1dd42440101 127.0.0.1:7001
slots:0-5460 (5461 slots) master
1 additional replica(s)
M: a6f17371926c65f3663abb08b09c5e534ad3cad4 127.0.0.1:7002
slots:5461-10922 (5462 slots) master
0 additional replica(s)
S: 62f34720497b2402bd25dddfe3f4d462c083c7b2 127.0.0.1:7006
slots: (0 slots) slave
replicates b517a81b4ea86301002e9c237d73a1dd42440101
M: 0e100779ef9039b7d1082d055d397e2d955a8281 127.0.0.1:7003
slots:10923-16383 (5461 slots) master
0 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
结合redis搭建lnmp环境Redis 作 mysql 的缓存服务器:
server1:php,nginx
server2:redis的master端
server3:mysql端
server1安装nginx和php:
[root@server1 ~]# ls
nginx-1.8.0-1.el6.ngx.x86_64.rpm
php-5.3.3-38.el6.x86_64.rpm
php-cli-5.3.3-38.el6.x86_64.rpm
php-common-5.3.3-38.el6.x86_64.rpm
php-devel-5.3.3-38.el6.x86_64.rpm
php-fpm-5.3.3-38.el6.x86_64.rpm
php-gd-5.3.3-38.el6.x86_64.rpm
php-mbstring-5.3.3-38.el6.x86_64.rpm
php-mysql-5.3.3-38.el6.x86_64.rpm
php-pdo-5.3.3-38.el6.x86_64.rpm
phpredis-master.zip
[root@server1 ~]# yum install nginx-1.8.0-1.el6.ngx.x86_64.rpm php-* -y
更改时区:
[root@server1 ~]# vim /etc/php.ini
[root@server1 ~]# cd /etc/php.d/
[root@server1 php.d]# ls
curl.ini json.ini mysql.ini pdo_sqlite.ini zip.ini
fileinfo.ini mbstring.ini pdo.ini phar.ini
gd.ini mysqli.ini pdo_mysql.ini sqlite3.ini
[root@server1 php.d]# id nginx
uid=498(nginx) gid=499(nginx) groups=499(nginx)
[root@server1 php.d]# cd /etc/php-fpm.d/
[root@server1 php-fpm.d]# ls
www.conf
[root@server1 php-fpm.d]# vim www.conf 添加用户组
[root@server1 php-fpm.d]# /etc/init.d/php-fpm start 打开PHP服务
Starting php-fpm: [ OK ]
[root@server1 php-fpm.d]# netstat -antlp 查看端口9000开启
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:6379 0.0.0.0:* LISTEN 914/redis-server 0.
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 907/sshd
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 993/master
tcp 0 0 127.0.0.1:9000 0.0.0.0:* LISTEN 1222/php-fpm
tcp 0 0 172.25.38.1:44147 172.25.38.2:6379 ESTABLISHED 914/redis-server 0.
tcp 0 0 172.25.38.1:22 172.25.38.250:42654 ESTABLISHED 1043/sshd
tcp 0 0 :::22 :::* LISTEN 907/sshd
tcp 0 0 ::1:25 :::* LISTEN 993/master
[root@server1 php-fpm.d]# cd /etc/nginx/
[root@server1 nginx]# ls
conf.d koi-utf mime.types scgi_params win-utf
fastcgi_params koi-win nginx.conf uwsgi_params
[root@server1 nginx]# cd conf.d/
[root@server1 conf.d]# ls
default.conf example_ssl.conf
[root@server1 conf.d]# vim default.conf 打开php访问
[root@server1 conf.d]# /etc/init.d/nginx start 开启nginx服务
Starting nginx: [ OK ]
[root@server1 conf.d]# netstat -antlp 查看默认端口80开启
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:6379 0.0.0.0:* LISTEN 914/redis-server 0.
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 1253/nginx
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 907/sshd
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 993/master
tcp 0 0 127.0.0.1:9000 0.0.0.0:* LISTEN 1222/php-fpm
tcp 0 0 172.25.38.1:44147 172.25.38.2:6379 ESTABLISHED 914/redis-server 0.
tcp 0 0 172.25.38.1:22 172.25.38.250:42654 ESTABLISHED 1043/sshd
tcp 0 0 :::22 :::* LISTEN 907/sshd
tcp 0 0 ::1:25 :::* LISTEN 993/master
[root@server1 conf.d]# cd /usr/share/nginx/html/
[root@server1 html]# ls
50x.html index.html
[root@server1 html]# vim index.php 编写php访问界面
在网页测试可以看到nginx测试页:
更改默认访问顺序为PHP:
[root@server1 html]# cd ..
[root@server1 nginx]# ls
html
[root@server1 nginx]# cd
[root@server1 ~]# cd /etc/nginx/conf.d/
[root@server1 conf.d]# ls
default.conf example_ssl.conf
[root@server1 conf.d]# vim default.conf 添加php访问优先
[root@server1 conf.d]# which nginx
/usr/sbin/nginx
[root@server1 conf.d]# nginx -s reload 重启服务
在网页测试可以看到PHP界面:
配置php的测试页和server2进行数据交互:
[root@server1 ~]# ls
test.php 测试php界面脚本
[root@server1 ~]# cp test.php /usr/share/nginx/html/index.php
cp: overwrite `/usr/share/nginx/html/index.php'? y
[root@server1 ~]# cd /usr/share/nginx/html/
[root@server1 html]# ls
50x.html index.html index.php
[root@server1 html]# vim index.php
[root@server1 html]# cat index.php
connect('172.25.38.2',6379) or die ("could net connect redis server");
# $query = "select * from test limit 9";
$query = "select * from test";
for ($key = 1; $key < 10; $key++)
{
if (!$redis->get($key))
{
$connect = mysql_connect('172.25.38.3','redis','westos');
mysql_select_db(test);
$result = mysql_query($query);
//如果没有找到$key,就将该查询sql的结果缓存到redis
while ($row = mysql_fetch_assoc($result))
{
$redis->set($row['id'],$row['name']);
}
$myserver = 'mysql';
break;
}
else
{
$myserver = "redis";
$data[$key] = $redis->get($key);
}
}
echo $myserver;
echo "
";
for ($key = 1; $key < 10; $key++)
{
echo "number is $key";
echo "
";
echo "name is $data[$key]";
echo "
";
}
?>
[root@server1 html]# yum install -y unzip 安装解压工具
[root@server1 ~]# unzip phpredis-master.zip
[root@server1 ~]# cd phpredis-master
[root@server1 phpredis-master]# ls
common.h debian library.c php_redis.h redis_session.c tests
config.m4 debian.control library.h README.markdown redis_session.h
CREDITS igbinary mkdeb-apache2.sh redis.c serialize.list
[root@server1 phpredis-master]# phpize
Configuring for:
PHP Api Version: 20090626
Zend Module Api No: 20090626
Zend Extension Api No: 220090626
[root@server1 phpredis-master]# ./configure
[root@server1 phpredis-master]# make && make install
配置php和redis的结合:
[root@server1 phpredis-master]# cd /usr/lib64/php/modules/
[root@server1 modules]# ls
curl.so gd.so mbstring.so mysql.so pdo.so phar.so sqlite3.so
fileinfo.so json.so mysqli.so pdo_mysql.so pdo_sqlite.so redis.so zip.so
[root@server1 modules]# cd /etc/php.d/
[root@server1 php.d]# ls
curl.ini gd.ini mbstring.ini mysql.ini pdo_mysql.ini phar.ini zip.ini
fileinfo.ini json.ini mysqli.ini pdo.ini pdo_sqlite.ini sqlite3.ini
[root@server1 php.d]# cp mysql.ini redis.ini
[root@server1 php.d]# vim redis.ini
[root@server1 php.d]# cat redis.ini
extension=redis.so 加载 redis 模块
[root@server1 php.d]# /etc/init.d/php-fpm reload
Reloading php-fpm: [12-Aug-2018 13:30:32] NOTICE: configuration file /etc/php-fpm.conf test is successful
[ OK ]
[root@server1 php.d]# php -m | grep redis
redis
在server3配置mysql,这里用之前实验过的虚拟机,新的虚拟机直接安装mysql-server开始就行:
[root@server3 ~]# /etc/init.d/redis_6379 stop 关闭redis服务
Stopping ...
Redis stopped
[root@server3 ~]# rpm -qa|grep mysql
mysql-community-common-5.7.17-1.el6.x86_64
mysql-community-client-5.7.17-1.el6.x86_64
mysql-community-libs-compat-5.7.17-1.el6.x86_64
mysql-community-libs-5.7.17-1.el6.x86_64
mysql-community-server-5.7.17-1.el6.x86_64
mha4mysql-node-0.56-0.el6.noarch
[root@server3 ~]# cd /var/lib/mysql 删除之前的mysql环境
[root@server3 mysql]# ls
auto.cnf client-key.pem mysql public_key.pem sys
binlog.000001 ib_buffer_pool mysqld_safe.pid server3-relay-bin.000001 westos
binlog.index ibdata1 mysql.sock server3-relay-bin.000002
ca-key.pem ib_logfile0 mysql.sock.lock server3-relay-bin.index
ca.pem ib_logfile1 performance_schema server-cert.pem
client-cert.pem ibtmp1 private_key.pem server-key.pem
[root@server3 mysql]# rm -fr *
[root@server3 mysql]# ls
[root@server3 mysql]# cd
[root@server3 ~]# rpm -e --nodeps `rpm -qa | grep mysql` 卸载mysql
warning: /etc/my.cnf saved as /etc/my.cnf.rpmsave
[root@server3 ~]# yum install -y mysql-server 安装简单的mysql-server
[root@server3 ~]# cd /var/lib/mysql/
[root@server3 mysql]# ls
[root@server3 mysql]# /etc/init.d/mysqld start 开启数据库
[ OK ]
Starting mysqld: [ OK ]
[root@server3 mysql]# mysql
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| test |!
+--------------------+
3 rows in set (0.00 sec)
mysql> grant all on test.* to redis@'%' identified by 'westos'; 给所有redis用户授权可以查看test数据库
Query OK, 0 rows affected (0.00 sec)
[root@server3 ~]# ls
mha4mysql-node-0.56-0.el6.noarch.rpm redis-4.0.8 redis-4.0.8.tar.gz test.sql
[root@server3 ~]# vim test.sql
use test;
CREATE TABLE `test` (`id` int(7) NOT NULL AUTO_INCREMENT, `name` char(8) DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `test` VALUES (1,'test1'),(2,'test2'),(3,'test3'),(4,'test4'),(5,'test5'),(6,'test6'),(7,'test7'),(8,'test8'),(9,'test9');
#DELIMITER $$
#CREATE TRIGGER datatoredis AFTER UPDATE ON test FOR EACH ROW BEGIN
# SET @RECV=gman_do_background('syncToRedis', json_object(NEW.id as #`id`, NEW.name as `name`));
# END$$
#DELIMITER ;
[root@server3 ~]# mysql < test.sql
[root@server3 ~]#
[root@server2 ~]# redis-cli
127.0.0.1:6379> get 1
"test1"
127.0.0.1:6379> get 2
"test2"
127.0.0.1:6379> get 3
"test3"
127.0.0.1:6379> get 9
"test9"
127.0.0.1:6379>
mysql> use test
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> select * from test;
+----+-------+
| id | name |
+----+-------+
| 1 | test1 |
| 2 | test2 |
| 3 | test3 |
| 4 | test4 |
| 5 | test5 |
| 6 | test6 |
| 7 | test7 |
| 8 | test8 |
| 9 | test9 |
+----+-------+
9 rows in set (0.00 sec)
mysql> update test set name='westos' where id=1;
Query OK, 1 row affected (0.07 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select * from test;
+----+--------+
| id | name |
+----+--------+
| 1 | westos |
| 2 | test2 |
| 3 | test3 |
| 4 | test4 |
| 5 | test5 |
| 6 | test6 |
| 7 | test7 |
| 8 | test8 |
| 9 | test9 |
+----+--------+
9 rows in set (0.00 sec)
127.0.0.1:6379> get 1
"test1"
127.0.0.1:6379>
Gearman 是一个支持分布式的任务分发框架:
Gearman Job Server:Gearman 核心程序,需要编译安装并以守护进程形式运行在后台。
Gearman Client:可以理解为任务的请求者。
Gearman Worker:任务的真正执行者,一般需要自己编写具体逻辑并通过守护进程方式
运行,Gearman Worker 接收到 Gearman Client 传递的任务内容后,会按顺序处理。
大致思路:
下面要编写的 mysql 触发器,就相当于 Gearman 的客户端。修改表,插入表就相当于直接
下发任务。然后通过 lib_mysqludf_json UDF 库函数将关系数据映射为 JSON 格式,然后
在通过 gearman-mysql-udf 插件将任务加入到 Gearman 的任务队列中,最后通过
redis_worker.php,也就是 Gearman 的 worker 端来完成 redis 数据库的更新。
安装 gearman 软件包:
[root@server1 ~]# yum install gearmand-1.1.8-2.el6.x86_64.rpm libgearman-* libevent-* -y
[root@server1 ~]# /etc/init.d/gearmand start
Starting gearmand: [ OK ]
[root@server1 ~]# netstat -antlp 默认端口4730
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:6379 0.0.0.0:* LISTEN 914/redis-server 0.
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 1253/nginx
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 907/sshd
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 993/master
tcp 0 0 0.0.0.0:4730 0.0.0.0:* LISTEN 3642/gearmand
tcp 0 0 127.0.0.1:9000 0.0.0.0:* LISTEN 3590/php-fpm
tcp 0 0 172.25.38.1:44147 172.25.38.2:6379 ESTABLISHED 914/redis-server 0.
tcp 0 0 172.25.38.1:22 172.25.38.250:42654 ESTABLISHED 1043/sshd
tcp 0 0 :::22 :::* LISTEN 907/sshd
tcp 0 0 ::1:25 :::* LISTEN 993/master
tcp 0 0 :::4730 :::* LISTEN 3642/gearmand
[root@server1 ~]# scp gearman-mysql-udf-0.6.tar.gz lib_mysqludf_json-master.zip server3:/root
gearman-mysql-udf-0.6.tar.gz 100% 368KB 368.5KB/s 00:00
lib_mysqludf_json-master.zip 100% 23KB 22.9KB/s 00:00
安装 lib_mysqludf_jsonUDF 库函数将关系数据映射为 JSON 格式。通常,数据库中的数据映射为 JSON 格式,是通过程序来转换的。
[root@server3 ~]# ls
gearman-mysql-udf-0.6.tar.gz mha4mysql-node-0.56-0.el6.noarch.rpm redis-4.0.8.tar.gz
lib_mysqludf_json-master.zip redis-4.0.8 test.sql
[root@server3 ~]# yum install unzip -y
[root@server3 ~]# unzip lib_mysqludf_json-master.zip
Archive: lib_mysqludf_json-master.zip
37f851c808c4161beb4d5e535771dc0c59c82de6
creating: lib_mysqludf_json-master/
inflating: lib_mysqludf_json-master/README.md
inflating: lib_mysqludf_json-master/lib_mysqludf_json.c
inflating: lib_mysqludf_json-master/lib_mysqludf_json.html
inflating: lib_mysqludf_json-master/lib_mysqludf_json.so
inflating: lib_mysqludf_json-master/lib_mysqludf_json.sql
[root@server3 ~]# ls
gearman-mysql-udf-0.6.tar.gz mha4mysql-node-0.56-0.el6.noarch.rpm test.sql
lib_mysqludf_json-master redis-4.0.8
lib_mysqludf_json-master.zip redis-4.0.8.tar.gz
[root@server3 ~]# cd lib_mysqludf_json-master
[root@server3 lib_mysqludf_json-master]# ls
lib_mysqludf_json.c lib_mysqludf_json.so README.md
lib_mysqludf_json.html lib_mysqludf_json.sql
[root@server3 lib_mysqludf_json-master]# yum install gcc mysql-devel -y
[root@server3 lib_mysqludf_json-master]# gcc $(mysql_config --cflags) -shared -fPIC -o lib_mysqludf_json.so lib_mysqludf_json.c
[root@server3 lib_mysqludf_json-master]# ll
total 100
-rw-r--r-- 1 root root 25921 Feb 22 2013 lib_mysqludf_json.c
-rw-r--r-- 1 root root 20576 Feb 22 2013 lib_mysqludf_json.html
-rwxr-xr-x 1 root root 22223 Aug 12 14:29 lib_mysqludf_json.so
-rw-r--r-- 1 root root 1431 Feb 22 2013 lib_mysqludf_json.sql
-rw-r--r-- 1 root root 16416 Feb 22 2013 README.md
[root@server3 lib_mysqludf_json-master]# ll lib_mysqludf_json.so
-rwxr-xr-x 1 root root 22223 Aug 12 14:29 lib_mysqludf_json.so
[root@server3 lib_mysqludf_json-master]# cd /usr/lib64/mysql/plugin/
[root@server3 plugin]# ls
ha_archive.so ha_blackhole.so.0.0.0 ha_federated.so.0
ha_archive.so.0 ha_example.so ha_federated.so.0.0.0
ha_archive.so.0.0.0 ha_example.so.0 ha_innodb_plugin.so
ha_blackhole.so ha_example.so.0.0.0 ha_innodb_plugin.so.0
ha_blackhole.so.0 ha_federated.so ha_innodb_plugin.so.0.0.0
[root@server3 plugin]# cd -
/root/lib_mysqludf_json-master
[root@server3 lib_mysqludf_json-master]# ls
lib_mysqludf_json.c lib_mysqludf_json.so README.md
lib_mysqludf_json.html lib_mysqludf_json.sql
[root@server3 lib_mysqludf_json-master]# cp lib_mysqludf_json.so /usr/lib64/mysql/plugin/
[root@server3 lib_mysqludf_json-master]# cd /usr/lib64/mysql/plugin/
[root@server3 plugin]# ls
ha_archive.so ha_example.so ha_innodb_plugin.so
ha_archive.so.0 ha_example.so.0 ha_innodb_plugin.so.0
ha_archive.so.0.0.0 ha_example.so.0.0.0 ha_innodb_plugin.so.0.0.0
ha_blackhole.so ha_federated.so lib_mysqludf_json.so
ha_blackhole.so.0 ha_federated.so.0
ha_blackhole.so.0.0.0 ha_federated.so.0.0.0
[root@server3 plugin]# mysql
mysql> show global variables like 'plugin_dir'; 查看 mysql 的模块目录:
+---------------+-------------------------+
| Variable_name | Value |
+---------------+-------------------------+
| plugin_dir | /usr/lib64/mysql/plugin |
+---------------+-------------------------+
1 row in set (0.00 sec)
mysql> CREATE FUNCTION json_object RETURNS STRING SONAME
-> 'lib_mysqludf_json.so'; 注册 UDF 函数
Query OK, 0 rows affected (0.00 sec)
mysql> quit
Bye
安装 gearman-mysql-udf这个插件是用来管理调用 Gearman 的分布式的队列。
[root@server3 plugin]# ls
ha_archive.so ha_example.so ha_innodb_plugin.so
ha_archive.so.0 ha_example.so.0 ha_innodb_plugin.so.0
ha_archive.so.0.0.0 ha_example.so.0.0.0 ha_innodb_plugin.so.0.0.0
ha_blackhole.so ha_federated.so lib_mysqludf_json.so
ha_blackhole.so.0 ha_federated.so.0
ha_blackhole.so.0.0.0 ha_federated.so.0.0.0
[root@server3 plugin]# cd
[root@server3 ~]# ls
gearman-mysql-udf-0.6.tar.gz mha4mysql-node-0.56-0.el6.noarch.rpm test.sql
lib_mysqludf_json-master redis-4.0.8
lib_mysqludf_json-master.zip redis-4.0.8.tar.gz
[root@server3 ~]# tar zxf gearman-mysql-udf-0.6.tar.gz
[root@server3 ~]# ls
gearman-mysql-udf-0.6 lib_mysqludf_json-master.zip redis-4.0.8.tar.gz
gearman-mysql-udf-0.6.tar.gz mha4mysql-node-0.56-0.el6.noarch.rpm test.sql
lib_mysqludf_json-master redis-4.0.8
[root@server3 ~]# cd gearman-mysql-udf-0.6
[root@server3 gearman-mysql-udf-0.6]# ls
aclocal.m4 ChangeLog config.h.in configure.ac libgearman_mysql_udf Makefile.am NEWS
AUTHORS config configure COPYING m4 Makefile.in READM
[root@server3 ~]# yum install libgearman-* libevent-* -y
[root@server3 ~]# cd gearman-mysql-udf-0.6
[root@server3 gearman-mysql-udf-0.6]# ls
aclocal.m4 ChangeLog config.h.in configure.ac libgearman_mysql_udf Makefile.am NEWS
AUTHORS config configure COPYING m4 Makefile.in README
[root@server3 gearman-mysql-udf-0.6]# ./configure --libdir =/usr/lib64/mysql/plugin/
configure: error: expected an absolute directory name for --libdir: =/usr/lib64/mysql/plugin
[root@server3 gearman-mysql-udf-0.6]# ./configure --libdir=/usr/lib64/mysql/plugin/
[root@server3 gearman-mysql-udf-0.6]# make && make install
[root@server3 gearman-mysql-udf-0.6]# cd /usr/lib64/mysql/plugin/
[root@server3 plugin]# ls
ha_archive.so ha_example.so.0 ha_innodb_plugin.so.0.0.0
ha_archive.so.0 ha_example.so.0.0.0 libgearman_mysql_udf.la
ha_archive.so.0.0.0 ha_federated.so libgearman_mysql_udf.so
ha_blackhole.so ha_federated.so.0 libgearman_mysql_udf.so.0
ha_blackhole.so.0 ha_federated.so.0.0.0 libgearman_mysql_udf.so.0.0.0
ha_blackhole.so.0.0.0 ha_innodb_plugin.so lib_mysqludf_json.so
ha_example.so ha_innodb_plugin.so.0
[root@server3 plugin]# mysql
这里如果使用mysql5.7版本以后就会出现报错无法注册UDF函数,因为版本自带:
mysql> CREATE FUNCTION gman_do_background RETURNS STRING SONAME 'libgearman_mysql_udf.so';
Query OK, 0 rows affected (0.00 sec) 注册 UDF 函数
mysql> CREATE FUNCTION gman_servers_set RETURNS STRING SONAME
-> 'libgearman_mysql_udf.so'; 注册 UDF 函数
Query OK, 0 rows affected (0.00 sec)
mysql> select * from mysql.func; 查看函数
+--------------------+-----+-------------------------+----------+
| name | ret | dl | type |
+--------------------+-----+-------------------------+----------+
| json_object | 0 | lib_mysqludf_json.so | function |
| gman_do_background | 0 | libgearman_mysql_udf.so | function |
| gman_servers_set | 0 | libgearman_mysql_udf.so | function |
+--------------------+-----+-------------------------+----------+
3 rows in set (0.00 sec)
mysql> SELECT gman_servers_set('172.25.38.1:4730'); 指定 gearman 的服务信息
+--------------------------------------+
| gman_servers_set('172.25.38.1:4730') |
+--------------------------------------+
| 172.25.38.1:4730 |
+--------------------------------------+
[root@server3 ~]# vim test.sql
[root@server3 ~]# cat test.sql
use test;
#CREATE TABLE `test` (`id` int(7) NOT NULL AUTO_INCREMENT, `name` char(8) DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;
#INSERT INTO `test` VALUES (1,'test1'),(2,'test2'),(3,'test3'),(4,'test4'),(5,'test5'),(6,'test6'),(7,'test7'),(8,'test8'),(9,'test9');
DELIMITER $$
CREATE TRIGGER datatoredis AFTER UPDATE ON test FOR EACH ROW BEGIN
SET @RECV=gman_do_background('syncToRedis', json_object(NEW.id as `id`, NEW.name as `name`));
END$$
DELIMITER ;
[root@server3 ~]# mysql < test.sql
[root@server3 ~]# mysql
mysql> SHOW TRIGGERS FROM test;
+-------------+--------+-------+----------------------------------------------------------------------------------------------------------------+--------+---------+----------+----------------+----------------------+----------------------+--------------------+
| Trigger | Event | Table | Statement | Timing | Created | sql_mode | Definer | character_set_client | collation_connection | Database Collation |
+-------------+--------+-------+----------------------------------------------------------------------------------------------------------------+--------+---------+----------+----------------+----------------------+----------------------+--------------------+
| datatoredis | UPDATE | test | BEGIN
SET @RECV=gman_do_background('syncToRedis', json_object(NEW.id as `id`, NEW.name as `name`));
END | AFTER | NULL | | root@localhost | latin1 | latin1_swedish_ci | latin1_swedish_ci |
+-------------+--------+-------+----------------------------------------------------------------------------------------------------------------+--------+---------+----------+----------------+----------------------+----------------------+--------------------+
1 row in set (0.00 sec)
[root@server1 ~]# ll worker.php
-rw-r--r-- 1 root root 452 Aug 12 11:58 worker.php
[root@server1 ~]# cp worker.php /usr/local/
[root@server1 ~]# ll gearman-1.1.2.tgz
-rw-r--r-- 1 root root 30961 Aug 12 11:58 gearman-1.1.2.tgz
[root@server1 ~]# tar zxf gearman-1.1.2.tgz
[root@server1 ~]# cd gearman-1.1.2
[root@server1 gearman-1.1.2]# ls
ChangeLog CREDITS LICENSE php_gearman.h test_client.php test_worker.php
config.m4 examples php_gearman.c README tests
[root@server1 gearman-1.1.2]# phpize
Configuring for:
PHP Api Version: 20090626
Zend Module Api No: 20090626
Zend Extension Api No: 220090626
[root@server1 gearman-1.1.2]# ./configure && make && make install
[root@server1 gearman-1.1.2]# cd /usr/lib64/php/modules/
[root@server1 modules]# ls
curl.so gearman.so mysqli.so pdo.so redis.so
fileinfo.so json.so mysql.so pdo_sqlite.so sqlite3.so
gd.so mbstring.so pdo_mysql.so phar.so zip.so
[root@server1 modules]# cd /etc/php.d/
[root@server1 php.d]# ls
curl.ini gd.ini mbstring.ini mysql.ini pdo_mysql.ini phar.ini sqlite3.ini
fileinfo.ini json.ini mysqli.ini pdo.ini pdo_sqlite.ini redis.ini zip.ini
[root@server1 php.d]# cp redis.ini gearman.ini
[root@server1 php.d]# vim gearman.ini
[root@server1 php.d]# cat gearman.ini
extension=gearman.so
[root@server1 php.d]# /etc/init.d/php-fpm reload
Reloading php-fpm: [12-Aug-2018 15:05:20] NOTICE: configuration file /etc/php-fpm.conf test is successful
[ OK ]
[root@server1 php.d]# php -m | grep gearman
gearman
[root@server1 php.d]# cd /usr/local/
[root@server1 local]# ls
bin cluster etc games include lib lib64 libexec sbin share src worker.php
[root@server1 local]# vim worker.php
[root@server1 local]# cat worker.php
addServer();
$worker->addFunction('syncToRedis', 'syncToRedis');
$redis = new Redis();
$redis->connect('172.25.38.2', 6379);
while($worker->work());
function syncToRedis($job)
{
global $redis;
$workString = $job->workload();
$work = json_decode($workString);
if(!isset($work->id)){
return false;
}
$redis->set($work->id, $work->name);
}
?>
[root@server1 local]# nohup php worker.php &
[1] 6011
[root@server1 local]# nohup: ignoring input and appending output to `nohup.out'
[root@server1 local]#
mysql> use test
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> update test set name='redhat'; 更新数据
Query OK, 9 rows affected (0.06 sec)
Rows matched: 9 Changed: 9 Warnings: 0