Redis:一个NoSql数据库,No====》not only,常常用作缓存使用
redis的数据类型 string hash set zset list
reids:是一个中间件,是一个独立的服务器
java中比较有名的客户端 Jedis , lettuce ,Redisson
spring,SpringBoot 中有一个RedisTemplate(StringRedisTemplate)处理和redis交互
redis-server.exe :服务端,启动后不要关闭
redis-cli.exe: 客户端,访问redis中的数据
Springboot中 RedisTemplate使用的是 lettuce 这个客户端库
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
我们使用的是 RedisTemplate,但是底层使用的是 lettuce这个客户端和redis进行交互
RedisTemplate 泛型的三种情况
1.RedisTemplate redisTemplate; //都不写
2.RedisTemplate<String,String> redisTemplate; //都是String
3.RedisTemplate<Object,Object> redisTemplate; //都是Object
StringRedisTemplate和RedisTemplate的区别
StringRedisTemplate是把k和v都作为String处理,使用的是String的序列化,可读性好
RedisTemplate把k和v经过序列化后存储到redis,可读性不好,默认使用jdk的序列化
序列化:把对象转换为可传输的字节序列过程称为序列化
反序列化:把字节序列还原为对象的过程称为反序列化
可以设置redisTemplate的序列化方式
@PostMapping("/redis/setSerial")
public String setSerial(@RequestParam("key") String k, @RequestParam("value") String v){
redisTemplate.setKeySerializer(new StringRedisSerializer());//设置key的序列化方式为String序列化
redisTemplate.setValueSerializer(new StringRedisSerializer());//设置value的序列化方式为String序列化 ,在获取redis中的值时,redisTemplate会自动使用 设置的序列化方式 返回数据,比如说 设置的value的序列化方式为json序列化,则取出来的对象也是 将json数据反序列化后的对象
redisTemplate.opsForValue().set(k,v);
return "通过redis-cli查看设置后的结果";
}
需要查看setKeySerializer这个方法的参数,是一个接口,ctrl+H,查看接口的实现类即可。
IDEA中生产序列化版本号的方法
使用 json 序列化方式
@PostMapping("/redis/getUser")
public User getUser(){
User user = new User();
user.setId(1001);
user.setName("zhangsan");
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer(User.class));//json序列化方式
redisTemplate.opsForValue().set("student",user);
Object student = redisTemplate.opsForValue().get("student");
System.out.println(student); //这里的student是普通的java对象
return user;
}
redis.cn 中文官网
tar -zxvf redis.tar.gz 解压压缩包 tar -zxvf redis.tar.gz -C /usr/local
yum -y install gcc 安装gcc
在redis目录下的src目录下,执行make 编译源代码,执行完后 make install,这样在任何目录下都可以执行
./redis-server 前台启动 后台启动方式 ./redis-server &
ps -ef | grep redis 可以查看进程
1. ./redis-cli shutdown ,可以关闭 redis-server 服务 或者先 ./redis-cli 启动客户端后,再在客户端输入 shutdown 关闭redis-server服务
2. ps -ef | grep redis ,第二列是 redis服务的进程号,使用 kill -9 进程号
使用redis客户端,连接其它的redis服务器 ./redis-cli -h 127.0.0.1【这是其它redis的ip】 -p 6379【这是其他redis的端口号】
redis 默认是只能在安装的机器上访问,若想其他网络能访问到redis服务,必须修改redis.conf配置文件 ,修改内容 1. bind 127.0.0.1 ,把这一行 注释掉,这一行是限制只有 127.0.0.1才能访问redis, 2. protected-mode yes ,这里需要把 yes 修改为 no ,这样修改以后,启动redis-server服务的时候需要这样的命令 redis/src 目录下执行 ./redis-server ../redis.conf & ,使用redis.conf配置文件,后台启动 redis-server 服务 ; 还需要检查防火墙的状态 使用命令是
systemctl status firewalld ,查看 是否关闭的
redis.conf 配置文件中 databases 16 表示
redis 默认是16个库,默认使用第0个库 db0-----db15,可以根据需要修改库的个数
redis的常用操作命令
1. 客户端输入 ping 返回 PONG,说明redis正常使用
2 。 dbsize 表示当前库中的保存的key的数量
3. select 数字【0-16】 表示使用哪个库
4. flushdb 表示清空当前库中的数据,对其他库没有影响
5. exit 退出 客户端,此时服务端还在运行中,使用 shutdown 可以关闭服务端
redis 操作key 常用的命令
1. keys pattern
keys * * 表示0个或多个字符 ,生成环境尽量不要用 *,redis是单线程的,
keys w?ord ? 表示单个字符
2, exists key [key] 检查key是否存在
exists k1 k2 k3 k4 k5 ,返回 库中存在的 总数量
3. expire key seconds 设置key的生存时间,超过时间,自动删除,时间单位是秒,设置成功返回1,设置失败返回0
expire k1 5 返回1 expire kcdkdk 5 返回0,因为库中不存在这个key
4. ttl key 以秒为单位,返回 key的剩余生存时间
返回值 -1 ,没有设置key的生存时间,key永不过期
-2, key不存在
数字,key的剩余时间,单位为秒
5 type key ,打印出key对应的value的类型, 5种类型,string list set zset hash
6 del key [key] ,删除key
reids的5种数据类型
1.字符串类型 常用操作命令
set k1 v1 set k2 v2
get k1 get k2
incr key ,把key对应的value的值加1 ,如果key不存在,则创建key的value为0,再执行+1操作,对key的操作是原子行的,
decr key, 把key对应的value的值减1,如果key不存在,则创建key的value为0,再执行-1操作,
append key value,把value追加到key对应的value的后面,如果key不存在则等价于 set key value
strlen key, 返回key对应的value的长度
getrange key 2 5 2和5指的是 value字符串的下标,两个都包含在内
如 set k1 abcdefghijklmn 则 getrange k1 2 5 得到的是 cdef
-1 代表 value的最后一个字符,如 getrange k1 -4 -1 得到的是 klmn
获取全部长度的值 使用 getrange k1 0 -1 等价于 get k1
setrange k1 5 tom 把k1对应的value从第5个字符开始替换3个字符为tom
mset k1 v1 k2 v2 k3 v3 ,一次创建多个key和value
mget k1 k2 k3,一次获取多个key的值
hash类型的操作
hset key field value ,如 hset kk k1 v1 和 hset kk k2 v2
hget key field 获取 指定field对应的value
hmset key field value field value field value ,一次设置key对应的多个field和value
hmget key field field field ,一次获取key下的多个 field对应的value
hgetall key ,获取key中的所有的field和value,显示的是 field和value
hdel key field field ,一次删除key下的一个或多个field
hkeys key ,获取key中所有的field
hvals key 获取key中所有的value
hexists key field, 检测 field是否在key中
list类型的操作
lpush 左侧添加 lpush key value1 value2 value3 前面的value会插入到最后面,后面的value会插入到左侧的头部
rpush 右侧添加 rpush mylist2 a b c ,则是前面的a会插入到尾部,b再插入到尾部,c再插入到尾部,最后c在最后面 再执行 rpush mylist2 d e f g, 则最后面的是g
lrange key start stop 如 lrange mylist2 2 4 取出来的是 c d e start和stop是包含在内的了,-1表示最后一个元素 如 lrange mylist2 -4 -1 ,或者 lrange mylist2 3 -1 ,取出来的都是 defg
lrange mylist2 0 -1 取出列表中的所有数据
lindex key index ,取出 key中下标为index的元素
llen key , 取出 key中的元素个数
lrem key count value , 删除列表中与value相等的元素,count>0时,从左侧查找count个value删除掉,count<0时,从右侧查找count个value删除掉,count=0时,把列表中所有与value相等的都删除掉 如
rpush course c c++ java php c java mysql oracle java c php java c
执行 lrem course 2 c ,从左侧查询c,删除2个
执行 lrem course -2 java,从右侧查询java,删除2个
执行 lrem course 0 php ,删除列表中所有的 php
lset key index value ,设置key的第index位的value为 新的value
如 lset course 2 SPRING
linsert key before|after privo value ,查找key对应的列表中privo,在它的前面或者后面插入value
如 rpush kk a b c d e f g h i ,执行 lrange kk 0 -1 ,查询kk中保存的全部数据是abcdefghi,然后
执行 linsert kk before e AAA,则会把AAA插入到e的前面,如果before换成after就是在e的后面插入AAA
set类型的操作
sadd key member [member] ,添加新的成员到集合key中去
sadd k1 m1 m2 m3 m4
smembers key ,显示key中的所有的成员 smembers k1
sismember key member ,判断 member是否在key对应的value的set集合中 sismember k1 m2
scard key ,计算key对应的set集合中的元素的个数
srem key member [member] ,删除 key对应的value集合中的member
srandmember key [count], 从key对应的value集合中,随机取出count个元素,若count>0,则取出的元素不会重复,count<0,表示取出的元素可能会重复。集合中的数据不会减少。count默认为1.
spop key [count] ,随机从key对应的value集合中,删除count个元素
zset集合的操作
zadd key score member [score member] [score member] ,score是分数,代表在zset中的顺序,score是可以重复的 ,score 也可以有小数点,score代表 元素的顺序,score相等的元素,根据元素的ascii码确定前后顺序
zadd scores 20 a 30 b 40 c 99 d 80 e 60 f
zrange key start end [withscores] ,由于zset是排序的,可以根据下表获取数据 -1,代表最后一个元素 zrange scores 0 -1 , 显示所有的 元素,
zrevrange key start end [withscores] ,根据score从大到小的顺序显示
zrem key member [member] , 删除元素
zcard key , 返回元素的个数
redis的事务
这里的事务是指,redis控制台的输入命令组成的2个及2个以上的命令的组合,redis事务是没有回滚的
开启事务 ,使用 multi ,提交事务 使用 exec
如 1 multi 2 set username zhangsan 3 get username 4 lindex mylist 1 3 4【这个命令后面只能跟一个数字】 5 set username wangwu 6 get username 7 exec
这样的话,redis会检测到命令4有语法错误,直接终止redis事务的运行,
如 1 multi 2 set username zhangsan 3 get username 4 lindex username 1 【这里username是字符串类型的,导致这条语句报错,但是不会影响 其他命令的执行】 5 set username wangwu 6 get username 7 exec ,最终username保存的是 wangwu,redis认为,语法没有错误,则所有的命令都可以正常执行,
discard ,主动放弃 事务内的命令
如 1 set age 10 2 multi 开启事务 3 set age 20 4 set age 30 5 discard。最终结果 age还是10
redis持久化方式
rdb方式 Redis Database
在指定的时间间隔内,将内存中的数据集快照写入到磁盘中(二进制文件) ,文件名字为 dump.rdb(二进制文件)
# save "" 如果把#号去掉,下面的三行save也去掉,表示关闭rdb的方式
save 900 1 900秒内有一个key被改动
save 300 10 300秒内有10个key的值被改动
save 60 10000 60秒内有10000个key的值被改动
任意一条满足就保存
dbfilename dump.rdb 保存的文件名 redis启动的时候会从这个文件内读取数据,将key和value回复到redis中去
保存的目录 dir ./
rdb方式的缺点: 有可能会丢失数据,如果恰巧在redis服务挂掉的时候,redis新修改了key,但是没达到保存的条件,此时的数据就会发生丢失
AOF方式 append only file (此种方式保存的数据比较全)
redis每次接受到一条改变数据的命令时,它将把接收的命令写入到AOF文件中,只记录写操作,不记录读操作,当redis重启时,它通过执行AOF文件中的命令来回复数据
AOF默认不开启,需要手动开启,修改redis.conf 配置文件
1. appendonly no ,需要把这里的no 改成yes,这就开启了AOF方式
2. appendfilename "appendonly.aof" AOF方式保存的文件名
3. 保存的目录 dir ./
4. appendfsync everysec ,表示每秒 执行一次同步操作, appendfsync always ,表示每次执行写操作,都会把写操作的命令追加到 AOF文件中去, appendfsync no, 不主动进行同步操作,由操作系统去做(30秒执行一次)
5. auto-aof-rewrite-min-size 64mb AOF文件达到64m时,重新整理AOF文件,去掉一些重复的命令
Redis 主从复制------读写分离
一台主服务器(master)用来负责写入数据,写入数据后,把数据同步到从服务器(slave)上,多台从服务器用来负责读取redis的数据
主redis服务器的配置 主服务器既可以写也可以读,主要是写
> redis6380.conf 清空文件内容,
最后一个是 rdb文件名字
从redis服务器的配置
把上面的 6382替换为6384,再重新配置一个从服务器
这时候启动redis服务的命令 是 redis/src/redis-server ../redis6380.conf ,由于配置文件里面配置了使用后台启动,我们这里不用在后面 加上 &(后台启动符号)了
redis/src/redis-server ../redis6382.conf 启动redis服务
redis/src/redis-server ../redis6384.conf 启动redis服务
使用redis-cli 启动客户端
redis-cli -p 6380 后,连接上一个redis服务, 使用 info replication 查看当前连接到的redis服务器的信息
./redis-cli -p 6382 后,连接上一个redis服务, 使用 info replication 查看当前连接到的redis服务器的信息
./redis-cli -p 6384 启动客户端后,连接上redis服务器,使用 info replication 查看信息。
redis配置主从之后,主服务器上可以设置 key和value ,从服务器上只能 读取key,不能设置key和value ,这样实现了 读写分离
redis容灾处理
当redis主服务器(master)出现故障,需要手动把slave服务器中的一个提升为master,剩下的slave挂载到新的master上(冷处理,服务器挂了,再处理)
命令 1 slaveof no one ,将一台slave服务器提升为master,我不是任何人的从服务器
2. slaveof 127.0.0.1 6382 将slave挂载到新的master上
比如说,我们现在把 6380这个主服务器停掉, 现在的6382和6384两个都是从服务器,我们在6382的客户端窗口,执行 slaveof no one ,后6382端口 变成主服务器,但是6384端口还不知道谁是新的主服务器,这时,我们需要在6384端口的客户端执行 slaveof 127.0.0.1 6382,我们把6384端口的从服务器挂载到 新的 master服务器下(6382端口服务下)
当6380机器修好后,启动6380服务,此时6380还认为自己是主服务器,我们需要在6380客户端执行 slaveof 127.0.0.1 6382 ,让6380也挂载到 6382端口的服务器下,就可以了
redis高可用哨兵
哨兵最少是3个,必须是奇数个,哨兵分别安装在不同的机器上,
redis sentinel 是官方提供的高可用方案,用来监控多个redis服务实例的运行情况。哨兵不处理数据,是监控主redis运行的程序 默认端口号 26379
监控: 往主redis发送ping命令,redis服务器会响应 pong给哨兵,每个哨兵都监控 主redis,如果有超过一半的哨兵认为主redis不能提供服务之后,(少数服从多数),开始处理故障,哨兵选举一个新的redis主服务器,并把其他的从服务器连接到新的主redis服务器
提醒:
自动故障转移:
哨兵程序 src/redis-sentinel
复制三份 sentinel.conf文件,修改配置
1. port 26379 ===》第一个 port 26380(当前哨兵运行的端口号) 第二个 port 26382 第三个 port 26384
2. 监控redis运行用到的, 分别是 哨兵 监控 主reids名字(随便) 主redis的ip 主redis的port 投票的数量(2) ,达到2个就认为主redis已经不能提供服务了
sentinel monitor mymaster 127.0.0.1 6382 2 #现在6382是redis的主服务器
3. 启动哨兵
src目录下 ./redis-sentinel ../sentinel6380.conf ./redis-sentinel ../sentinel6382.conf
./redis-sentinel ../sentinel6384.conf ,启动三个哨兵
4. 关闭掉 6382 redis主服务器之后,哨兵通过选举 将6384 选举为新的主服务器,6380为从服务器并且挂载到 新的redis主服务器下面,
5.重新启动 6382服务器, 稍微等待一会后,6382 会连接到 6384主服务器上当作新的从服务器
redis的安全问题
1. 设置密码 redis.conf配置文件中,需要修改为足够复杂的密码,1秒内可以接收150K次
src 目录下 ./redis-server ../redis.conf 启动服务
客户端 使用密码连接方式1 ./redis-cli -a 123456
连接方式2 ./redis-cli 启动客户端,在客户端中使用 auth 123456 ,才可以操作redis
2. 绑定ip bind 127.0.0.1 127.0.0.2 ,只有绑定的ip才能连接到 redis
3. 修改默认的端口号,