开始时间:2022-03-25
课程链接:Redis实战精讲
Redis配置文件
Redis的安装根目录下(/opt/redis-5.0.2),Redis在启动时会加载这个配置文件,在运行时按照配置进行工作。 这个文件有时候我们会拿出来,单独存放在某一个位置,启动的时候必须明确指定使用哪个配置文件,此文件才会生效。
Redis 的网络相关配置
- bind:绑定IP地址,其它机器可以通过此IP访问Redis,默认绑定127.0.0.1,也可以修改为本机的IP地址。
- port:配置Redis占用的端口,默认是6379。
- tcp-keepalive:TCP连接保活策略,可以通过tcp-keepalive配置项来进行设置,单位为秒,假如设置为60秒,则server端会每60秒向连接空闲的客户端发起一次ACK请求,以检查客户端是否已经挂掉,对于无响应的客户端则会关闭其连接。如果设置为0,则不会进行保活检测。
进入redis.conf文件
我们的ip是192.168.91.128
因此修改bind后面的默认值
同时修改端口号6380
[root@localhost redis-5.0.2]# redis-cli -h 192.168.91.128 -p 6380
192.168.91.128:6380>
[root@localhost redis-5.0.2]# redis-cli -h 192.168.91.128 -p 6380 shutdown
常规配置:
loglevel:配置日志级别,开发阶段配置debug,上线阶段配置notice或者warning.
logfile:指定日志文件。redis在运行过程中,会输出一些日志信息;默认情况下,这些日志信息会输出到控制台;我们可以使用logfile配置日志文件,使redis把日志信息输出到指定文件中。
databases:配置redis服务默认创建的数据库实例个数,默认值是16。
在vim的命令行模式下 输入
:/ 想要搜的文件名
可以实现类似ctrl+F的功能
指定日志文件名字
安全配置
为了高效性,默认不配置密码
requirepass:配置Redis的访问密码。默认不配置密码,即访问不需要密码验证。此配置项需要在protected-mode=yes时起作用。使用密码登录客户端:redis-cli -h ip -p 6379 -a pwd
Redis持久化
redis是内存数据库,它把数据存储在内存中,这样在加快读取速度的同时也对数据安全性产生了新的问题,即当redis所在服务器发生宕机后,redis数据库里的所有数据将会全部丢失。为了解决这个问题,redis提供了持久化功能——RDB和AOF(Append Only File)
在适当的时机采用适当手段把内存中的数据持久化到磁盘中,每次redis服务启动时,都可以把磁盘上的数据再次加载内存中使用。
RDB
RDB(Redis DataBase)是 Redis 默认的持久化方案。在指定的时间间隔内,执行指定次数的写操作,则会将内存中的数据写入到磁盘中。即在指定目录下生成一个dump.rdb文件。Redis重启会通过加载dump.rdb文件来恢复数据。
原理:Redis会复制一个与当前进程一样的进程。
新进程的所有数据(变量、环境变量、程序计数器等)数值都和原进程一致,但是是一个全新的进程,并作为原进程的子进程,来进行持久化。
整个过程中,主进程是不进行任何IO操作的,这就确保了极高的性能。
如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那RDB方式要比AOF方式更加的高效。RDB的缺点是最后一次持久化后的数据可能丢失。
RDB保存的文件是dump.rdb文件 ,位置保存在Redis的启动目录。Redis每次同步数据到磁盘都会生成一个dump.rdb文件,新的dump.rdb会覆盖旧的dump.rdb文件。
配置RDB 持久化策略
save <seconds> <changes>:配置持久化策略
dbfilename:配置redis RDB持久化数据存储的文件
dir: 配置redis RDB持久化文件所在目录
save <seconds> <changes>:
配置复合的快照触发条件,即Redis 在seconds秒内key改变changes次,Redis把快照内的数据保存到磁盘中一次。默认的策略是:
1分钟内改变了1万次
或者5分钟内改变了10次
或者15分钟内改变了1次
如果要禁用Redis的持久化功能,则把所有的save配置都注释掉。
但他有不足,就是比如刚触发完了我的一次持久化,我再添加一些数据,很可能三个条件都不满足,那就会造成数据丢失
不过一般redis里面放的都是频繁访问的数据
会存放到mysql里面
AOF
AOF(Append Only File)
采用操作日志来记录进行每一次写操作,每次redis服务启动时,都会重新执行一遍操作日志中的指令。记录的是改数据的所有操作,而不是记录数据
如果宕机了,那就重新执行这些操作,
效率低下,redis默认不开启AOF功能。
appendonly:配置是否开启AOF策略
appendfilename:配置操作日志文件
根据数据的特点决定开启哪种持久化策略;
一般情况,开启RDB足够了。
Redis事务
事务:把一组数据库命令放在一起执行,保证操作原子性,要么同时成功,要么同时失败。
Redis的事务:允许把一组redis命令放在一起,把命令进行序列化(按照命令队列依次执行),然后一起执行,保证部分原子性。
分为压入报错【原子性】 执行报错【不保证原子性】
multi标记事务开始 exec标记事务结束
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set k1 v1
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> set k3 v3
QUEUED
127.0.0.1:6379> exec
1) OK
2) OK
3) OK
redis的事务只能保证部分原子性:
a)如果一组命令中,有在压入事务队列过程中发生错误的命令,则本事务中所有的命令都不执行,能够保证事务的原子性。
multi
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set kk vv
QUEUED
127.0.0.1:6379> seta kk2 vv2
(error) ERR unknown command `seta`, with args beginning with: `kk2`, `vv2`,
127.0.0.1:6379> exec
(error) EXECABORT Transaction discarded because of previous errors.
如果一组命令中,在压入队列过程中正常,但是在执行事务队列命令时发生了错误,则只会影响发生错误的命令,不会影响其它命令的执行,不能够保证事务的原子性。
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set k3 v3
QUEUED
127.0.0.1:6379> incr k1
QUEUED
127.0.0.1:6379> set k4 v4
QUEUED
127.0.0.1:6379> exec
1) OK
2) (error) ERR value is not an integer or out of range
3) OK
压入队列不报错,执行的时候报错,这个时候就不满足原子性
discard:清除所有已经压入队列中的命令,并且结束整个事务。
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set kk3 32
QUEUED
127.0.0.1:6379> discard
OK
事务案例
银行卡同时取钱问题
设置一个版本号
id balance version
update table set balance=balance-dept,version=version+1
where id=xxxx and version=100
看一个例子
127.0.0.1:6379> set balance 100
OK
127.0.0.1:6379> set balance2 1000
OK
127.0.0.1:6379> set version 1
OK
127.0.0.1:6379> watch version
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> decrby balance 50
QUEUED
127.0.0.1:6379> incrby balance2 50
QUEUED
127.0.0.1:6379> incr version
QUEUED
已经排好队了,这个时候我们用watch监控了version,一旦外部让version产生了变化,那么整个事务都不执行
我们再开启一个xshell
127.0.0.1:6379> incrby version
(error) ERR wrong number of arguments for 'incrby' command
127.0.0.1:6379> incr version
(integer) 2
此时改变了version的值
127.0.0.1:6379> exec
(nil)
同理,可以放弃监控
使用
unwatch
放弃所有的监控,要在添加监控只能重新加
事务小结
- 单独的隔离操作:事务中的所有命令都会序列化、顺序地执行。事务在执行过程中,不会被其它客户端发来的命令请求所打断,除非使用watch命令监控某些键。
- 不保证事务的原子性:redis同一个事务中如果一条命令执行失败,其后的命令仍然可能会被执行,redis的事务没有回滚。Redis已经在系统内部进行功能简化,这样可以确保更快的运行速度,因为Redis不需要事务回滚的能力。
Redis消息的订阅与发布
图一:消息订阅者(client2 、 client5 和 client1)订阅频道 channel1
图二:消息发布者发布消息到频道channel1,会被发送到三个订阅者:
比如我订阅频道ch1和ch2
127.0.0.1:6379> subscribe ch1 ch2
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "ch1"
3) (integer) 1
1) "subscribe"
2) "ch2"
3) (integer) 2
订阅后这条路就一直在收听状态
我们再开一个xshell,使用publish进行发布
127.0.0.1:6379> publish ch2 nihaoma
(integer) 1
127.0.0.1:6379> publish ch1 wohenhao
这里就会实时收听
1) "message"
2) "ch2"
3) "nihaoma"
1) "message"
2) "ch1"
3) "wohenhao"
psubscribe pattern [pattern]
功能:订阅一个或多个符合给定模式的频道。模式以 * 作为通配符,例如:news.* 匹配所有以 news. 开头的频道。
返回值:订阅的信息。
可以根据这个做出消息队列
Redis主从复制
主从复制
主机数据更新后根据配置和策略,自动同步到从机的master/slave机制,Master主机以写为主,Slave从库以读为主。
主少从多、主写从读、读写分离、主写同步复制到从。
一主二从原理
- 配从(库)不配主(库)
- 配从(库): slaveof 主库IP 主库端口
- 主写从读、读写分离
- 从连前后同
- 主断从待命、从断重新连
搭建三台redis服务:使用一个redis模拟三台redis服务
提供三分redis配置文件:redis6379.conf、redis6380.conf、redis6381.conf
修改
先使用
cp redis.conf redis6379.conf
cp redis.conf redis6380.conf
cp redis.conf redis6381.conf
然后修改该文件,6379.conf里面的
bind 127.0.0.1
port 6379
logfile "6379.log"
dbfilename dump6379.rdb
pidfile /var/run/redis_6379.pid
同理,按照端口号配置另外两个文件
分别使用三个redis配置文件,启动三个redis服务:
redis-server redis6379.conf &
redis-server redis6380.conf &
redis-server redis6381.conf &
在三个窗口启动三台redis服务
在对应的窗口链接对应服务器
redis-cli -h 127.0.0.1 -p 6379
redis-cli -h 127.0.0.1 -p 6380
redis-cli -h 127.0.0.1 -p 6381
查看主从关系
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:0
默认情况下,所有的redis服务都是主机,即都能写和读,但是都还没有从机。
在6380和6381设置为从机
127.0.0.1:6380> slaveof 127.0.0.1 6379
OK
127.0.0.1:6380> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6379
回来看6379,有两个从机了
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=6380,state=online,offset=70,lag=1
slave1:ip=127.0.0.1,port=6381,state=online,offset=70,lag=1
主机上设置一个值
127.0.0.1:6379> set k1 v1
OK
从机就能同步了,已有的同步过去了
这个叫全量复制
现添的数据,也能同步,这个叫增量复制
127.0.0.1:6380> get k1
"v1"
127.0.0.1:6381> get k1
"v1"
从机就不能写数据了
这个叫做主写从读,读写分离
127.0.0.1:6381> set k2 v2
(error) READONLY You can't write against a read only replica.
主机宕机,从机待命
关闭6379服务:redis-cli -h 127.0.0.1 -p 6379 shutdown
在从机上看
127.0.0.1:6380> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6379
master_link_status:down
连接状态为down
依然还能读
此时重启6379
主机恢复,一切正常
[root@localhost redis-5.0.2]# redis-server redis6379.conf &
6380就恢复了
127.0.0.1:6380> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6379
master_link_status:up
从机宕机
6380关机了
此时6379就只有一个从机了
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:1
slave0:ip=127.0.0.1,port=6381,state=online,offset=98,lag=1
从机恢复
[root@localhost redis-5.0.2]# redis-server redis6380.conf &
[1] 6022
[root@localhost redis-5.0.2]# redis-cli -h 127.0.0.1 -p 6380
127.0.0.1:6380>
此时从机6380自己当老大了
127.0.0.1:6380> info replication
# Replication
role:master
主机6379就没有这个小弟了
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:1
slave0:ip=127.0.0.1,port=6381,state=online,offset=224,lag=1
从机上位
当6379关机后
6380设置
127.0.0.1:6380> slaveof no one
OK
自己当老大了,然后让6381连6380,重新设置主从关系就行
那6379此时恢复了怎么办?
已经是孤家寡人,光杆司令了
那可以让6380重新隶属于6379
此时的关系是6379下面一个slave6380,而6380下面一个6381,6381并没有直接属于6379
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:1
127.0.0.1:6380> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6379
master_link_status:up
master_last_io_seconds_ago:6
master_sync_in_progress:0
slave_repl_offset:0
slave_priority:100
slave_read_only:1
connected_slaves:1
127.0.0.1:6381> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6380
master_link_status:up
主机的数据是可以同步到从机和从机的从机上,但这个时候6380虽然名义上是6381的主机,但是6380已经没有写的权限了
小结
一台主机配置多台从机,一台从机又可以配置多台从机,从而形成一个庞大的集群架构。
减轻一台主机的压力,但是增加了服务间的延迟时间。
哨兵模式
从机上位的自动版。
Redis提供了哨兵的命令,哨兵命令是一个独立的进程,哨兵通过发送命令,来监控主从服务器的运行状态,如果检测到master故障了根据投票数自动将某一个slave转换master,然后通过消息订阅模式通知其它slave,让它们切换主机。
然而,一个哨兵进程对Redis服务器进行监控,可能会出现问题,为此,我们可以使用多哨兵进行监控。
搭建哨兵模式
提供哨兵配置文件:
在redis安装目下创建配置文件:redis_sentinel.conf
创建redis_sentinel.conf文件,编辑内容,表示:指定监控主机的ip地址,port端口,得到哨兵的投票数(当哨兵投票数大于或者等于此数时切换主从关系)。
sentinel monitor dc-redis 127.0.0.1 6379 1
启动哨兵服务:
[root@localhost redis-5.0.2]# redis-sentinel redis_sentinel.conf
等6379关机后
投票选举继承人
选中了6381->上位啦!
原主机恢复,启动6379,变为了6381的小弟
[root@localhost redis-5.0.2]# redis-cli -h 127.0.0.1 -p 6379
127.0.0.1:6379> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6381
master_link_status:up
Jedis操作Redis
使用Redis官方推荐的Jedis,在java应用中操作Redis。Jedis几乎涵盖了Redis的所有命令。操作Redis的命令在Jedis中以方法的形式出现。
建立一个普通的maven web工程
然后添加依赖
<!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.1.0</version>
</dependency>
测试之前要先把redis里面的bind修改一下
进入redis6379.conf文件
将bind修改为本机ip 192.168.113.128(注意,这里本机ip不是192.168.91.128了,我不知道为什么我一顿骚操作后ip变了,反正变了就以变了后为主)
启动6379
[root@localhost redis-5.0.2]# redis-server redis6379.conf &
[1] 3749
[root@localhost redis-5.0.2]# redis-cli -h 192.168.113.128 -p 6379
192.168.113.128:6379> set k1 v1
OK
192.168.113.128:6379> set k2 v2
OK
192.168.113.128:6379> set k3 v3
并给redis设置三个键值对k1 k2 k3
此时在idea里面写代码
package BUPT;
import redis.clients.jedis.Jedis;
import java.util.Set;
public class JedisKeyTest {
public static void main(String[] args) {
Jedis jedis = new Jedis("192.168.113.128", 6379);
String res = jedis.ping();
//返回pong表示正常
System.out.println(res);
Set<String> keys = jedis.keys("*");
for (String key : keys
) {
System.out.println(key);
}
}
}
注意:连接时一定要关闭防火墙!!
[root@localhost redis-5.0.2]# systemctl stop firewalld
查看返回值
PONG
k3
k1
k2
基本上命令还是以前redis的命令,只是现在这些命令变成了jedis对象的方法了
jedis敲事务
package BUPT;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Transaction;
public class JedisKeyTest {
public static void main(String[] args) {
Jedis jedis = new Jedis("192.168.113.128", 6379);
String res = jedis.ping();
//返回pong表示正常
System.out.println(res);
Transaction tran = jedis.multi();
tran.set("k6", "v6");
tran.set("k7", "v7");
tran.set("k8", "v8");
tran.exec();
}
}
可视化工具
redis-desktop-manager
无脑安装,点进来就是
输入几个参数,测试能否连接
结束时间:2022-03-29