一、Redis基础
1、安装启动Redis
1.1 去pkgs.org下载rpm包
[root@node1 ~]# wget http://www6.atomicorp.com/channels/atomic/centos/6/i386/RPMS/redis-3.0.7-4.el6.art.i686.rpm
1.2 yum本地安装
[root@node1 ~]# yum localinstall redis-3.0.7-4.el6.art.i686.rpm
查看redis安装生成的文件:
[root@node1 ~]# rpm -ql redis
备份原始配置:
[root@node1 ~]# cp -p /etc/redis.conf{,.orgi}
1.3 配置
[root@node1 ~]# vim /etc/redis.conf
#监听多个地址:
bind 127.0.0.1 10.201.106.21
启动:
[root@node1 ~]# service redis start
Starting redis-server: [ OK ]
[root@node1 ~]# ss -tnlp | grep redis
LISTEN 0 128 10.201.106.21:6379 *:* users:(("redis-server",16155,5))
LISTEN 0 128 127.0.0.1:6379 *:* users:(("redis-server",16155,4))
2、Redis使用
2.1 连接
[root@node1 ~]# redis-cli
127.0.0.1:6379>
获取帮助:
127.0.0.1:6379> help
查看支持的字符:
127.0.0.1:6379> help @STRING
查看单个命令用法:
127.0.0.1:6379> HELP APPEND
APPEND key value
summary: Append a value to a key
since: 2.0.0
group: string
TAB键可以补全命令
127.0.0.1:6379> HELP 按tab
命令是分组的:
127.0.0.1:6379> help @server
列出连接的客户端:
127.0.0.1:6379> CLIENT LIST
2.1.1 杂项
打开1号数据库:
127.0.0.1:6379> SELECT 1
OK
127.0.0.1:6379[1]>
默认是0号数据库:
127.0.0.1:6379[4]> SELECT 0
OK
127.0.0.1:6379>
2.2 数据类型常用命令
2.2.1 String
查看帮助:
127.0.0.1:6379> help @string
设置disto字串的值为fedora
127.0.0.1:6379> SET disto fedora
OK
获取disto的值
127.0.0.1:6379> GET disto
"fedora"
在同一个名称空间,对同一个键的二次定义,是修改其值:
127.0.0.1:6379> SET disto centos
OK
127.0.0.1:6379> GET disto
"centos"
附加延长字串:
127.0.0.1:6379> append disto slackware
(integer) 15
127.0.0.1:6379> GET disto
"centosslackware"
获取字串长度:
127.0.0.1:6379> STRLEN disto
(integer) 15
NX:键不存在才设定
可以通过SETNX判断键是否存在,不存在才创建,避免覆盖之前的:
127.0.0.1:6379> SET disto gentoo NX
(nil) #提示操作未能执行
还是原来的值
127.0.0.1:6379> GET disto
"centosslackware"
XX:键存在才设定:
127.0.0.1:6379> SET foo bar XX
(nil)
设置count键值为0,通过INCR不断加1
127.0.0.1:6379> SET count 0
OK
127.0.0.1:6379> INCR count
(integer) 1
127.0.0.1:6379> INCR count
(integer) 2
127.0.0.1:6379> INCR count
(integer) 3
127.0.0.1:6379> INCR count
(integer) 4
127.0.0.1:6379> GET count
"4"
减1:
127.0.0.1:6379> DECR count
(integer) 3
127.0.0.1:6379> DECR count
(integer) 2
127.0.0.1:6379> GET count
"2"
127.0.0.1:6379> DECR count
(integer) 1
127.0.0.1:6379> DECR count
(integer) 0
127.0.0.1:6379> DECR count
(integer) -1
127.0.0.1:6379> GET count
"-1"
无法递增字符内容:
127.0.0.1:6379> set foo bar
OK
127.0.0.1:6379> incr foo
(error) ERR value is not an integer or out of range
2.2.2 List[字串容器]
查看帮助:
127.0.0.1:6379> help @list
定义一个列表:
127.0.0.1:6379> LPUSH list1 mon
(integer) 1
获取第一个元素:
127.0.0.1:6379> lindex list1 0
"mon"
从左侧赋值:
127.0.0.1:6379> LPUSH list1 sun
(integer) 2
127.0.0.1:6379> lindex list1 0
"sun"
127.0.0.1:6379> lindex list1 1
"mon"
从右侧赋值:
127.0.0.1:6379> RPUSH list1 tue
(integer) 3
127.0.0.1:6379> LINDEX list1 2
"tue"
修改值:
127.0.0.1:6379> LSET list1 1 fri
OK
127.0.0.1:6379> LINDEX list1 1
"fri"
从右侧弹出值(删除):
127.0.0.1:6379> RPOP list1
"tue"
127.0.0.1:6379> RPOP list1
"fri"
127.0.0.1:6379> RPOP list1
"sun"
127.0.0.1:6379> RPOP list1
(nil) #没有值了,无法执行
2.2.3 Sets(集合)
查看集合命令帮助:
127.0.0.1:6379> HELP @SET
创建一个新的集合:
127.0.0.1:6379> SADD w1 mon tue wed thu fri sat sun
(integer) 7
创建第二个集合:
127.0.0.1:6379> SADD w2 tue thu day
(integer) 3
求两个集的交集(列出两个集合,同时拥有的值):
127.0.0.1:6379> SINTER w1 w2
1) "thu"
2) "tue"
求并集(大家都有的只留一份):
127.0.0.1:6379> SUNION w1 w2
1) "mon"
2) "tue"
3) "wed"
4) "fri"
5) "sat"
6) "sun"
7) "thu"
8) "day"
弹出元素(随机,无法控制):
127.0.0.1:6379> SPOP w1
"fri"
127.0.0.1:6379> SPOP w1
"sun"
判断元素是否在集合里面
127.0.0.1:6379> SISMEMBER w1 mon
(integer) 1
127.0.0.1:6379> SISMEMBER w1 sun
(integer) 0 #0表示不是
2.2.4 Sorted Sets(有序集合)
score=内建索引号码,内置排序号码。跟普通位置索引是两回事。但是score大小决定你的索引位置
查看帮助:
127.0.0.1:6379> help @sorted_set
定义有序集合:
127.0.0.1:6379> ZADD weekday1 1 mon 2 tue 3 wed
(integer) 3
查看集合的元素个数:
127.0.0.1:6379> ZCARD weekday1
(integer) 3
查看元素对应的索引号:
127.0.0.1:6379> ZRANK weekday1 tue
(integer) 1
127.0.0.1:6379> ZRANK weekday1 wed
(integer) 2
根据元素获取score
127.0.0.1:6379> ZSCORE weekday1 wed
"3"
指定索引返回元素:
127.0.0.1:6379> ZRANGE weekday1 0 2
1) "mon"
2) "tue"
3) "wed"
127.0.0.1:6379> ZRANGE weekday1 0 1
1) "mon"
2) "tue"
2.2.5 Hashed(映射)
外键指向整个映射,内键指明指定字段的值
查看帮助:
127.0.0.1:6379> help @hash
定义键:
127.0.0.1:6379> HSET h1 a mon
(integer) 1
获取指定映射内,指定字段的值:
127.0.0.1:6379> HGET h1 a
"mon"
在映射内添加新字段并赋值:
127.0.0.1:6379> HSET h1 b tue
(integer) 1
127.0.0.1:6379> HGET h1 b
"tue"
获取映射里面的所有键:
127.0.0.1:6379> HKEYS h1
1) "a"
2) "b"
获取映射里面的所有元素(键值)
127.0.0.1:6379> HVALS h1
1) "mon"
2) "tue"
获取映射里面的元素个数
127.0.0.1:6379> HLEN h1
(integer) 2
二、其它应用
1、Redis认证功能
1.1 编辑配置
设置密码为“redis123”
[root@node1 ~]# vim /etc/redis.conf
requirepass redis123
重启服务:
[root@node1 ~]# service redis restart
Stopping redis-server: [ OK ]
Starting redis-server: [ OK ]
1.2 验证
之前的默认连接方法:
[root@node1 ~]# redis-cli -h 10.201.106.21
10.201.106.21:6379> SELECT 0
(error) NOAUTH Authentication required.
认证:
10.201.106.21:6379> AUTH redis123
OK
10.201.106.21:6379> SELECT 0
OK
为了后面实验方便,将上面密码配置注释掉,重启服务,取消认证
2、Redis管理
2.1 清空数据库:
FLUSHDB:清空当前库
FLUSHALL:清空所有库
127.0.0.1:6379> FLUSHDB
OK
2.2 事务(通过MULTI,EXEC,WATCH等命令实现事务功能)
2.2.1 事务示例
启动一个事务:
127.0.0.1:6379> MULTI
OK
#不会马上执行,而是放在队列中
127.0.0.1:6379> SET ip 192.168.1.1
QUEUED
127.0.0.1:6379> GET ip
QUEUED
127.0.0.1:6379> SET port 8080
QUEUED
127.0.0.1:6379> GET port
QUEUED
事务执行(结果一并返回):
127.0.0.1:6379> EXEC
1) OK
2) "192.168.1.1"
3) OK
4) "8080"
2.2.2 WATCH(乐观锁演示)
ip键启动乐观锁监控
127.0.0.1:6379> WATCH ip
OK
开启事务:
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set IP 10.0.0.1
QUEUED
127.0.0.1:6379> GET ip
QUEUED
然后在EXEC之前,新开一个redis客户端窗口修改ip键的值:
127.0.0.1:6379> SET ip 172.16.0.1
OK
127.0.0.1:6379> get ip
"172.16.0.1"
回到第一个开启事务的窗口执行EXEC,由于ip值已经发生修改,事务执行失败
127.0.0.1:6379> EXEC
(nil) #事务未执行
2.2.3 一致性
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> GET ip
QUEUED
127.0.0.1:6379> SET port 6379
QUEUED
127.0.0.1:6379> SETT
(error) ERR unknown command 'SETT'
127.0.0.1:6379> EXEC
(error) EXECABORT Transaction discarded because of previous errors.
2.3 Redis的连接
2.3.1 PING
测试服务器是否在线
127.0.0.1:6379> PING
PONG
2.3.2 ECHO
127.0.0.1:6379> ECHO "hello redis"
"hello redis"
2.3.3 查看连接相关命令帮助
127.0.0.1:6379> help @connection
2.4 服务器端常用命令
2.4.1 查看帮助
127.0.0.1:6379> help @server
2.4.2 获取当前客户端连接名
连接没有指定,所以为空
127.0.0.1:6379> CLIENT GETNAME
(nil)
2.4.3 关闭客户端连接
127.0.0.1:6379> CLIENT KILL 127.0.0.1:49928
OK
2.4.4 设定当前连接名
127.0.0.1:6379> CLIENT SETNAME localconnect
OK
127.0.0.1:6379> CLIENT GETNAME
"localconnect"
2.4.5 获取当前服务器状态信息
127.0.0.1:6379> INFO
只显示内存段信息:
127.0.0.1:6379> INFO Memory
# Memory
used_memory:657760
used_memory_human:642.34K
used_memory_rss:1716224
used_memory_peak:678504
used_memory_peak_human:662.60K
used_memory_lua:24576
mem_fragmentation_ratio:2.61
mem_allocator:jemalloc-3.6.0
重置info统计信息:
CONFIG RESETSTAT
2.4.6 修改配置
运行时修改指定参数,只保存在内存
CONFIG SET parameter value :
把在内存修改的新值同步到文件中
CONFIG REWRITE
2.4.7 查看键的数量
127.0.0.1:6379> DBSIZE
(integer) 2
2.4.8 获取最新一次SAVE保存时间戳
127.0.0.1:6379> LASTSAVE
(integer) 1525450413
2.4.9 实时监控所接收的请求
127.0.0.1:6379> MONITOR
OK
2.4.10 把数据同步后,关闭服务
SHUTDOWN [SAVE]
3、Redis的发布订阅
3.1 查看相关命令帮助
127.0.0.1:6379> HELP @pubsub
3.2 简单示例
订阅news频道:
127.0.0.1:6379> SUBSCRIBE news
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "news"
3) (integer) 1
发布消息:
127.0.0.1:6379> PUBLISH news "heloow world"
(integer) 1
127.0.0.1:6379> PUBLISH news abc
(integer) 1
自动接收消息:
3.3 退订频道
UNSUBSCRIBE:退订此前订阅的频道;
4、模式匹配
127.0.0.1:6379> PSUBSCRIBE "new.i[to]"
Reading messages... (press Ctrl-C to quit)
1) "psubscribe"
2) "new.i[to]"
3) (integer) 1
127.0.0.1:6379> PUBLISH new.io redis
(integer) 1
127.0.0.1:6379> PUBLISH new.it qq
(integer) 1
5、持久化
5.1 列出redis持久化备份目录
127.0.0.1:6379> CONFIG GET dir
1) "dir"
2) "/var/lib/redis"
5.2 RDB持久化相关配置
RDB相关配置
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
dir /var/lib/redis/
关闭RDB:
save ""
5.3 AOF持久化
5.3.1 AOF配置
#默认关闭
appendonly no
appendfilename "appendonly.aof"
appendfsync {always|everysec|no}
no-appendfsync-on-rewrite no
#达到两倍开始重写AOF文件
auto-aof-rewrite-percentage 100
#AOF文件达到64M才重写
auto-aof-rewrite-min-size 64mb
5.4 备份恢复优先使用AOF备份
6、Redis复制(主从)
6.1 从服务器配置(node2)
安装redis:
[root@node2 ~]# yum -y localinstall redis-3.0.7-4.el6.art.i686.rpm
修改监听端口:
bind 10.201.106.22 127.0.0.1
服务启动:
[root@node2 ~]# service redis start
Starting redis-server: [ OK ]
服务器配置SLAVE:
[root@node2 ~]# redis-cli
127.0.0.1:6379> SLAVEOF 10.201.106.21 6379
OK
现在node2已经是从服务器了
日志查看:
[root@node2 ~]# tail -20 /var/log/redis/redis.log
`-._ `-._`-.__.-'_.-' _.-'
`-._ `-.__.-' _.-'
`-._ _.-'
`-.__.-'
1694:M 14 Sep 04:35:05.444 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
1694:M 14 Sep 04:35:05.444 # Server started, Redis version 3.0.7
1694:M 14 Sep 04:35:05.444 # 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.
1694:M 14 Sep 04:35:05.444 * The server is now ready to accept connections on port 6379
1694:S 14 Sep 04:36:03.912 * SLAVE OF 10.201.106.21:6379 enabled (user request from 'id=2 addr=127.0.0.1:54185 fd=6 name= age=32 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=32768 obl=0 oll=0 omem=0 events=r cmd=slaveof')
1694:S 14 Sep 04:36:04.156 * Connecting to MASTER 10.201.106.21:6379
1694:S 14 Sep 04:36:04.156 * MASTER <-> SLAVE sync started
1694:S 14 Sep 04:36:04.157 * Non blocking connect for SYNC fired the event.
1694:S 14 Sep 04:36:04.159 * Master replied to PING, replication can continue...
1694:S 14 Sep 04:36:04.160 * Partial resynchronization not possible (no cached master)
1694:S 14 Sep 04:36:04.196 * Full resync from master: d76cae20eecf731fd10f73a5498e61197a60e9de:1
1694:S 14 Sep 04:36:04.256 * MASTER <-> SLAVE sync: receiving 44 bytes from master
1694:S 14 Sep 04:36:04.256 * MASTER <-> SLAVE sync: Flushing old data
1694:S 14 Sep 04:36:04.256 * MASTER <-> SLAVE sync: Loading DB in memory
1694:S 14 Sep 04:36:04.256 * MASTER <-> SLAVE sync: Finished with success
主服务器配置
从服务器查看已经同步qq键值
清除主配置:
127.0.0.1:6379> FLUSHALL
OK
从库空了:
127.0.0.1:6379> KEYS *
(empty list or set)
获取从库配置:
127.0.0.1:6379> CONFIG GET slaveof
1) "slaveof"
2) "10.201.106.21 6379"
注意:如果master使用requirepass开启了认证功能,从服务器要使用masterauth <PASSWORD> 来连入服务器请求此密码进行认证
7、sentinel(哨兵,监测主从)
7.1 sentinel配置准备
关闭node2的redis进程
[root@node2 ~]# killall redis-server
在node2服务器启动三个redis进程,一个主库,两个从库(相当于一台机器启动三个redis)
创建配置存放目录:
[root@node2 ~]# mkdir -pv /etc/redis
拷贝配置文件到目录:
[root@node2 ~]# cp /etc/redis.conf /etc/redis/
再拷贝2个配置文件,共3个配置文件:
[root@node2 redis]# cp redis.conf redis.conf.2
[root@node2 redis]# cp redis.conf redis.conf.3
[root@node2 redis]# ls
redis.conf redis.conf.2 redis.conf.3
准备存放数据目录,并修改权限:
[root@node2 redis]# mkdir -pv /redis/db{1,2,3}
[root@node2 redis]# chown -R redis:redis /redis/db*
7.2 修改三个redis配置
第一个redis配置文件:
[root@node2 ~]# vim /etc/redis/redis.conf
#为了方便监听在0.0.0.0,建议如果配置多个IP监听,将外网IP配置在前面,127.0.0.1配置在后面,IP中间用空格隔开
bind 0.0.0.0
dir /redis/db1
#后面要用命令启动,需要设置开启进程运行后台功能
daemonize yes
第二个redis配置文件:
[root@node2 ~]# vim /etc/redis/redis.conf.2
pidfile /var/run/redis/redis2.pid
port 6380
logfile /var/log/redis/redis2.log
dir /redis/db2
bind 0.0.0.0
daemonize yes
第三个redis配置文件:
拷贝redis.conf.2配置文件覆盖redis.conf.3
[root@node2 ~]# cd /etc/redis
[root@node2 redis]# cp redis.conf.2 redis.conf.3
[root@node2 ~]# vim /etc/redis/redis.conf.3
pidfile /var/run/redis/redis3.pid
port 6381
logfile /var/log/redis/redis3.log
dir /redis/db3
daemonize yes
7.3 启动服务,并配置sentinel
启动第一个redis(主服务器):
[root@node2 ~]# redis-server /etc/redis/redis.conf
启动第二个redis(从服务器):
[root@node2 ~]# redis-server /etc/redis/redis.conf.2
启动第三个redis(从服务器):
[root@node2 ~]# redis-server /etc/redis/redis.conf.3
[root@node2 ~]# ss -tnlp | grep redis
LISTEN 0 128 *:6379 *:* users:(("redis-server",19377,4))
LISTEN 0 128 *:6380 *:* users:(("redis-server",19391,4))
LISTEN 0 128 *:6381 *:* users:(("redis-server",19397,4))
7.4 连接配置
连接主服务器检查状态是不是主服务器:
[root@node2 ~]# redis-cli -h 10.201.106.22 -p 6379
10.201.106.22:6379> info replication
# Replication
role:master
……
第一个从服务器配置:
[root@node2 ~]# redis-cli -h 10.201.106.22 -p 6380
配置向哪个主服务器进行同步
10.201.106.22:6380> SLAVEOF 10.201.106.22 6379
OK
第二个从服务器配置:
10.201.106.22:6381> SLAVEOF 10.201.106.22 6379
OK
主服务器查看状态:
10.201.106.22:6379> info replication
10.201.106.22:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=10.201.106.22,port=6380,state=online,offset=211,lag=1
slave1:ip=10.201.106.22,port=6381,state=online,offset=211,lag=0
……
7.5 测试同步
10.201.106.22:6379> SET ip 1.1.1.1
OK
查看已经能够正常同步:
10.201.106.22:6380> GET ip
"1.1.1.1"
10.201.106.22:6381> GET ip
"1.1.1.1"
7.6 sentinel监控主节点
准备配置文件:
[root@node2 ~]# cp /etc/redis-sentinel.conf /etc/redis/
[root@node2 ~]# vim /etc/redis/redis-sentinel.conf
#一个哨兵同意,就确定为故障
sentinel monitor mymaster 10.201.106.22 6379 1
#设置5秒检查不到主服务器,就将其down掉
sentinel down-after-milliseconds mymaster 5000
#并行度为1
sentinel parallel-syncs mymaster 1
#判断故障转移失败超时时间
sentinel failover-timeout mymaster 60000
启动sentinel服务:
[root@node2 ~]# redis-sentinel /etc/redis/redis-sentinel.conf
连入sentinel:
[root@node2 ~]# redis-cli -h 10.201.106.22 -p 26379
查看配置信息:
10.201.106.22:26379> info
获取master信息:
10.201.106.22:26379> SENTINEL masters
1) 1) "name"
2) "mymaster"
3) "ip"
4) "10.201.106.22"
5) "port"
6) "6379"
7) "runid"
8) "6afb08c6e2369213825dc8c08ca0fafede756569"
9) "flags"
10) "master"
11) "pending-commands"
12) "0"
13) "last-ping-sent"
14) "0"
15) "last-ok-ping-reply"
16) "603"
17) "last-ping-reply"
18) "603"
19) "down-after-milliseconds"
20) "5000"
21) "info-refresh"
22) "8121"
23) "role-reported"
24) "master"
25) "role-reported-time"
26) "521577"
27) "config-epoch"
28) "0"
29) "num-slaves"
30) "2"
31) "num-other-sentinels"
32) "0"
33) "quorum"
34) "1"
35) "failover-timeout"
36) "60000"
37) "parallel-syncs"
38) "1"
查看从节点服务器:
10.201.106.22:26379> SENTINEL slaves mymaster
7.7 故障转移测试
kill主服务器进程:
[root@node2 ~]# ps aux | grep 6379
root 19377 0.1 0.3 33920 1748 ? Ssl 05:53 0:04 redis-server 0.0.0.0:6379
[root@node2 ~]# kill 19377
在哨兵查看,6380端口(原第一从服务器)已经变成主服务器:
10.201.106.22:26379> INFO Sentinel
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
master0:name=mymaster,status=ok,address=10.201.106.22:6380,slaves=2,sentinels=1
查看主节点信息:
10.201.106.22:26379> SENTINEL masters
重新启动10.201.106.22:6379(原主服务器)
[root@node2 ~]# redis-server /etc/redis/redis.conf
再次查看,不会切换,主节点还是6380端口:
10.201.106.22:26379> INFO Sentinel
10.201.106.22:26379> SENTINEL slaves mymaster
8、Clustering(分片)
分布式解决方案:
Twemproxy(Twitter),不建议使用
Codis(豌豆荚,豆瓣),建议使用
Redis Cluster(官方)
Cerberus(芒果TV)
来源:51CTO
作者:fengyunjueding
链接:https://blog.51cto.com/zhongle21/2113716