事务是指一系列操作步骤,这一系列的操作步骤,要么完全执行,要么完全地不执行
Redis中的事务是一组命令的集合,至少是两个或两个以上的命令,redis事务保证这些命令被执行时中间不会被任何操作打断
(1)multi标记一个事务的开始,事务内的多条命令会按照先后顺序被放入一个队列中,返回值总是ok
(2)exec执行所有事务内的命令,返回事务内的所有执行语句内容,事务被打断返回nil,如果其中一条事务语法错误,则无法执行事务(任意一条),会完全放弃该事务内的任意命令。
另一个错误是语法没有错误,但执行出错,不报错的事务会执行成功,执行错误的命令报错(因为没有回滚机制)
(3)discard取消事务,放弃执行事务块的所有命令,返回值综述ok
(4)watch监视该值的改变
redis的watch机制:使用watch监视一个或多个key,跟踪key的value修改情况,如果有key的value值在事务Exec执行之前被修改了,整个事务被取消。Exec返回提示信息,表示事务已经失败。
监视后,发现age的值已经被改动,所以放弃当前的事务。注意,redis同一时间只操作一个key
这事实上就是乐观锁的实现机制
(4)持久化,即存储将数据存储到一个不会丢失的地方,如果把数据放到内存中,非常容易丢失,所以放在内存中的数据不是持久化,而放到磁盘就算一种持久化,Redis提供两种机制对数据进行持久化存储,便于发生故障后能迅速回复数据(AOF和RDB)
=================================
Redis Database(RDB)指定的时间间隔将内存中的数据写到磁盘,数据恢复时将快照文件读到内存中。
RDB保存了某个时间点的全部数据集,存储在一个二进制文件中,只有一个文件,默认是dump.rdb。RDB技术非常适合做备份,可以保存最近一个小时,一天,一个月的全部数据。保存数据是在单独的进程中写文件,不影响redis的正常使用。RDB回复数据时比其它AOP速度更快
RDB方式的数据持久化,仅需在redis.conf文件中配置即可,默认配置是启用的。在配置文件redis.conf中搜索SNAPSHOTTING,查找在注释开始和结束之间的关于RDB的配置说明。配SNAPSHOTTING地方有三处。
①配置执行RDB生成快照文件的时间策略,对Redis进行设置,让它在“N秒内数据集至少有M个key改动”这一条件被满足时,自动保存一次数据集。
配置格式:save seconds change
save 900 1
save 300 10
save 60 100000
这三个策略是可以同时触发的
②dbfilename:设置RDB的文件名,默认文件名为dump.rdb
③dir:指定RDB文件的存储位置,默认是当前目录
RDB的缺点就是,其会丢失数据,一旦没有满足触发策略容易发生数据丢失
=================================
Append-only File(AOF),Redis每次接收到一条改变数据的命令时,它将把该命令写到一个AOF文件中(只记录命令,是一个文本文件,可以修改),当Redis重新启动时,它通过执行AOF文件中的所有命令来恢复数据。
AOF方式的数据持久化,在redis.conf文件中配置即可:
①appendonly:默认是no,改成yes,即开启aof持久化
②appendfilename:指定AOF文件名,默认文件名为appendonly.aof
③dir:指定RDB和AOF文件存放的目录,默认是
④appendfsync:配置向aof文件写命令数据的策略:
no:不主动进行同步操作,而是完全交给操作系统来做(即每30秒一次),比较快但不是很安全
always:每次执行写入都会执行同步,慢但是安全
everysec:每秒执行一次同步操作,慢一些但是比较安全
⑤auto-aof-rewrite-min-size:允许重写的最小AOF文件大小,默认是64M。当aof文件大于64M时,开始整理aof文件,去掉无用的操作命令,缩小aof文件。
(5)redis服务器的主从复制
为了避免单点故障,我们需要将数据复制多份部署在多台不同的服务器上,即使有一台服务器出现故障,其他服务器依然可以继续提供服务。
这就要求当一台服务器上的数据更新后,自动将更新的数据同步到其它服务器上,那该怎么实现?Redis主从复制
主master负责数据的修改操作,从redis全部负责数据的读操作。读写分离可以降低服务器压力。
通过启动多个redis-server可以模拟主从复制结构。
Redis主从复制实现(master/salve)
方式1:修改配置文件,启动时,服务器读取配置文件,并自动称为指定服务器的从服务器,从而构成主从复制关系
新建三个redis的配置文件
如果redis启动,先停止
作为Master的redis端口是6380
作为Slaver的redis端口分别是6382,6384
从原有的redis.conf拷贝三份,分别命名为redis6380.conf,redis6382.conf,redis6384.conf。
复制这几个就是为了在一台机子上启动多个redis server
编辑Master配置文件
redis6380.conf在空文件中加入如下内容:
include /usr/local/redis-3.2.9/redis.conf
包含原来的配置文件的内容,将redis.conf加入到当前配置文件
daemonize yes
表示redis是后台启动
port 6380
当前redis的端口号
pidfile /var/run/redis_6380.pid
linux运行程序的唯一标识,需要一个位置存储唯一的表示路径
logfile 6380.log
设置日志文件位置
dbfilename dump6380.rdb
rdb存储的位置
编辑Slave配置文件
redis6382.conf和redis6384.conf在空文件中加入如下内容:
include /usr/local/redis-3.2.9/redis.conf
daemonize yes
port 6382
pidfile /var/run/redis_6382.pid
logfile 6382.log
dbfilename dump6382.rdb
slaveof 127.0.0.1 6380
设置主master地址
===================================
./redis-cli -p 6380
Master服务器的客户端
info replication
显示服务器的关系信息
同样,连接到6382,显示的是up
在主服务器上添加key和val,主从都会显示。从服务器只能读不能写。
当Master服务出现故障,需要手动将slave中的一个提升为master,剩下的slave挂至新的master上
命令:
①:slaveof no one
将一台slave服务器提升为Master
②:slaveof 127.0.0.1 6381
方式二:./redis-server --slaveof master-ip master-port在启动redis时指定当前服务成为某个主redis服务的从Slave
(6)哨兵系统
可自动化的处理故障
- 监控:Sentinel不断的检查主服务和从服务是否按照预期正常工作
- 提醒:被监控的redis出现问题时,Sentinel会通知管理员或其它应用程序
- 自动故障转移:监控的主redis不能正常工作,Sentinel会开始进行故障迁移操作。就是将从服务器提升为主服务器,其它服务器挂到新主服务器之上。
- 每个哨兵(Sentinel)独立运行,可以进行通讯,并交换监控的结果。哨兵通过心跳机制来检查主从服务器是否正常。哨兵的个数必须是奇数,从而投票觉得当前主服务器是否运行正常。
安装完redis,哨兵就已经存在,redis-sentinel。我们在一台机子上模拟三个哨兵系统,复制三份sentinel.conf文件:
Sentinel系统默认port是26379。三个配置port分别设置为26380,26382,26384。三个文件分别命名:
- sentinel26380.conf
- sentinel26382.conf
- sentinel26384.conf
三个sentinel配置文件修改:
1、修改port 26380 port 26382 port 26384
2、修改sentinel monitor mymaster 127.0.0.1 6380 2
格式:sentinel monitor name masterIp masterPort Quorum投票数
修改之后运行哨兵系统
一旦主redis关闭,会自动转化主redis
此外,如果新启动了一个服务器并且配置哨兵,会自动添加到从服务器之中
(7)安全设置
访问redis默认是没有密码的。要设置redis访问密码,修改redis.conf中requirepass 密码。因为redis速度很快,所以在一台比较好的 服务器下,一个外部用户可以1s进行150k次密码尝试,需要指定非常非常强大的密码来防止暴力破解。
开启访问密码设置
修改redis.conf,找到requirepass
只要改了配置文件就重新加载
两种密码的使用方式:
其次,redis可以绑定ip,修改redis.conf文件,把#bind 127.0.0.1前面的注释#号去掉,然后把127.0.0.1改成允许访问你的redis服务器的ip地址,表示只允许该ip进行访问。多个ip使用空格分隔
最后,修改redis的端口是很重要的,使用默认端口非常危险,redis.conf中修改port6379,将其修改为自己指定的端口,端口1024以内是保留给操作系统,用户可以使用1024-65535
(8)Jedis操作Redis
Jedis有线程不安全的问题,一般跟commons-pool(线程池)一起使用。
package com.fty;
import redis.clients.jedis.Jedis;
import java.util.List;
public class RedisString {
public static void main(String[] args) {
/**
* 1、修改redis.conf,启动redis需要指定redis.conf的位置
* 2、关闭linux防火墙,或者让redis的端口号通过防火墙 systemctl statsu firewalld
*/
//创建Jredis对象,指定连接的redis服务器的ip端口
Jedis jedis = new Jedis("127.0.0.1", 6379);
// jedis.auth("密码");
//调用Jedis对象的方法操作Redis数据
jedis.set("break", "豆浆和油条");
//获取key的值
String value = jedis.get("break");
System.out.println(value);
//mset一次创建多个key-value
jedis.mset("lunch","红烧肉盖饭", "dinner", "牛排");
//获取多个key对应的值mget
List<String> values = jedis.mget("break", "lunch", "dinner");
for(String val : values) {
System.out.println(val);
}
}
}
使用Jedis Pool
package com.fty;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
public class RedisUtils {
private static JedisPool pool;
//创建JedisPool对象
public static JedisPool open(String ip, int port) {
if(pool == null) {
//创建JedisPool
//创建JedisPoolConfig,给config设置连接池的参数,使用config对象去创建JedisPool
JedisPoolConfig config = new JedisPoolConfig();
//给config设置连接池的参数
config.setMaxTotal(10);//设置最大的线程数,一个线程就是一个Jedis对象
config.setMaxIdle(2);//设置最大空闲数
config.setTestOnBorrow(true);//设置检查项为true,标识线程池中获取的对象一定是经过检查可用的
/**
* poolConfig 配置器
* host:redis所在的ip
* port:redis的端口
* timeout:连接redis的超时事件
* password:redis访问密码
*/
pool = new JedisPool(config, "localhost", 6379, 6000, "密码");//创建Pool对象
}
return pool;
}
//关闭pool对象
public static void close() {
if(pool != null) {
pool.close();
}
}
public static void main(String[] args) {
//从JedisPool中获取JedisPool对象
JedisPool pool = null;
Jedis jedis = null;
try {
pool = open("localhost", 6379);
jedis = pool.getResource();
/**
* 拿到Jedis后就能进行set 和 get
*/
} catch (Exception e) {
e.printStackTrace();
} finally {
//关闭Jedis对象,从Pool中获取的Jedis放回到Pool,共其它请求使用
if(jedis != null) {
jedis.close();//放回池中
}
}
}
}