Java-Redis

文章目录

基础

基础内容

java 复制代码
概念:
	Redis,全称为Remote Dictionary Server(远程数据服务),是开源的、基于内存的、键值对存储系统,是非关系型、日志型数据库;
特点:
	性能高;
	数据类型丰富,单键值对最大支持512M大小的数据;
	简单易用,支持所有主流编程语言;
	支持数据持久化、主从复制、哨兵模式等;

使用场景/功能

java 复制代码
高性能缓存服务器:
	用于减轻数据库服务器的压力,项目运行将所必须内容加载到Redis中,提高项目对数据的获取速度;
数据共享:
	Redis是分布式的独立服务,可以多个项目使用相同的Redis;
分布式锁:
	实现对某操作的原子性执行,推荐使用redisson第三方库实现;
全局id:
	incrby 利用原子性,incrby userid 1000 分库分表的场景,一次性拿一段;
计数器:
	incr方法实现,目前涉及到的内容集中在计费操作,通过incr记次数实现;
限流:
	incr 本质还是统计次数,然后利用最大值限制;
位统计:
	用于大数据量的统计,通过二进制表示数据;
还有很多,不做详细介绍了 用到哪种学习哪种?
参考博客:https://blog.csdn.net/agonie201218/article/details/123640871	

常见数据类型

字符串String

java 复制代码
key是区分大小写的;
默认使用String类型存储键值对;
get获取的key对应的value是不存在,那么会输出nil;
不支持中文存储value,只是通过二进制形式存储,若想正常实现存储内容,需要在登录的时候采用redis-cli --raw登录;
TTL 查询key对应的过期时间,值为-1,则表示该键没有过期时间;值为-2,表示该key已经过期了;

列表List

java 复制代码
存储和操作一组有顺序的数据;
输入输出可以类比栈,单向输入输出;
	lPush在左侧输入输出,RPush在右侧输入输出;输入元素是abc 那么输出是cba;
	lPop 和 RPop也是类似的操作;
	Llen 获取 长度;
可以重复的;
相关命令以l开头;

集合Set

java 复制代码
不可以重复;
smembers course ,假设该set集合没有元素,则返回empty list or set
相关命令以S开头;

有序集合 SortedSet

java 复制代码
每一个key都会关联一个浮点类型的分数,会按照这个分数排序,从小到大来排序;
有序集合的元素是唯一的,但是分数是可以重复的;
相关命令都是z开头;

哈希hash

java 复制代码
键值对的集合,适合存储对象;
相关命令都以h开头;

消息队列 Stream

java 复制代码
可以解决发布订阅功能的缺点;
相关命令都以x开头;
涉及到消费者组、以及消息的多次读取;

地理空间 Geospatial

java 复制代码
存储地理位置信息的数据结构,同时对地理位置进行计算操作;
相关命令都以Geo开头;
如果key-value存储地点-经纬度,那么通过查询key得到的是一个数组;
如果计算两个value之间的距离,返回结果默认是米;
查询某个key在指定半径内的其他key;

命令:
GEOSEARCH City FROMMEMBER shanghai BYRADIUS 1000 KM 查询key=上海 1000千米范围内的key城市

HyperLogLog

java 复制代码
是一种用来做基数统计的算法;基于随机算法,牺牲一些精确度的角度,来减轻内存消耗;
基数 = 如果集合中的元素都不重复,那么基数=集合中元素的个数;
例如:集合12345,它的基数是5,集合1122334455,它的基数仍旧是5;
优点:占用内存小;缺点:精度不高;
适用场景:数据量大,且不需要精确度的情况;
相关命令都以pf开头;

位图Bitmap

java 复制代码
字符串类型的扩展,可以使用字符串模拟一个数组;
数组的下标就是偏移量,值只有0和1;也支持位运算,与 或 非 异或等;
相关命令有bit开头或bit结尾;

位域Bitfield

java 复制代码
将小的整数,存储到一个较大的位图中,可以高校的使用内存;

下载与安装

三种方式实现:

java 复制代码
linux系统;
windows系统的压缩包安装;
windows系统的docker desktop 镜像安装;

停止终端的方式:

java 复制代码
按下ctrl+c 或者 关闭终端页面;

可视化(多个)

参考链接:https://blog.csdn.net/WeiHao0240/article/details/123423230

参考博客:https://blog.csdn.net/boboJon/article/details/135073969

发布订阅功能

java 复制代码
订阅频道
	subscribe xxx
发布消息到频道
	publish xxx 消息内容
订阅频道的终端可以有多个;

缺点:
消息无法持久化;
无法记录历史消息;

事务

java 复制代码
概念:在一次请求中,执行多条命令;
通过MULTI开启事务,将后续所有命令放入队列中,通过EXEC执行队列中命令;
并不能保证事务中的所有命令都执行成功;
可以保证的内容:
	执行EXEC命令之前,会将所有命令都缓存起来,不立即执行;
	执行EXEC命令,事务中的某个命令执行失败,其余命令不会受到影响;
	执行EXEC命令过程中,其他用户提交的命令,不会插入得到命令的执行序列中;

通过MULTI启动事务,指令会多TX标识符;
再次输入命令,会返回QUEUED,表示已经放入命令执行队列;

两种持久化

java 复制代码
是一个重要的功能,Redis是基于内存的,如果断点,则会导致数据丢失;所以必须有持久化操作;
两种方式:RDB 和 AOF 方式;
RDB:Redis Database
	在指定时间间隔内,将内存中的数据快照写入磁盘中;
	某个时间点上完整副本;
	通过save参数配置;
	save 参数1 参数2  --》参数1=时间间隔 参数2=修改次数
	更适合用来做备份,因为如果服务宕机,那么快照最后一次后的所有修改就会丢失;
	思考1:
		由于正式环境中 redis都会给分配较大的内存空间,通过RDB进行备份的时候,redis是不能进行处理的,会影响业务;
		通过提供bgsave命令处理,会创建一个子进程专门处理备份,主进程处理业务,但是在创建子进程的过程中仍旧不能处理业务;
AOF:
	执行追加文件,在执行写命令的过程中,不仅会将结果写入数据库中,而且会将写命令写入追加文件中(AOF文件);
	redis执行写操作时,会重新执行AOF文件,重新构建数据库;
	开启AOF方式:配置文件中,将appendonly参数值改成yes;

主从模式

java 复制代码
将主节点数据复制到从节,主节点-master,从节点slave;
从节点可以有很多,每个从节点只能有一个主节点;
数据的复制是单向的,只能从主节点到从节点;
主节点负责写操作,从节点负责读操作;
主节点通过异步的方式向从节点发送数据,从节点收到后更新自己的数据;
一台主机上可以配置多个redis 通过不同的端口号进行区分;

配置:

java 复制代码
主节点 不需要配置,因为默认就是主节点;
设置从节点的方式两种:命令 以及 配置文件修改
命令:
	role --》 查看当前节点角色
	replicaf host port --》配置所属主节点
配置文件:是redis.conf文件
	修改端口号:port pidfile 都要修改端口号
	dbfilename 配置也要加上端口号
	rplicaof host port 配置主节点
	Redis默认是以守护进程的方式运行,系统默认会将pid写入文件中;

redis-cli登录:
	info replication 查看配置信息;

哨兵模式

主从模式存在问题:

当主节点宕机之后,需要人工干预将从节点提升为主节点;

哨兵模式:

java 复制代码
哨兵以一个独立的进程运行在一个Redis集群中,用来监控Redis集群中的节点是否运行正常;
作用:
	监控:会不断向各个节点发送指令,检查各个节点的是否正常运行;
	通知:发现某个节点不能正常工作,会通过发布订阅模式,通知其他节点;
	自动故障转移:会将从节点变成新的主节点,再将其他从节点指向该主节点;

哨兵模式配置:
	配置文件sentinel.conf
	内容:
		sentinel monitor master ip port 1
		ip 和 port都是主节点的
		1 = 使用一个哨兵来实现故障转移
		正式环境中一般都采用3个哨兵,防止哨兵节点宕机;
启动哨兵模式:
	redis-sentinel sentinel.conf

集群模式Cluster

java 复制代码
解决问题:
	采用主从复制、哨兵机制,每台机子上完整存储所有数据,当数据量特别大的时候,这种情况是无效的;
定义:
	cluster是redis提供的分布式数据库解决方案,将所有数据分片,节点进行领取,即使某些节点宕机,也还可以执行操作;
数据分片:
	将key通过CRC16校验函数计算,再对16384取模运算,再决定数据分配到哪个槽位(也即是片、slot)	;
	每个redis的cluster节点负责一部分槽数据的存储;(槽数据 = 存储在特定槽上的所有键值对)
	这些节点再结合主从复制模式,对数据进行备份;
查询策略:
	每个节点都会存储整个集群节点信息,这些叫元信息;
	元信息:各节点存储的槽数据、master和slave状态、节点存活状态;
	两次查询实现数据查询;
元信息传递:
	gossip协议,每个节点把自己的数据信息通过协议传递出去;
	具体过程:周期性执行;所有被感染的节点选择k个相邻的节点散播消息;
扩容缩容:
	当数据量大时,增加节点;数据量少,减少节点;	

缓存淘汰

java 复制代码
淘汰策略:常用的三个;默认是LRU
	先进先出FIFO:
		类似一个队列,淘汰最早载入缓存的数据;
	最近最早使用LRU:
		老数据,按照最近被访问的时间排序,末端节点删除;
		实现思路-双向链表+哈希表;双向链表存储键值对;哈希表存储key和双向链表的node节点的指针引用;
		具体执行: 当某个key被访问到,会将其对应的node节点放到双向链表的头部;
	最不经常使用LFU:
		多一个 被访问次数 这个属性;
		key+value 结合被访问次数,组成新的数据结构;
		将该数据结构放入双向链表中,按照次数从大到小的排序方式,先替换排在最后的元素;

过期删除

java 复制代码
默认采用定期删除;
目前有三种策略:主动删除、惰性删除、定期删除;
	主动删除:
		设置错误间隔时间,在指定时间后进行主动删除;
		缺点:当redis比较忙,删除时间刚好到了,则会增加服务器的负担;
	惰性删除:
		程序访问某个数据,先判断是否已经过期,没过期则返回,反之,则删除;
		缺点:只有当被访问到的时候,才进行删除,会导致内存中存在大量无效数据,造成资源的浪费;
	定期删除:
		主动删除+惰性删除;
		每个一段时间,执行主动删除;其余时间,采用惰性删除;

缓存一致 Cache Aside

java 复制代码
定义:
	后端缓存数据 = 数据库数据,并不是时时刻刻保持一致,允许在一定小范围内,出现不一致的情况;
采用策略:
	Cache Aside策略:
		模式1 = 删除缓存、更新数据库
		模式2 = 更新数据库、更新缓存
	Read/Write Through
		将缓存作为主要的数据读取方式,如果缓存中没有数据,则更新缓存,再从缓存中取数;
	Write Behind
		更新数据库与更新缓存都采用异步的形式;
		结合mysql的主从复制模式,将mysql作为主服务,redis作为从服务;

模式1:

模式2:

Read/Write Through

Write Behind

缓存击穿

java 复制代码
定义:
	查询某个数据的值,缓存中没有,而数据库中有
危害:
	如果访问该key的量特别大,且缓存中没有,则请求全部会访问数据库;
	redis的性能是mysql数据库的10-100倍,当访问量redis可以承受时,转到mysql上,可能就会导致mysql宕机;
解决:
	mysql角度,加锁,控制redis击穿之后数据库的并发访问量;
	redis角度,热点数据永不过期;异步线程,将重要数据、已经过期的 进行过期时间重置;

缓存穿透

java 复制代码
定义:
	一条查询数据,缓存中没有,数据库中也没有;
解决方法:
	拦截非法请求;
	缓存空对象;
	布隆过滤器;

布隆过滤器:

缓存雪崩

java 复制代码
定义:
	一大批缓存数据都失效,故此这批请求都会被打到数据库上,导致数据库宕机;
与缓存击穿的区别:
	缓存击穿是单点;缓存雪崩是多点;
解决方式:
	mysql角度,加锁,减少数据库并发量;
	redis角度,	
		热点数据永不过期;
		让失效时间分散点;
		缓存预热,即在上线前,根据当天的情况,将数据直接加载到缓存系统;

实战内容

配置文件

单机模式:

xml 复制代码
spring:
  redis:
    enable: true
// 意图是控制是否启用Redis功能
    host: localhost
    port: 6379
    database: 0
    // redis数据库的索引,表示第一个数据库
    timeout: 10000ms
    // Redis服务器的超时时间,单位ms,也就是10秒
    lettuce:
    // spring data redis默认使用的客户端;
      pool:
      // 配置lettuce的连接池配置
        max-active: 8
        // 最大活动连接数
        max-idle: 8
        // 最大空闲连接数
        min-idle: 0
        // 最小空闲连接数
        max-wait: -1ms
        // 获取连接的最大等待时间

主从模式:

xml 复制代码
// 通过spring.redis.sentinel来配置;

spring:
  redis:
    sentinel:
    // 配置使用主从复制模式
      master: mymaster
      // 指定主服务器组
      nodes:
        - "sentinel1:26379"
        - "sentinel2:26379"
        - "sentinel3:26379"
        // seninel实例的主机名或ip 以及端口号
    database: 0
    timeout: 10000ms
    password: yourpassword

Sentinel配置文件:(哨兵模式)
# Sentinel配置文件位置 /etc/redis/sentinel.conf 
具体内容:sentinel monitor mymaster 192.168.1.100 6379 2
# 监控名为mymaster
# 监控主机的ip和port 192.168.1.100 6379
# 至少有2个sentinel确认服务器宕机后才进行故障转移
sentinel down-after-milliseconds mymaster 30000
# 如果sentinel在3,0000毫秒内没有收到主服务器的有效回复,则认为主服务器宕机;
sentinel failover-timeout mymaster 180000
# 故障转移,等待新主机启动的超时时间为18,0000毫秒
sentinel parallel-syncs mymaster 1
# 故障转移过程中,同时复制给从服务器的数量限制为1

集群模式:

xml 复制代码
spring:
  redis:
    cluster:
    // 指定redis采用集群模式
      nodes:
      // 集群中的节点列表,每个节点都是集群中的一个成员;
        - "node1:7000"
        - "node2:7000"
        - "node3:7000"
        - "node4:7000"
        - "node5:7000"
        - "node6:7000"
    password: yourpassword
    timeout: 10000ms

配置Redis的Bean

java 复制代码
public class RedisConfig {
    @Autowired
    private StringRedisTemplate commonStringRedisTemplate;
    // 自动注入StringRedisTemplate实例;
    // 是 Spring Data Redis 提供的一个模板类,专门用于处理字符串类型的键值对;

    @Bean
    // 将返回一个可以被 Spring 管理的 Bean。
    public RedisOperations commonRedisOperations(){
        RedisOperations redisOperations = new DefaultRedisOperations(commonStringRedisTemplate);
        // 创建了一个 DefaultRedisOperations 实例,这是一个自定义的类(假设它是存在的),它接受 StringRedisTemplate 作为构造函数的参数。
        // 用于封装 Redis 操作,并初始化分布式锁机制。
        DistributedLock.init(redisOperations);
        // 初始化一个分布式锁机制,接受一个 RedisOperations 参数用于设置内部的 Redis 操作实例。同时,在应用程序启动时,分布式锁就会准备好使用。
        log.info("{}","Redis分布式锁初始化完成");
        return redisOperations;
    }
}

Redis为什么这么快?

Hash冲突怎么办?

项目与redis服务配置方式不同?

java 复制代码
问题描述:
	项目配置redis,采用单机模式配置;
	redis服务,采用集群方式;
	导致项目启动异常;
分析:
	Redis 服务是按照集群(cluster)模式部署的,而应用程序却以单机(standalone)模式尝试连接到该集群中的某一个节点,这通常不会直接导致 Redis 服务本身启动异常。但会遇到连接或者操作失败的问题。
相关推荐
Armyyyyy丶14 分钟前
Redis底层实现原理之五大基础结构
数据结构·redis·缓存
seabirdssss23 分钟前
使用Spring Boot DevTools快速重启功能
java·spring boot·后端
喂完待续32 分钟前
【序列晋升】29 Spring Cloud Task 微服务架构下的轻量级任务调度框架
java·spring·spring cloud·云原生·架构·big data·序列晋升
benben04434 分钟前
ReAct模式解读
java·ai
轮到我狗叫了1 小时前
牛客.小红的子串牛客.kotori和抽卡牛客.循环汉诺塔牛客.ruby和薯条
java·开发语言·算法
yudiandian20141 小时前
【QT 5.12.12 下载 Windows 版本】
开发语言·qt
高山有多高1 小时前
详解文件操作
c语言·开发语言·数据库·c++·算法
狂奔的sherry2 小时前
单例模式(巨通俗易懂)普通单例,懒汉单例的实现和区别,依赖注入......
开发语言·c++·单例模式
Volunteer Technology2 小时前
三高项目-缓存设计
java·spring·缓存·高并发·高可用·高数据量
EnigmaCoder2 小时前
【C++】引用的本质与高效应用
开发语言·c++