一、安装+配置:
- 安装:
yum -y install redis php-redis
- 配置: vim /etc/redis.conf
# 允许所有主机访问
bind 0.0.0.0
protected-mode yes
port 6379
tcp-backlog 511
timeout 0
tcp-keepalive 300
daemonize no
supervised no
pidfile /var/run/redis_6379.pid
loglevel notice
logfile /var/log/redis/redis.log
databases 16
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
dir /var/lib/redis
slave-serve-stale-data yes
slave-read-only yes
repl-diskless-sync no
repl-diskless-sync-delay 5
repl-disable-tcp-nodelay no
slave-priority 100
# 设置访问密码
requirepass 123456
# 最大访问数
maxclients 100000
appendonly no
appendfilename "appendonly.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
lua-time-limit 5000
slowlog-log-slower-than 10000
slowlog-max-len 128
latency-monitor-threshold 0
notify-keyspace-events ""
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-size -2
list-compress-depth 0
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
hll-sparse-max-bytes 3000
activerehashing yes
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
hz 10
aof-rewrite-incremental-fsync yes
- 启动服务:
systemctl start redis
- 连接:
redis-cli -a 123456
- 获取数据库保存文件路径:
config get dir
二、主从复制:
- 主服务器配置(192.168.8.81): vim /etc/redis.conf
# 允许所有主机访问
bind 0.0.0.0
protected-mode yes
port 6379
tcp-backlog 511
timeout 0
tcp-keepalive 300
daemonize no
supervised no
pidfile /var/run/redis_6379.pid
loglevel notice
logfile /var/log/redis/redis.log
databases 16
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
dir /var/lib/redis
slave-serve-stale-data yes
slave-read-only yes
repl-diskless-sync no
repl-diskless-sync-delay 5
repl-disable-tcp-nodelay no
slave-priority 100
# 设置访问密码
requirepass 123456
# 最大访问数
maxclients 100000
appendonly no
appendfilename "appendonly.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
lua-time-limit 5000
slowlog-log-slower-than 10000
slowlog-max-len 128
latency-monitor-threshold 0
notify-keyspace-events ""
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-size -2
list-compress-depth 0
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
hll-sparse-max-bytes 3000
activerehashing yes
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
hz 10
aof-rewrite-incremental-fsync yes
- 从服务器配置(192.168.8.82):
# 允许所有主机访问
bind 0.0.0.0
protected-mode yes
port 6379
tcp-backlog 511
timeout 0
tcp-keepalive 300
daemonize no
supervised no
pidfile /var/run/redis_6379.pid
loglevel notice
logfile /var/log/redis/redis.log
databases 16
save "" # 从服务器关闭持久化
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
dir /var/lib/redis
# 设置为从服务器
slaveof 192.168.8.81 6379
# 主服务器密码
masterauth 123456
slave-serve-stale-data yes
slave-read-only yes
repl-diskless-sync no
repl-diskless-sync-delay 5
repl-disable-tcp-nodelay no
slave-priority 100
# 设置访问密码
requirepass 123456
# 最大访问数
maxclients 100000
appendonly no
appendfilename "appendonly.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
lua-time-limit 5000
slowlog-log-slower-than 10000
slowlog-max-len 128
latency-monitor-threshold 0
notify-keyspace-events ""
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-size -2
list-compress-depth 0
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
hll-sparse-max-bytes 3000
activerehashing yes
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
hz 10
aof-rewrite-incremental-fsync yes
- 测试: a. 主(192.168.8.81): redis-cli -a 123456
set name dollarphp
b. 从(192.168.8.82): redis-cli -a 123456
get name
三、负载均衡(twemproxy):
- 使用场景:
适用于多个从redis从服务器之间的读操作
- 系统架构:
角色 ip地址
主redis+负载均衡 192.168.8.81
从redis 192.168.8.82
从redis 192.168.8.83
- 下载:
yum -y groupinstall "development tools"
git clone https://github.com/dollarphper/twemproxy.git
cd twemproxy
- 解压:
tar -xzf nutcracker-0.4.1.tar.gz
- 安装:
cd nutcracker-0.4.1
autoreconf -fvi
./configure --prefix=/usr/local/twemproxy
make -j 8
make install
- 设置环境变量:
echo "PATH=$PATH:/usr/local/twemproxy/sbin/" >> /etc/profile
. /etc/profile
- 创建目录:
mkdir -p /usr/local/twemproxy/run
mkdir -p /usr/local/twemproxy/sbin/conf
- 添加配置文件: vim /usr/local/twemproxy/sbin/conf/nutcracker.yml
alpha:
listen: 0.0.0.0:8143
hash: fnv1a_64
distribution: ketama
auto_eject_hosts: true
redis: true
server_retry_timeout: 2
server_failure_limit: 1
redis_auth: 123456
servers:
- 192.168.8.82:6379:1
- 192.168.8.83:6379:1
- 检查配置文件语法:
cd /usr/local/twemproxy/sbin/
./nutcracker -t
10. 启动服务:
nutcracker -d -c /usr/local/twemproxy/sbin/conf/nutcracker.yml -p /usr/local/twemproxy/run/redisproxy.pid -o /usr/local/twemproxy/run/redisproxy.log
- 停止服务:
pkill nutcracker
- 创建启动服务: vim /usr/lib/systemd/system/twemproxy.service
[Unit]
Description=twemproxy
After=network.target
[Service]
Type=forking
PIDFile=/usr/local/twemproxy/run/redisproxy.pid
ExecStart=/bin/bash /home/lee/shell/twemproxy.sh
ExecStop=/usr/bin/pkil nutcracker
PrivateTmp=true
[Install]
WantedBy=multi-user.target
- 启动服务:
systemctl enable twemproxy
systemctl start twemproxy
- 添加开机自启动:
chkconfig twemproxy on
- 测试: a. 主服务器(192.168.8.81): a-1. 窗口1:
redis-cli -a 123456
set name dollarphp
a-2. 窗口2:
redis-cli -a 123456 -p 8143
get name
b. 从服务器(192.168.8.82):
systemctl stop redis
c. 从服务器(192.168.8.83):
systemctl stop redis
d. 主服务器(窗口2):
四、php+redis实现短信验证码(string+expire):
- 代码:
$redis->set('key', 'value');
$redis->expire('key', 3);
$redis->get('key');
五、php+redis实现文章列表(hash):
- 代码:
<?php
$redis = new Redis();
$redis->connect('192.168.8.81',6379);
$redis->auth('123456');
$data = array(
1=>array(
'title'=>'test title1',
'content'=>'test content',
'time'=>'test time'
),
2=>array(
'title'=>'test title2',
'content'=>'test content',
'time'=>'test time'
),
3=>array(
'title'=>'test title3',
'content'=>'test content',
'time'=>'test time'
)
);
$title = "article";
foreach($data as $k=>$v){
foreach($v as $k1=>$v1){
$redis->hSet($title.'_'.$k, $k1, $v1); # 存值
}
}
$val = $redis->hGetAll($title); # 取值,所有值
// $val = $redis->hMGet($title,array(1,3)); # 取值,指定多值
// $val = $redis->hGet($title,2); # 取值,指定单值
// $bool = $redis->hDel($title,2); # 删除指定值
// $len = $redis->hLen($title); # 求长度
ksort($val); # 排序
var_dump($val);
- 输出:
array(3) {
[1]=>
string(67) "{"title":"test title1","content":"test content","time":"test time"}"
[2]=>
string(67) "{"title":"test title2","content":"test content","time":"test time"}"
[3]=>
string(67) "{"title":"test title3","content":"test content","time":"test time"}"
}
六、php+redis实现队列(list):
- 代码:
<?php
$redis = new Redis();
$redis->connect('192.168.8.81',6379);
$redis->auth('123456');
$title = "order";
$data = array(
array(
'order_no'=>'001',
'user'=>'小明',
'expire'=>'1527732204'
),
array(
'order_no'=>'002',
'user'=>'小红',
'expire'=>'1527732205'
),
array(
'order_no'=>'003',
'user'=>'小华',
'expire'=>'1527732206'
)
);
foreach($data as $v){
$val = json_encode($v);
$redis->rPush($title,$val); # 入列
}
$val = $redis->lRange($title,0,-1); # 取值,取出队列中的所有值
// $val = $redis->lIndex($title,0); # 取值,取出最早插入的那条值
// $val = $redis->lPop($title); # 出列,取出最早插入的那条值,并删除
// $len = $redis->lLen($title); # 求长度,求列表的长度
// while(true){ # 守护进程
// $val = $redis->lPop($title); # 取出队列中的元素,可以配合redis的订阅、发布
// sleep(5); # 间隔5秒钟
// # 业务处理部分
// }
var_dump($val);
- 输出:
array(3) {
[0]=>
string(62) "{"order_no":"001","user":"\u5c0f\u660e","expire":"1527732204"}"
[1]=>
string(62) "{"order_no":"002","user":"\u5c0f\u7ea2","expire":"1527732205"}"
[2]=>
string(62) "{"order_no":"003","user":"\u5c0f\u534e","expire":"1527732206"}"
}
七、php+reids实现共同好友(set):
- 代码:
<?php
$redis = new Redis();
$redis->connect('192.168.8.81',6379);
$redis->auth('123456');
$title1 = "friend_1";
$title2 = "friend_2";
$data1 = array(
"xiaoming",
"xiaohua",
"xiaozhang"
);
$data2 = array(
"xiaoqiang",
"xiaoming",
"xiaoli"
);
foreach($data1 as $v){
$redis->sAdd($title1,$v); # 添加值
}
foreach($data2 as $v){
$redis->sAdd($title2,$v); # 添加值
}
$val = $redis->sMembers($title1); # 取值,取出title1中所有的成员
// $val = $redis->sInter($title1,$title2); # 求交集(最小匹配)
// $val = $redis->sDiff($title1,$title2); # 求差集(在title2中有,title1中没有的值)
// $val = $redis->sUnion($title1,$title2); # 求并集(最大匹配)
// $len = $redis->sCard($title1); # 求长度
// $bool = $redis->sIsMember($title1,'xiaohong'); # 判断指定值是否在集合中
var_dump($val);
- 输出:
array(3) {
[0]=>
string(9) "xiaozhang"
[1]=>
string(8) "xiaoming"
[2]=>
string(7) "xiaohua"
}
八、php+redis实现排行榜(sorted set):
- 代码:
<?php
$redis = new Redis();
$redis->connect('192.168.8.81',6379);
$redis->auth('123456');
$title = "score";
$data = array(
"1000"=>array(
"xiaoming"
),
"1050"=>array(
"xiaoqiang",
"xiaozhang"
),
"1100"=>array(
"xiaohong"
)
);
foreach($data as $k=>$v){
foreach($v as $v1){
$redis->zAdd($title,$k,$v1); # 添加分数和成员
}
}
// $redis->zIncrBy($title,-10,"xiaoqiang"); # 分数增加,值可以为负数
// $redis->zRem($title,"xiaoqiang"); # 移除指定成员
// $redis->zRemRangeByScore($title,1000,1050); # 移除指定分数区间内的成员
// $val = $redis->zRange($title,0,-1,true); # 排序,按分数从小到大
$val = $redis->zRevRange($title,0,-1,true); # 排序,按分数从大到小
// $val = $redis->zRangeByScore($title,1000,1080,array('withscores' => true)); # 排序,指定分数区间,按分数从小到大排序
// $val = $redis->zRevRangeByScore($title,1080,1000,array('withscores' => true)); # 排序,指定分数区间,按分数从大到小排序
// $val = $redis->zRank($title,"xiaohong"); # 返回成员的排名,按分数从小到大
// $val = $redis->zRevRank($title,"xiaohong"); # 返回成员的排名,按分数从大到小
// $val = $redis->zScore($title,"xiaohong"); # 返回成员的分数
// $len = $redis->zCard($title); # 返回成员的总数
// $len = $redis->zCount($title,1000,1050); # 返回指定分数区间内的成员总数
var_dump($val);
- 输出:
array(4) {
["xiaohong"]=>
float(1100)
["xiaozhang"]=>
float(1050)
["xiaoqiang"]=>
float(1050)
["xiaoming"]=>
float(1000)
}
九、php+redis实现发布/订阅—用于多台服务器之间的实时通信,一般用不上,忽略之(publish、subscribe):
- 订阅(sub.php):
<?php
$redis = new Redis();
$redis->connect('192.168.8.81',6379);
$redis->auth('123456');
$title = "channel";
$redis->subscribe(array($title),'callback');
function callback($i,$c,$m){
$msg = $c."==>".$m.PHP_EOL;
file_put_contents('msg.txt',$msg,FILE_APPEND);
}
- 发布(pub.php):
<?php
$redis = new Redis();
$redis->connect('192.168.8.81',6379);
$redis->auth('123456');
$title = "channel";
$res = $redis->publish($title,'hello');
- 守护进程(msg.sh):
#!/bin/bash
while true ; do
php /home/lee/redis/sub.php &> /home/lee/redis/msg.log
sleep 1
done &
- 运行守护进程:
. msg.sh
- 发布(3次):
php pub.php
php pub.php
php pub.php
- 查看: cat msg.txt
channel==>hello
channel==>hello
channel==>hello
十、事务(multi、exec):
- 代码:
$redis->multi();
$redis->set('name','lee000');
$redis->expire('name',5);
$redis->exec();