Redis

发布于:2025-03-14 ⋅ 阅读:(17) ⋅ 点赞:(0)

2025年1月17号晚

SQL与NOSQL的对比:

Redis常改的配置文件:

这种配置文件的日志文件会创建在当前工作目录下

这种方式启动Redis比较麻烦, 可以做到开机自启: 

1.编写配置文件,然后:

Redis有三种连接方式:

命令行客户端, 图形界面客户端, 编程语言

一开始的时候应该熟悉这些个命令, 在后面还是使用图形化客户端比较方便, 就类似于SQLyog

Redis的数据结构:

Redis的常用命令:

可以通过官网或者help命令来查看相关的使用说明,

TTL返回-1说明是永久, 返回-2说明已经失效

其中这个KEYS不建议在生产环境中使用, 其提供模糊搜索的功能,*表示任意个,?表示一个,模糊搜索的效率是比较低的

String类型:

整型和浮点型在底层存储时与普通字符串具有差异, 可以实现增减

Key的结构:

为了保证key的唯一性

Hash类型:

List类型:

这个列表的左侧为首,右侧为尾,左侧第一个是0

其中BLPOP和BRPOP在没有时会等待指定时间,而不是直接返回空, 类似于阻塞

Set类型:

SortedSet:​​​​​​类型​

Java客户端:

Jedis:

在单元测试中@AfterEach和@BeforeEach修饰的方法是在每个测试方法执行前后分别执行的,是JUnit中非常常用的两个注解

SpringDataRedis:

注意RedisTemplate接收的是一个Object对象,然后根据数据结构的类型使用序列化器将其序列化为字节数组,最后存储在Redis中的是一个字节数组, 在读取数据的时候会使用对应的反序列化器将其转换为Java对象,这个过程保证了Redis存储和Java对象之间的兼容性

这种使用jdk序列化工具的序列化方式存在弊端:

解决方案: 通过编写配置类来修改RedisTemplate的序列化的工具来实现不同的序列化方式, 可以使得所存即所见(存"giao", 在Redis中看到的就是"giao", 而不是一个字节数组), 如下图的配置类所示, 根据数据结构的不同采用不同的序列化工具可以实现所存即所见的目的.

练习过程遇到的错误:

在我演示代码时遇到的几个错误: 1.Linux对于6379端口防火墙是不允许外部连接的,

2.Java的jdk的序列化工具对于信息的存储是所存非所见的, 所以在redis中手动的存储的key,通过Java来访问是null, 因为通过Java的jdk序列化之后在redis中是找不到的,所以就为null, 但是通过Java存储的就能找到.所以这时就需要自定义序列化工具来实现所见即所存(使用别的序列化工具)或者使用别的序列化工具, 比如spring自带的StringRedisTemplate, 对于类,可以使用json序列化工具序列化之后再使用StringRedisTemplate写入Redis

在使用json序列化工具反序列化时要保证类具有无参构造函数和getter,setter方法, 这是很多工具给对象赋值所需要的.

关于lombok: 先引入依赖, :@Data是getter,setter方法, equals方法, toString方法, hashCode方法

@NoArgsConstruct是提供无参构造器

@AllArgsConstruct是全参构造器

为了使 Lombok 在你的 IDE 中正常工作,你可能需要安装 Lombok 插件。大多数流行的 IDE(如 IntelliJ IDEA 和 Eclipse)都有可用的 Lombok 插件。安装插件后,IDE 将能够识别 Lombok 注解并正确编译代码, 以后遇到问题可能是这方面的原因

高级篇:

分布式缓存:

持久化:
RDB:

Linux不是直接操作物理内存的, 而是管理一个虚拟内存(页表),虚拟内存和物理内存之间存在映射关系. 当bgsave时,会将物理内存标记为只读, 这 时如果有新的写操作的请求就会对物理内存进行拷贝, 以后对该数据的读取也会转移到这个副本上. 如果,子进程写入磁盘的时间比较长,此时有大量的写操作涌入, 就会对内存有很大的消耗.

AOF: 

主从:

具体如何搭建, 看资料:D:\BaiduNetdiskDownload\Redis-笔记资料\03-高级篇\资料\Redis集群.md

哨兵:

具体如何搭建, 看资料:D:\BaiduNetdiskDownload\Redis-笔记资料\03-高级篇\资料\Redis集群.md

这里面最重要的就是offset值, 如果offset的值都一样,那么选哪个作为master也就没有区别了.

RedisTemplate的哨兵模式:

注意: 只需要配置哨兵的地址, 其他都交给哨兵来完成.

这个方法可以写在启动类中.

分片集群:

之所以可以访问集群任意节点,最后都会被转发到正确节点是因为这些节点之间会做自动的路由(或者叫重定向).

也就是说数据跟着插槽走,而不是跟着节点, 这样的话,当节点宕机时,将插槽转移到活的节点即可保证数据不丢失.

切记在集群模式下要加上 -c

也有手动分配插槽的命令等等.

多级缓存:

JVM进程缓存:

它提供了一个get方法, 如果未命中可以去到数据库中查询, 查询之后自动的将数据写入缓存.

Lua语法:

CentOs自带lua文件的运行环境, lua文件不需要编译, 可以直接运行.

lua有一种特殊的命令行方式, 直接输入lua就能进入lua的控制台

local表示该变量为局部变量, 不用local修饰, 则表明该变量是全局变量

lua数组的角标是从1开始.

在lua中字符串的拼接是用 ".." ,例如:

local str  = "hello" .. "world"

遍历数组和table的示例, 注意: 一个是ipairs, 一个是pairs

OpenResty:

关于openResty的安装教程见文档: D:\BaiduNetdiskDownload\Redis-笔记资料\03-高级篇\资料

向tomcat发送请求:

注意: 这个ngx.location.capture发送的请求会被Nginx自己监听, 所以我们需要对这个路径做反向代理到tomcat服务器

不同的进程的数据不是共享的, 也就说不同的tomcat对应的不同的JVM之间数据独立, 那么就要保证相同的请求路径每次都访问相同的tomcat, hash $request-cluster是用来对路径做一种算法来生成一个hash值, 然后对集群配置的数量取模,就能保证相同的路径每次都是访问相同的tomcat.

Redis缓存预热:

注意: 1.InitializingBean, 这个接口必须要实现afterPropertiesSet()方法, 该方法在类加载完成后自动调用.

查询Redis:

Nginx本地缓存:

先去查本地缓存, 缓存未命中则去查Redis, 还没命中就去查数据库(发送请求给tomcat), 最后将数据写入本地缓存.

缓存同步:

安装Canal见文档:D:\BaiduNetdiskDownload\Redis-笔记资料\03-高级篇\资料

业务逻辑的实现:

最佳实践:

键值设计:

object encoding key, 可以查看其编码方式, 尽量保持在44个字节内, 这样就能避免使用row的底层编码方式.

BigKey:

存储对象时,推荐使用hash类型的数据结构存储

可以通过命令行的方式来修改hash-max-ziplist-entries, 一般要求不能超过1000, 因为大于1000就可能造成bigKey问题, 重启后修改的值会失效.

批处理:

执行命令消耗的时间和网络传输的时间相比可以忽略不计, 也就是说命令的响应时间主要花在网络传输上面.

原生的M操作是说, 这些命令是内置在Redis中的, 而且执行起来是原子性的, 

Pipeline的操作不是原子性的, 也就是说pipeline发送命令到Redis, 会一条一条的执行, 如果此时有别的请求也发送到的Redis中, 因为到的时间有先后, 所以可能会将pipeline发送的命令被分段执行, 这样就不发保证执行的时效性, 好处就是pipeline可以同时传输不同的命令.

数据倾斜: 比如要执行10000个写操作, 那么这一万条数据全部都保存在同一个Redis服务端当中, 也就是说服务端数据的分配不均, 这就是数据倾斜.

建议使用并行Slot的方法, Spring也提供了执行的方法

服务端优化:

持久化配置:

慢查询:

Redis有一个队列存储接收到的请求.

安全配置:
内存配置:
集群和主从:

Redis原理篇:

数据结构:

SDS:

IntSet:

IntSet应该在数据量不太大的时候使用.

Dict:

为了方便增加元素, 新加的元素永远在链表的队首.

size的大小永远是2的n次方, 因此h&sizemask的值才和size%h的值一致.

ZipList:

QuickList:

SkipList:

RedisObject:

五种数据结构:
String:

在使用String时最好保证字符串的长度不要超过44字节, 能用int表示最好使用int

List:

Set:

ZSet:

Hash:

网络模型:

用户空间和内核空间:

IO多路复用:

惊群现象: 比如有多个进程监听同一个FD(调用epoll_wait), 这时FD准备就绪时, 其中有进程来读取文件, 因为LT模式在读取时不会将FD从链表中删除, 这就会导致多个进程都来读取该FD

通讯协议:

RESP:

内存回收:

过期策略:

淘汰策略: