Redis 的高级应用
Ø 简介
本文主要介绍 Redis 中的高级应用,主要包括以下内容:
1. 安全性
2. 主从复制
3. 事务处理
4. 持久化机制
5. 发布订阅消息
6. 虚拟内存的使用
7. 性能监控
1. 安全性
设置客户端连接后进行任何操作前需要使用的密码。
由于 redis 速度非常快,所以在一台比较好的服务器下,一个外部用户可以在一秒钟进行150k次的密码尝试,所以需要设置强大的密码防止黑客的暴力破解。
1) 为客户端设置登录密码(两种方式)
1. 第一种方式,在 redis.conf 配置文件中设置 requirepass 密码,重启 redis-server 后同样生效。
1) 使用 vi 打开 redis.conf 文件
[root@192 ~]# vi /usr/local/redis/etc/redis.conf
2) 搜索 requirepass 的位置,输入命令 /requirepass 并设置密码,如图:
3) 输入:wq命令保存并退出编辑。
4) 关闭 redis-server
[root@192 ~]# pkill redis-server
5) 开启 redis-server(注意:这里必须保证使用的是刚才修改过的 redis.conf 文件)
[root@192 ~]# /usr/local/redis/bin/redis-server /usr/local/redis/etc/redis.conf
6) 再次访问 redis 就需要输入密码授权了,例如:
7) 也可以在登录 redis-cli 时同时指定密码,例如:
但是出现了一个警告,意思是使用 -a 指定密码不安全!
2. 第二种方式,设置只在当前 redis-server 重启之前生效的登录密码,代码如下:
[root@192 ~]# /usr/local/redis/bin/redis-cli
127.0.0.1:6379> get name
"abc"
127.0.0.1:6379> config set requiepass 123456
(error) ERR Unsupported CONFIG parameter: requiepass
127.0.0.1:6379> config set requirepass 123456
OK
127.0.0.1:6379> get name
(error) NOAUTH Authentication required.
127.0.0.1:6379> auth 123456
OK
127.0.0.1:6379> get name
"abc"
这种方式有几个问题:
1) 重启 redis-server 之后之前设置的密码会被清除掉;
2) 不会将设置的密码记录到 redis.conf 中;
3) 可以理解为设置的一个临时密码。
Ø 注意:在做 Redis 集群时,所有的 Redis 客户端密码需要保持一致。
2. 主从复制
Redis 主从复制可以允许多个 slave server 拥有和 master server 相同的数据库版本,防止单节点服务器(服务器奔溃、数据丢失)。
1. Redis 主从复制的特点:
1) master 可以用于多个 slave.
2) 多个 slave 可以连接同一个 master 外,还可以连接到其他 slave.
3) 主从复制不会阻塞 master,在同步数据时,master 可以继续处理 client 请求。
4) 提高系统的伸缩性。
5) 注意:slave 不能进行写操作,否则报错:
(错误)READONLY-您不能针对只读副本进行写入。
2. Redis 主从复制过程:
1) slave 与 master 建立连接,发送 sync 同步命令。
2) master 会启动一个后台进程,将数据库快照保存到文件中,同时 master 主进程会开始收集新的写命令并缓存。
3) 后台完成保存后,就将此文件发送给 slave.
4) slave 将此文件保存到硬盘上。
3. 配置主从服务器:
1) 在 slave 的配置文件中加入以下配置:
1. 指定 master 的IP和端口,搜索/replicaof 或 /slaveof
2. 指定 master 的请求密码,搜索/masterauth
2) 开启 slave 的 redis-server 可能报错:
MASTER <-> REPLICA sync started
Error condition on socket for SYNC: No route to host
解决办法:
1. 关闭 master 的 reids-server
2. 将 redis.conf 中的 bind 127.0.0.1 改为 bind 0.0.0.0 即可。
3. 如果还是报错,关闭防火墙:service iptables stop
4. 开启 master 的 reids-server
3) 区分当前是主机还是从机
1. 输入 info 或者 info replication 命令,主机信息:
2. 输入 info 或者 info replication 命令,从机信息:
4) 其他
注意开启 redis-server 时配置文件的指定,例如:
/usr/local/redis/bin/redis-server /usr/local/redis/etc/redis.conf
优点:可以完整的 Redis 中的数据做备份。
缺点:当主机挡掉后,不能马上的做主从切换。
它只是 Redis 集群中的一小部分功能。
3. 事务处理
Redis 对事务的支持比较简单。Redis 只能保证一个 Client 发起的事务中的命令可可以连续的执行,而中间不会插入其他 Client 的命令。当一个 Client 在一个连接中发出 multi 命令时,这个连接会进入一个事务上下文,该连接后续的命令不会立即执行,而是先放到一个队列中,当执行 exec 命令时,redis 会顺序的执行队列中的命令。
1) 事务相关操作
1. 开启与提交事务
127.0.0.1:6379> multi #开启事务
OK
127.0.0.1:6379> set name abeam
QUEUED
127.0.0.1:6379> set age 30
QUEUED
127.0.0.1:6379> exec #提交事务
OK
OK
2. 取消事务中的队列任务
127.0.0.1:6379> multi #开启事务
OK
127.0.0.1:6379> set key2 vlaue2
QUEUED
127.0.0.1:6379> set key3 vlaue3
QUEUED
127.0.0.1:6379> discard #取消事务
OK
2) Redis 不能回滚事务中的队列,例如:
127.0.0.1:6379> multi
OK
127.0.0.1:6379> incr age
QUEUED
127.0.0.1:6379> incr name #这里的命令会报错
QUEUED
127.0.0.1:6379> exec
(integer) 31 #但是,这里的命令被正常执行了
(error) ERR value is not an integer or out of range
3) 乐观锁复杂事务控制
乐观锁:大多数是基于数据版本(version)的记录机制实现的。即为数据增加一个版本表示,在基于数据库表的版本解决方案中,一般是通过为数据表添加一个"version"字段来实现读取数据时,将此版本号一同读出,之后更新时对此版本号加1.此时,将提交数据的版本号与数据表中对应记录的当前版本号进行对比,如果提交的数据版本号大于数据库当前版本号,则予以更新,否则认为是过期数据。
1. Redis 使用 watch 命令实现乐观锁
watch 命令会监事给定的 key,当 exec 时如果监视的 key 从调用 watch 后发生过变化,则整个事务会失败。可以调用 watch 多次监控多个 key, 这样就可以对指定的 key 加乐观锁了。注意 watch 的 key 是对整个连接有效的,事务也一样。如果连接断开,监视和事务都会被自动清除。exec、discard、unwatch 命令都会清除连接中的所有监视。
1) Session1
127.0.0.1:6379> set age1 10
OK
127.0.0.1:6379> set age2 20
OK
127.0.0.1:6379> watch age1 #可以同时监控多个key
OK
127.0.0.1:6379> multi
OK
2) Session2
127.0.0.1:6379> set age1 100
OK
127.0.0.1:6379> set age2 200
OK
3) Session1
127.0.0.1:6379> incr age1
QUEUED
127.0.0.1:6379> incr age2
QUEUED
127.0.0.1:6379> exec #整个提交失败(因为监听的age1发生变化)
(nil)
127.0.0.1:6379> get age1
"100"
127.0.0.1:6379> get age2
"200"
4) 悲观锁(非Redis知识)
基于数据库的实现,当A用户查询、更新某条数据后,未提交之前B用户不允许进行更新,例如:
SELECT * FROM Member WHERE Id = 1 FOR UPDATE;
4. 持久化机制
Redis 是一个支持持久化的内存数据库,也就是说 redis 需要经常将内存中的数据同步到硬盘来保证持久化。Redis 支持两种持久化方式:
1. Snapshotting(快照)(存储数据)
快照是默认方式的持久化方式,这种方式是将内存中的数据写入到二进制文件中,默认的文件名为 dump.rdb。可以通过配置设置自动做快照持久化的方式,配置 redis 在 n 秒内如果超过 m 个 key 被修改就自动快照,例如:
save 900 1 #900秒内如果超过1个key被修改,则发起快照保存
save 300 10 #同上
save 60 10000 #同上
2. Append-only file(缩写aof)的方式(存储操作命令:增删改)
由于快照方式是在一定间隔时间做一次的,所以如果 redis 意外 down 掉的话,就会丢失最后一次快照后的所有修改。
aof 比快照方式具有更好的持久化性,是由于在使用 aof 时,redis 就会将每一个收到的写命令都通过 write 函数追加到文件中,当 redis 重启时会通过重新执行文件中保存的写命令来在内存中重建整个数据库的内容。
当然由于 os 会在内核中缓存 write 做的修改,所以可能不是立即写到磁盘上,这样 aof 方式的持久化也还是可能丢失部分修改。
可以通过配置文件告诉 redis 我们想要通过 fsync 函数强制 os 写入到磁盘的时机。
1. 开启 aof 持久化
1) 将 appendonly no 改为 yes #启用 aof 持久化方式
2) 三种持久化选择
# appendfsync always #收到写命令就立即写入磁盘,最慢,但是保证完全的持久化
appendfsync everysec #每秒钟写入磁盘一次,在性能和持久化方面做了很好的折中,默认值
# appendfsync no #完全依赖os,性能持久化没保证
3) 重启 redis-server
4) 将查看到 appendonly.aof 文件
5) 查看文件内容
5. 发布订阅消息
发布订阅(pub/sub)是一种消息通信模式,主要的目的是解除消息发布者和消息订阅者之间的耦合,Redis 作为一个 pub/sub 的 server, 在订阅者和发布者之间起到了消息路由的功能。订阅者可以通过 subscribe 和 psubscribe 命令向 redis server 订阅自己感兴趣的类型,redis 将信息类型成为通道(channel)。当发布者通过 publish 命令向 redis server 发送特定类型的消息时,订阅该信息类型的全部 client 都会收到此信息。
1) 监听发布示例
1. Session1(订阅1个消息 tv1)
127.0.0.1:6379> subscribe tv1 #订阅 tv1 的消息通道
Reading messages... (press Ctrl-C to quit)
"subscribe"
"tv1"
(integer) 1
"message" #收到 tv1 发布的信息
"tv1"
"message111"
2. Session2(订阅2个消息 tv1、tv2)
127.0.0.1:6379> subscribe tv1 tv2 #订阅 tv1和tv2 的消息通道
Reading messages... (press Ctrl-C to quit)
"subscribe"
"tv1"
(integer) 1
"subscribe"
"tv2"
(integer) 2
"message" #收到 tv1 发布的信息
"tv1"
"message111"
"message" #收到 tv2 发布的信息
"tv2"
"message222"
3. Session3(发布消息)
127.0.0.1:6379> publish tv1 message111 #发布 tv1 的消息
(integer) 2
127.0.0.1:6379> publish tv2 message222 #发布 tv2 的消息
(integer) 1
2) 相关命令
1. 模糊匹配订阅频道
127.0.0.1:6379> psubscribe tv*
Reading messages... (press Ctrl-C to quit)
"psubscribe"
"tv*"
(integer) 1
2. 查看客户端订阅的频道
127.0.0.1:6379> pubsub channels #查看所有订阅的频道
"tv1"
"tv2"
127.0.0.1:6379> pubsub channels *2 #模糊匹配订阅频道名称
"tv2"
6. 虚拟内存的使用
Redis 的虚拟内存与操作系统的虚拟内存不是一回事,但是思路和目的都是相同的。就是暂时把不经常访问的数据从内存交换到磁盘中,从而腾出宝贵的内存空间用于其他需要访问的数据。尤其是对 redis 这样的内存数据库,内存总是不够用的。除了可以将数据分割到多个 redis server 外。另外能够提高数据库容量的办法就是使用虚拟内存,把那些不经常访问的数据交换到磁盘上。
下面是 vm 相关配置(redis-2.4.17都有该配置,redis-5.0.5就没有该配置了?):
vm-enabled yes #开启 vm 功能
vm-swap-file /tmp/redis.swap #交换出来的 value 保存的文件路径
vm-max-memory 1000000 #redis 使用的最大内存上限
vm-page-size 32 #每个页面的大小32字节
vm-pages 134217728 #最多使用多个页面
vm-max-threads 4 #用于执行 value 对象换入的工作线程数量
really-use-vm yes #是否使用虚拟内存
7. 性能监控
Redis 本身不支持性能监控,但是可以使用"Redis-stat"组件实现性能监控,它可以实现对多个 Redis-Server 进行监控。这个工具可以通过 github 下载,下载地址:https://github.com/junegunn/redis-stat,下面是具体的实现步骤:
1) 建立三个 Redis 运行进程,准备不同的 redis.conf 配置文件。
2) 创建 redis 数据的保存目录,可以同时保存三个 Redis 进程:
mkdir -p /usr/data/redis/{redis-6379,redis-6380,redis-6381}/{run,logs,dbcache}
3) 将 redis.conf 拷贝一份:
cp /usr/local/redis/etc/redis.conf /usr/local/redis/etc/redis-6379.conf
4) 编辑"redis-6379.conf"配置文件:
vim /usr/local/redis/etc/redis.conf
1. 取消外网访问限制
注释掉"bind 127.0.0.1"或者改为"bind 0.0.0.0"
2. 端口保持不变:port 6379
3. 设置后台运行:daemonize yes
4. 设置 pid 保存文件路径
pidfile /usr/data/redis/redis-6379/run/redis_6379.pid
5. 设置日志文件路径
logfile "/usr/data/redis/redis-6379/logs/redis.log"
6. 设置数据文件路径
dir /usr/data/redis/redis-6379/dbcache/
5) 将"redis-6379.conf"复制为:redis-6380.conf、redis-6380.conf
cp /usr/local/redis/etc/redis-6379.conf /usr/local/redis/etc/redis-6380.conf
cp /usr/local/redis/etc/redis-6379.conf /usr/local/redis/etc/redis-6381.conf
6) 将其他的"*.conf"文件的6379替换为对应的端口号:
vim /usr/local/redis/etc/redis-6380.conf
执行替换命令:1,$s/6379/6380/g
vim /usr/local/redis/etc/redis-6381.conf
执行替换命令:1,$s/6379/6381/g
7) 启动所有的 Redis 服务:
/usr/local/redis/bin/redis-server /usr/local/redis/etc/redis-6379.conf
/usr/local/redis/bin/redis-server /usr/local/redis/etc/redis-6380.conf
/usr/local/redis/bin/redis-server /usr/local/redis/etc/redis-6381.conf
注:可采用"ps -ef | grep redis"或"netstat -tunpl"查看是否正常启动
8) 通过 Github 下载 redis-stat 开发包
l 如果想要使用 redis-stat 检测包必须下载 ruby 相关环境:
apt-get install ruby ruby-dev rubygems
l 将该工具下载到"/usr/local"目录下:cd /usr/local/
l 进行 redis-stat 的下载:
git clone https://github.com/junegunn/redis-stat.git
9) 执行"redis-stat"命令
cd /usr/local/redis-stat/bin
gem install redis-stat -V #加上"-V"参数才会在命令行显示安装日志
注:redis-stat 命令必须使用 ruby 进行命令处理
l 如果安装失败:Failed to build gem native extension.
执行"yum install ruby-devel"命令即可。
l 显示以下内容表示安装成功:
Installing ri documentation for redis-stat-0.4.14
13 gems installed
10) 启动 redis-stat 工具进行监听控制:
/usr/local/redis-stat/bin/redis-stat 192.168.175.128:6379 192.168.175.128:6380 192.168.175.128:6381 -a abeam.
11) 该工具还支持 Web 查看,它内部提供一个 HttpServer,在命令中加入相关参数即可:
/usr/local/redis-stat/bin/redis-stat 192.168.175.128:6379 192.168.175.128:6380 192.168.175.128:6381 -a abeam. --verbose --daemon --server=80
打开浏览器进行访问(这里打开的是虚拟机中的浏览器,主机的不知道为什么不能访问?):
12) 使用 Redis 的测试工具进行测试
/usr/local/redis/bin/redis-benchmark -h 192.168.175.128 -p 6379 -a abeam. -c 1000 -d 10 -n 10000
/usr/local/redis/bin/redis-benchmark -h 192.168.175.128 -p 6380 -a abeam. -c 1000 -d 10 -n 10000
/usr/local/redis/bin/redis-benchmark -h 192.168.175.128 -p 6381 -a abeam. -c 1000 -d 10 -n 10000