Redis
Redis 是基于 Open Source BSD 协议,使用 C 语言编写的一种Key-Value(键值对)内存数据库
安装
工具
启动服务端
redis-server /root/myredisconf/redis.conf -使用指定配置文件启动
启动客户端连接
redis-cli -a root -p 6379 用密码和端口登录授权
10大数据类型
1.String
set key value 设置指定 key 的值
-
EX
seconds – 设置键key的过期时间,单位时秒 -
PX
milliseconds – 设置键key的过期时间,单位时毫秒 -
NX
– 只有键key不存在的时候才会设置key的值 -
XX
– 只有键key存在的时候才会设置key的值 -
KEEPTTL
-- 获取 key 的过期时间 -
GET -- 返回 key 存储的值,如果 key 不存在返回空
get key 获取指定 key 的值
MGET 获取所有(一个或多个)给定 key 的值 MSET 同时设置一个或多个 key-value 对 MSETNX 同时设置一个或多个 key-value 对,得都不存在才插入
GETRANGE 返回 key 中字符串值的子字符 SETRANGE 从偏移量 offset 开始用 value 覆写给定 key 所储存的字符串值
INCR 将 key 中储存的数字值增一 INCRBY 将 key 所储存的值加上给定的增量值 ( increment ) DECR 将 key 中储存的数字值减一 DECRBY 将 key 所储存的值减去给定的减量值 ( decrement )
STRLEN 返回 key 所储存的字符串值的长度 APPEND 将 value 追加到 key 原来的值的末尾
GETSET 将给定 key 的值设为 value ,并返回 key 的旧值 ( old value )
2.List
List 是 Redis 中最常用数据类型。值value 中存储的是列表。
LPUSH 将一个或多个值插入到列表头部 RPUSH 在列表中添加一个或多个值 LRANGE 获取列表指定范围内的元素
LPOP 移出并获取列表的第一个元素 RPOP 移除并获取列表最后一个元素
LINDEX 通过索引获取列表中的元素
LLEN 获取列表长度
LREM 移除指定个数的列表元素
LTRIM 对一个列表进行修剪(trim),保留指定开始到结束
RPOPLPUSH 移除列表的最后一个元素,并将该元素添加到另一个列表并返回
LSET 通过索引设置列表元素的值
LINSERT before/after在列表的元素前或者后插入元素
BLPOP 移出并获取列表的第一个元素 BRPOP 移出并获取列表的最后一个元素 BRPOPLPUSH 从列表中弹出一个值,并将该值插入到另外一个列表中并返回它 LPUSHX 将一个值插入到已存在的列表头部 RPUSHX 为已存在的列表添加值
3.Hash
Hash(哈希散列)是 Redis 基本数据类型,值value 中存储的是 hash 表。Hash 特别适合用于存储对象。常用的命令:
HSET 用于设置存储在 key 中的哈希表字段的值也可以多次 HGET 获取存储在哈希表中指定字段的值 HMGET 获取存储在哈希表中指定字段的值 HGETALL 获取在哈希表中指定 key 的所有字段和值 HDEL 用于删除哈希表中一个或多个字段
HKEYS 获取存储在 key 中的哈希表的所有字段 HVALS 用于获取哈希表中的所有值
HEXISTS 用于判断哈希表中字段是否存在 HINCRBY 为存储在 key 中的哈希表指定字段做整数增量运算 HLEN 获取存储在 key 中的哈希表的字段数量
hsetnx 没有就加入
4.set
SADD key member1 [member2] 向集合添加一个或多个成员 SMEMBERS 返回集合中的所有成员 SISMEMBER 判断 member 元素是否是集合 key 的成员 SREM 移除集合中一个或多个成员 SCARD 获取集合的成员数
SRANDMEMBER 返回集合中一个或多个随机数 SPOP 移除并返回集合中的一个随机元素 SMOVE 将 member 元素从 source 集合移动到 destination 集合
集合运算 SDIFF 返回给定所有集合的差集 SDIFFSTORE 返回给定所有集合的差集并存储在 destination 中 SINTER 返回给定所有集合的交集 SINTERCARD numkeys key [key ...] [LIMIT limit] 返回给定所有集合的交集个数 SINTERSTORE 返回给定所有集合的交集并存储在 destination 中
SUNION 返回所有给定集合的并集 SUNIONSTORE 所有给定集合的并集存储在 destination 集合中 SSCAN 迭代集合中的元素
应用
5.有序集合zset(sorted set)
ZADD key score member [score member ...] 向有序集合添加一个或多个成员,或者更新已存在成员的分数 ZRANGE key end [withscores] 通过索引区间返回有序集合成指定区间内的成员 ZREVRANGE 返回有序集中指定区间内的成员,通过索引,分数从高到底 ZRANGEBYSCORE 通过分数返回有序集合指定区间内的成员 加一个括号变成不包括边界
ZSCORE 返回有序集中,某个成员的分数值 ZCARD 获取有序集合的成员数 ZREM 移除有序集合中的一个或多个成员 ZINCRBY 有序集合中对指定成员的分数加上增量 increment ZCOUNT 计算在有序集合中指定区间分数的成员数 zmpop 从键名列表中的第一个非空排序集中弹出一个或多个元素,它们是成员分数对
ZRANK 返回有序集合中指定成员的索引 ZREVRANK 返回有序集合中指定成员的排名,有序集成员按分数值递减(从大到小)排序
ZINTERSTORE 计算给定的一个或多个有序集的交集并将结果集存储在新的有序集合 key 中 ZLEXCOUNT 在有序集合中计算指定字典区间内成员数量 ZRANGEBYLEX 通过字典区间返回有序集合的成员 ZREMRANGEBYLEX 移除有序集合中给定的字典区间的所有成员 ZREMRANGEBYRANK 移除有序集合中给定的排名区间的所有成员 ZREMRANGEBYSCORE 移除有序集合中给定的分数区间的所有成员 ZREVRANGEBYSCORE 返回有序集中指定分数区间内的成员,分数从高到低排序 ZUNIONSTORE 计算一个或多个有序集的并集,并存储在新的 key 中 ZSCAN 迭代有序集合中的元素(包括元素成员和元素分值)
应用
6.位图bitmap
setbit key offset value 键 偏移位 只能零或者1
getbit key offset
strlen 统计字节数占用多少 每8位算一个字节(扩容)
bitcount key [start end] 是用来统计某一个二进制串里面1的个数
bitop operation destkey key [key] 主要对于多个对应key的二进制串,做and,or,xor, not操作。结果存入destkey 。
应用
7.HyperLogLog
去重复统计功能的基数估计算法-就是HyperLogLog
PFADD key element [element ...] 将指定元素加入到给定的HyperLogLog中。
PFCOUNT key [key ...] 返回给定HyperLogLog的基数估算值。
PFMERGE destkey sourcekey [sourcekey ...] 将多个HyperLogLog合并为一个HyperLogLog。
应用
8.Redis GEO地理空间
Redis GEO 主要用于存储地理位置信息,并对存储的信息进行操作,该功能在 Redis 3.2 版本新增。
底层是zset ,所以用zrange也可以
如果有乱码问题加参数 redis- cli-a111111 --raw
GEOADD key longitude latitude member [longitude latitude member ...] 用于存储指定的地理空间位置,可以将一个或多个经度(longitude)、纬度(latitude)、位置名称(member)添加到指定的 key 中。
GEOPOS key member [member ...] 用于从给定的 key 里返回所有指定名称(member)的位置(经度和纬度),不存在的返回 nil。
GEOHASH key member [member ...] 用于获取一个或多个位置元素的 geohash 值。
GEODIST key member1 member2 [m|km|ft|mi] 用于返回两个给定位置之间的距离。
GEORADIUS key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC] [STORE key] [STOREDIST key] 以给定的经纬度为中心, 返回键包含的位置元素当中, 与中心的距离不超过给定最大距离的所有位置元素。
GEORADIUSBYMEMBER key member radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC] [STORE key] [STOREDIST key] georadiusbymember 的中心点是由给定的位置元素决定的, 而不是使用经度和纬度来决定中心点。
应用
9.流Stream
Redis Stream 是Redis5.0推出的一种专门用来处理消息队列场景的高级数据结构,是Redis下消息队列的最佳实现。
实现消息队列,它支持消息的持久化、支持自动生成全局唯一ID、支持ack确认消息的模式、支持消费组模式等,让消息队列更加的稳定和可靠
消息队列的相关命令: XADD:添加消息到末尾(生产消息)XADD key ID field value [field value ...] XTRIM:对流进行修剪,限制长度 XTRIM key MAXLEN [~] count XDEL:删除消息 XDEL key ID [ID ...] XLEN:获取流包含的元素数量,及消息长度 XLEN key XRANGE:获取消息列表,会自动过滤已经删除的消息 XRANGE key start end [COUNT count] XREVERANGE:反向获取消息列表,ID从大到小 XREVRANGE key end start [COUNT count] XREAD:以阻塞或非阻塞方式获取消息列表(消费消息) XREAD [COUNT count] [BLOCK milliseconds] STREAMS key [key ...] id [id ...] 消费者组相关命令: XGROUP CREATE:创建消费者组 XGROUP [CREATE key groupname id-or-] [SETID key groupname id-or-] [DESTROY key groupname] [DELCONSUMER key groupname consumername] XREADGROUP GROUP:读取消费者组中的消息 XREADGROUP GROUP group consumer [COUNT count] [BLOCK milliseconds] [NOACK] STREAMS key [key ...] ID [ID ...] XACK:将消息标记为“已处理” XGROUP SETID:为消费者组设置新的最后递送消息ID XGROUP DELCONSUMER:删除消费者 XGROUP DESTROY:删除消费者组 XPENDING:显示待处理消息的相关信息 XCLAIM:转移消费者组的相关信息 XINFO GROUPS:打印消费者组的信息 XINFO STREAM:打印流信息
10.位域(bitfield)
位域修改 溢出控制
将一个Redis字符串看作是一个由二进制位组成的数组并能对变长位宽和任意没有字节对产的指定整型位域进行寻址和修改
Redis持久化
RDB(Redis 数据库): RDB 持久性以指定的时间间隔执行数据集的时间点快照。
RDF
后续集群时要修改dump文件名称
备注:不可以把备份文件dump.rdb和生产redis服务器放在同一台机器,必须分开各自存储,以防生产机物理损坏后备份文件也挂了。
优势
适合大规模的数据恢复、按照业务定时备份、对数据完整性和一致性要求不高、RDB 文件在内存中的加载速度要比 AOF 快得多
使用redis-check-rdb工具修复rdb文件
哪些情况会触发RDB快照
禁用快照
1.动态所有停止RDB保存规则的方法: redis-cli config set save
2.修改配置文件 set “”(推荐)
其他配置
stop-writes-on-bgsave-error:如果配置成no,表示你不在乎数据不一致或者有其他的手段发现和控制这种不一致,那么在快照写入失败时,也能确保redis继续接受新的写请求 --默认yes
rdbcompression:对于存储到磁盘中的快照,可以设置是否进行压缩存储。如果是的话,redis会采用LZF算法进行压缩。如果你不想消耗CPU来进行压缩的话,可以设置为关闭此功能 --默认yes
rdbchecksum:在存储快照后,还可以让redis使用CRC64算法来进行数据校验,但是这样做会增加大约10%的性能消耗,如果希望获取到最大的性能提升,可以关闭此功能 --默认yes
rdb-del-sync-files:在没有持久性的情况下删除复制中使用的RDB文件启用。 默认情况下no,此选项是禁用的。
AOF
AOF 则是通过保存Redis服务器所执行的写命令来记录数据库状态。
工作流程
序号 | 过程 |
---|---|
1 | Client作为命令的来源,会有多个源头以及源源不断的请求命令。 |
2 | 在这些命令到达Redis Server 以后并不是直接写入AOF文件,会将其这些命令先放入AOF缓存中进行保存。这里的AOF缓冲区实际上是内存中的一片区域,存在的目的是当这些命令达到一定量以后再写入磁盘,避免频繁的磁盘IO操作。 |
3 | AOF缓冲会根据AOF缓冲区同步文件的三种写回策略将命令写入磁盘上的AOF文件。 |
4 | 随着写入AOF内容的增加为避免文件膨胀,会根据规则进行命令的合并(又称AOF重写),从而起到AOF文件压缩的目的。 |
5 | 当Redis Server 服务器重启的时候会从AOF文件载入数据。 |
写会策略
修复
优点:更好的保护数据不丢失 、性能高、可做紧急恢复
缺点:相同数据集的数据而言aof文件要远大于rdb文件,恢复速度慢于rdb,aof运行效率要慢于rdb,每秒同步策略效率较好,不同步效率和rdb相同
重写原理:
1:在重写开始前,redis会创建一个“重写子进程”,这个子进程会读取现有的AOF文件,并将其包含的指令进行分析压缩并写入到一个临时文件中。 2:与此同时,主进程会将新接收到的写指令一边累积到内存缓冲区中,一边继续写入到原有的AOF文件中,这样做是保证原有的AOF文件的可用性,避免在重写过程中出现意外。 3:当“重写子进程”完成重写工作后,它会给父进程发一个信号,父进程收到信号后就会将内存中缓存的写指令追加到新AOF文件中 4:当追加结束后,redis就会用新AOF文件来代替旧AOF文件,之后再有新的写指令,就都会追加到新的AOF文件中 5:重写aof文件的操作,并没有读取旧的aof文件,而是将整个内存中的数据库内容用命令的方式重写了一个新的aof文件,这点和快照有点类似
RDB-AOF混合持久化
在同时开启rdb 和aof 持久化时,重启时只会加载 aof 文件,不会加载 rdb 文件
推荐方式:
1 开启混合方式设置
设置aof-use-rdb-preamble的值为 yes yes表示开启,设置为no表示禁用
2 RDB+AOF的混合方式---------> 结论:RDB镜像做全量持久化,AOF做增量持久化
先使用RDB进行快照存储,然后使用AOF持久化记录所有的写操作,当重写策略满足或手动触发重写的时候,将最新的数据存储为新的RDB记录。这样的话,重启服务的时候会从RDB和AOF两部分恢复数据,既保证了数据完整性,又提高了恢复数据的性能。简单来说:混合持久化方式产生的文件一部分是RDB格式,一部分是AOF格式。----》AOF包括了RDB头部+AOF混写
纯缓存模式:
Redis事务
可以一次执行多个命令,本质是一组命令的集合。一个事务中的所有命令都会序列化,按顺序地串行化执行而不会被其它命令插入,不许加塞
redis事务命令
命令 | 描述 |
---|---|
DISCARD | 取消事务,放弃执行事务块内的所有命令 |
EXEC | 执行所有事务块内的命令 |
MULTI | 标记一个事务块的开始 |
UNWATCH | 取消 WATCH 命令对所有 key 的监视 |
WATCH | 监视一个(或多个) key |
1.正常执行
//开启事务
multi
//执行事务
exec
2.放弃事务
//开启事务
multi
//放弃事务
discard
3.全体连坐
指检查出语法错误全体加入队列失败
4.冤头债主
指通过语法检查,但比如对string类型执行自增操作,程序报错,但其他操作会正常执行
5.watch
悲观锁(Pessimistic Lock), 顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。
乐观锁(Optimistic Lock), 顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据。乐观锁策略:提交版本必须 大于 记录当前版本才能执行更新
Redis使用Watch来提供乐观锁定,类似于CAS(Check-and-Set)
6.unwatch
小结
1.一旦执行了exec之前加的监控锁都会被取消掉了 2.当客户端连接丢失的时候(比如退出链接),所有东西都会被取消监视
Redis管道pipeLine
管道(pipeline)可以一次性发送多条命令给服务端,服务端依次处理完完毕后,通过一条响应一次性将结果返回,通过减少客户端与redis的通信次数来实现降低往返延时时间。pipeline实现的原理是队列,先进先出特性就保证数据的顺序性。
Redis复制(replica)
就是主从复制,master以写为主,Slave以读为主 当master数据变化的时候,自动将新的数据异步同步到其它slave数据库
读写分离、容灾恢复、数据备份、水平扩容支撑高并发
基本操作命令
修改配置文件细节操作
常见问题: 1.从机可以执行写命令吗? 从机不能写,做到主从读写分离 2.主机shutdown后,从机会上位吗? 从机不动,原地待命,从机数据可以正常使用;等待主机重启动归来 3.主机shutdown后,重启后主从关系还在吗? 从机还能否顺利复制? 还在,能顺利复制 4.某台从机down后,master继续,从机重启后它能跟上大部队吗? 可以继续跟上,首次一锅端,后续跟随,master写,slave跟
但是重启后关系不见了
上一个slave可以是下一个slave的master,slave同样可以接收其他slaves的连接和同步请求,那么该slave作为了链条中下一个的master,可以有效减轻主master的写压力
Redis哨兵(sentinel)
吹哨人巡查监控后台master主机是否故障,如果故障了根据投票数自动将某一个从库转换为新主库,继续对外服务
作用
主从监控 监控主从redis库运行是否正常 消息通知 哨兵可以将故障转移的结果发送给客户端 故障转移 如果Master异常,则会进行主从切换将其中一个Slave作为新Master 配置中心 客户端通过连接哨兵来获得当前Redis服务的主节点地址
配置
在master断开连接后,数据依然在,会从剩下的slave选出一个master,当原来的master连回来时,原来的master会转换身份,变为slave
哨兵的运行流程和原理
Raft算法
master上位流程
Redis集群(cluster)
slot槽位映射,一般业界有3种解决方案:哈希取余分区、一致性哈希算法分区(数据倾斜问题)、哈希槽分区
哈希槽经典面试题:为什么redis集群的最大槽数是16384个?
(1)如果槽位为65536,发送心跳信息的消息头达8k,发送的心跳包过于庞大。
在消息头中最占空间的是myslots[CLUSTER_SLOTS/8]。 当槽位为65536时,这块的大小是: 65536÷8÷1024=8kb
在消息头中最占空间的是myslots[CLUSTER_SLOTS/8]。 当槽位为16384时,这块的大小是: 16384÷8÷1024=2kb
因为每秒钟,redis节点需要发送一定数量的ping消息作为心跳包,如果槽位为65536,这个ping消息的消息头太大了,浪费带宽。
(2)redis的集群主节点数量基本不可能超过1000个。
集群节点越多,心跳包的消息体内携带的数据越多。如果节点过1000个,也会导致网络拥堵。因此redis作者不建议redis cluster节点数量超过1000个。 那么,对于节点数在1000以内的redis cluster集群,16384个槽位够用了。没有必要拓展到65536个。
(3)槽位越小,节点少的情况下,压缩比高,容易传输
Redis主节点的配置信息中它所负责的哈希槽是通过一张bitmap的形式来保存的,在传输过程中会对bitmap进行压缩,但是如果bitmap的填充率slots / N很高的话(N表示节点数),bitmap的压缩率就很低。 如果节点数很少,而哈希槽数量很多的话,bitmap的压缩率就很低。
cluster nodes查看并检验集群状态
cluster info 集群信息
使用集群后要以集群方式读写 登录要加-c
redis-cli -a 111111-p 6381-c
查看某个key该属于对应的槽位值
CLUSTER KEYSLOT 键名称
主从切换、对调
CLUSTER FAILOVER
重新分派槽号
reshard
分配从节点
redis-cli -a 密码 --cluster add-node ip:新slave端口 ip:新master端口 --cluster-slave --cluster-master-id 新主机节点ID
删除从节点
命令:redis-cli -a 密码 --cluster del-node ip:从机端口 从机节点ID
主从扩容和主从缩容
cluster-require-full-coverage: 默认值 yes , 即需要集群完整性,方可对外提供服务 通常情况,如果这3个小集群中,任何一个(1主1从)挂了,你这个集群对外可提供的数据只有2/3了, 整个集群是不完整的, redis 默认在这种情况下,是不会对外提供服务的。
CLUSTER COUNTKEYSINSLOT 槽位数字编号
CLUSTER KEYSLOT 键名称
Spring Boot集成Redis
jedis - lettuce - RedisTemplate(推荐)三者的联系
jedis
@Component
public class JedisDemo {
public static void main(String[] args) throws InterruptedException {
//1. connection获得,通过指定ip和端口号
Jedis jedis = new Jedis("192.168.169.129", 6380);
//2. 指定访问服务器的密码
jedis.auth("root");
System.out.println(jedis.ping());
Set<String> keys = jedis.keys("*");
System.out.println(keys);
jedis.set("kv","hello springboot");
System.out.println(jedis.get("kv"));
System.out.println(jedis.ttl("kv"));
jedis.expire("kv",20);
Thread.sleep(1000*3);
System.out.println(jedis.ttl("kv"));
jedis.lpush("list","11","12","13","123");
System.out.println(jedis.lrange("list",0,-1));
}
}
Lettuce
加入依赖
<dependency>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
<version>6.2.1.RELEASE</version>
</dependency>
业务
@Component
public class LettuceDemo {
public static void main(String[] args) {
//1.使用构建器 RedisURI.builder
RedisURI uri = RedisURI.builder()
.redis("192.168.169.129")
.withPort(6380)
.withAuthentication("default","root")
.build();
//2.创建连接客户端
RedisClient redisClient = RedisClient.create(uri);
StatefulRedisConnection connect = redisClient.connect();
//3.通过conn创建换作的command
RedisAsyncCommands commands = connect.async();
//业务
commands.set("kv2","hello springboot2");
System.out.println(commands.get("kv2"));
//4.各种关闭资源
connect.close();
redisClient.shutdown();
}
}
RedisTemplate
导入依赖
<!--SpringBoot与Redis整合依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
service层
@Slf4j
@Service
public class OrderService {
public static final String ORDER_KEY = "order:";
// @Autowired
// private RedisTemplate redisTemplate;
@Autowired
private StringRedisTemplate stringRedisTemplate; //改用StringRedisTemplate解决序列化问题
public void addOrder()
{
int keyId = ThreadLocalRandom.current().nextInt(1000)+1;
String orderNo = UUID.randomUUID().toString();
// redisTemplate.opsForValue().set(ORDER_KEY+keyId,"京东订单"+ orderNo);
stringRedisTemplate.opsForValue().set(ORDER_KEY+keyId,"京东订单"+ orderNo);
log.info("=====>编号"+ORDER_KEY+keyId+"的订单流水生成:{}",orderNo);
}
public String getOrderById(Integer id)
{
// return (String)redisTemplate.opsForValue().get(ORDER_KEY + id);
return stringRedisTemplate.opsForValue().get(ORDER_KEY + id);
}
序列化问题
键(key)和值 (value)都是通过Spring提供的Serializer序列化到数据库的。 RedisTemplate默认使用的是JdkSerializationRedisSerializer.StringRedisTemplate默认使用的是StringRedisSerializer。KEY被序列化成这样,线上通过KEY去查询对应的VALUE常不方
方案一
使用StringRedisTemplate,但是在get key的时候也会有乱码,这时需要在登录时使用redis-cli -a root -p 6380 --raw
方案二
使用StringRedisSerializer()序列化方式
@Configuration
public class RedisConfig
{
/**
* redis序列化的工具配置类,下面这个请一定开启配置
* 127.0.0.1:6379> keys *
* 1) "ord:102" 序列化过
* 2) "\xac\xed\x00\x05t\x00\aord:102" 野生,没有序列化过
* this.redisTemplate.opsForValue(); //提供了操作string类型的所有方法
* this.redisTemplate.opsForList(); // 提供了操作list类型的所有方法
* this.redisTemplate.opsForSet(); //提供了操作set的所有方法
* this.redisTemplate.opsForHash(); //提供了操作hash表的所有方法
* this.redisTemplate.opsForZSet(); //提供了操作zset的所有方法
* @param lettuceConnectionFactory
* @return
*/
@Bean
public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory)
{
RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(lettuceConnectionFactory);
//设置key序列化方式string
redisTemplate.setKeySerializer(new StringRedisSerializer());
//设置value的序列化方式json,使用GenericJackson2JsonRedisSerializer替换默认序列化
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
}
集群环境问题
故障描述:SpringBoot客户端没有动态感知到RedisCluster的最新集群信息
导致原因:SpringBoot 2.X 版本,Redis默认的连接池采用 Lettuce当Redis 集群节点发生变化后,Letture默认是不会刷新节点拓扑
解决方案:1. 排除lettuce采用jedis (不推荐)2 .重写连接工厂实例 (极度不推荐) 3 .刷新节点集群拓扑动态感应官网
server.port=7777
spring.application.name=redis7_study
# ========================logging=====================
logging.level.root=info
logging.level.com.atguigu.redis7=info
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger- %msg%n
logging.file.name=D:/mylogs2023/redis7_study.log
logging.pattern.file=%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger- %msg%n
# ========================swagger=====================
spring.swagger2.enabled=true
#在springboot2.6.X结合swagger2.9.X会提示documentationPluginsBootstrapper空指针异常,
#原因是在springboot2.6.X中将SpringMVC默认路径匹配策略从AntPathMatcher更改为PathPatternParser,
# 导致出错,解决办法是matching-strategy切换回之前ant_path_matcher
spring.mvc.pathmatch.matching-strategy=ant_path_matcher
# ========================redis集群=====================
spring.redis.password=111111
# 获取失败 最大重定向次数
spring.redis.cluster.max-redirects=3
spring.redis.lettuce.pool.max-active=8
spring.redis.lettuce.pool.max-wait=-1ms
spring.redis.lettuce.pool.max-idle=8
spring.redis.lettuce.pool.min-idle=0
#支持集群拓扑动态感应刷新,自适应拓扑刷新是否使用所有可用的更新,默认false关闭
spring.redis.lettuce.cluster.refresh.adaptive=true
#定时刷新
spring.redis.lettuce.cluster.refresh.period=2000
spring.redis.cluster.nodes=192.168.111.175:6381,192.168.111.175:6382,192.168.111.172:6383,192.168.111.172:6384,192.168.111.174:6385,192.168.111.174:6386
Redis管理 redis 服务相关命令
命令 | 描述 |
---|---|
BGREWRITEAOF | 异步执行一个 AOF(AppendOnly File) 文件重写操作 |
BGSAVE | 在后台异步保存当前数据库的数据到磁盘 |
CLIENT | 关闭客户端连接 |
CLIENT LIST | 获取连接到服务器的客户端连接列表 |
CLIENT GETNAME | 获取连接的名称 |
CLIENT PAUSE | 在指定时间内终止运行来自客户端的命令 |
CLIENT SETNAME | 设置当前连接的名称 |
CLUSTER SLOTS | 获取集群节点的映射数组 |
COMMAND | 获取 Redis 命令详情数组 |
COMMAND COUNT | 获取 Redis 命令总数 |
COMMAND GETKEYS | 获取给定命令的所有键 |
TIME | 返回当前服务器时间 |
COMMAND INFO | 获取指定 Redis 命令描述的数组 |
CONFIG GET | 获取指定配置参数的值 |
CONFIG REWRITE | 修改 redis.conf 配置文件 |
CONFIG SET | 修改 redis 配置参数,无需重启 |
CONFIG RESETSTAT | 重置 INFO 命令中的某些统计数据 |
DBSIZE | 返回当前数据库的 key 的数量 |
DEBUG OBJECT | 获取 key 的调试信息 |
DEBUG SEGFAULT | 让 Redis 服务崩溃 |
FLUSHALL | 删除所有数据库的所有 key |
FLUSHDB | 删除当前数据库的所有 key |
INFO | 获取 Redis 服务器的各种信息和统计数值 |
LASTSAVE | 返回最近一次 Redis 成功将数据保存到磁盘上的时间 |
MONITOR | 实时打印出 Redis 服务器接收到的命令,调试用 |
ROLE | 返回主从实例所属的角色 |
SAVE | 异步保存数据到硬盘 |
SHUTDOWN | 异步保存数据到硬盘,并关闭服务器 |
SLAVEOF | 将当前服务器转变从属服务器(slave server) |
SLOWLOG | 管理 redis 的慢日志 |
SYNC | 用于复制功能 ( replication ) 的内部命令 |
面试题
redis到底是单线程还是多线程?
redis4之后才慢慢支持多线程,直到redis6/7后才稳定。
lO多路复用听说过吗?
redis为什么快?
基于内存操作: Redis 的所有数据都存在内存中,因此所有的运算都是内存级别的,所以他的性能比较高;
数据结构简单:Redis 的数据结构是专门设计的,而这些简单的数据结构的查找和操作的时间大部分复杂度都是O(1),因此性能比较高:
多路复用和非阻塞I/O:Redis使用I/O多路复用来监听多个 socket连客端,这样就可以使用一个线程连接来处理多人请求,减少线程切换带来的开销,同时也避免了I/O 阻塞
避免上下文切换:因为是单线程模型,因此就避免了不必要的上下文切换和多线程竞争,这就省去了多线程切换带来的时间和性能上的消耗,而且单线程不会导致死锁问题的发生
标签:AOF,redis,Redis,获取,key,集合 From: https://www.cnblogs.com/sukidakara/p/18025021