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 并设置密码,如图:

clip_image002[4]

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 就需要输入密码授权了,例如:

clip_image003[4]

7)   也可以在登录 redis-cli 时同时指定密码,例如:

clip_image005[4]

但是出现了一个警告,意思是使用 -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

clip_image006[4]

2.   指定 master 的请求密码,搜索/masterauth

clip_image007[4]

 

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 命令,主机信息:

clip_image009[4]

2.   输入 info 或者 info replication 命令,从机信息:

clip_image010[4]

 

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 是对整个连接有效的,事务也一样。如果连接断开,监视和事务都会被自动清除。execdiscardunwatch 命令都会清除连接中的所有监视。

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秒内如果超过1key被修改,则发起快照保存

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 文件

clip_image012[4]

5)   查看文件内容

clip_image013[4]

 

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个消息 tv1tv2

127.0.0.1:6379> subscribe tv1 tv2   #订阅 tv1tv2 的消息通道

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.confredis-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.

clip_image015[4]

执行"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.

clip_image017[4]

 

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

打开浏览器进行访问(这里打开的是虚拟机中的浏览器,主机的不知道为什么不能访问?):

clip_image019[4]

 

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

clip_image021[4]

posted @ 2021-05-01 11:30  Abeam  阅读(368)  评论(0编辑  收藏  举报