JAVA 学习笔记 三

文章目录

redis

redis的特性


redis的使用场景

  1. 消息队列:使用 LIST 或 PUB/SUB 机制来实现消息传递和队列功能。
  2. 实时分析:利用 Sorted Sets 和 HyperLogLog 进行实时数据分析和计数。
  3. 会话存储:存储用户会话数据,例如登录状态和用户偏好。
  4. 分布式锁:利用 Redis 的 SETNX 命令实现分布式锁,以确保资源的互斥访问。
  5. 排行榜:使用 Sorted Sets 创建和管理排行榜或评分系统。
  6. 计数器:使用 INCR 命令实现高效的计数器功能,例如访问计数。
  7. 数据结构存储:利用 Redis 提供的各种数据结构(如 HASH、SET、LIST 等)来存储复杂数据类型。

哪里用到的redis,时效

  • 数据库存储 存储登录信息 token 30分钟 实现value的序列化,存储的对象
  • 缓存 路由转发,接口匹配 redismanager默认30天
    工作流暂存 10分钟:为了缓解数据库压力,开始的流程是异步进程,但是要全量进程的结果
  • 幂等性的实现 在消费消息时,将消息的uuid存储到redis中,防止重复消费

redis数据结构

String 动态字符串,类似于ArrayList

List 双向链表

Hash 数组加链表 等价于Java语言的HashMap

Set HashMap 只不过所有value都指向同一个对象

ZSet 压缩链表或者跳表

Stirng 底层实现

动态字符串sds

sds结构一共有五种header定义,目的是为了满足不同长度字符串使用,节省内存。

header主要包括:

  • len长度
  • alloc字符串最大容量,不包括header和最后的空终止字符
  • flags标志位,第三位表示类型,其余五位未使用
  • buf:字符数组
  • encoding
    • int:可以使用long类型的整数表示的会用long型来存储
    • raw:长度大于44字节的字符串,使用sds存储
    • embstr:长度小于等于44字节的字符串,效率比较高,且数据都保存在一块内存区域。

ZSet的实现方式:

ziplist压缩链表:

  • 元素数量小于128
  • 每个元素长度小于64

skiplist跳跃链表:不满足上述条件就采用跳表,具体来说组合了map和skiplist

  • map用来存储 member到score的映射, 时间复杂度为O(1)
  • skiplist按照从小到大存储分数,每个元素的值都是score,value

跳表就是在有序节点上增加多级索引

n个节点,第一层索引为n/2,第二层索引为n/4,第k层索引为n/2^k

空间换时间的折半查找

redis排行榜 zset

添加

zadd key score value

ZADD broadcast:20210108231 1 lisi

加分

zincrby key increment member

ZINCRBY broadcast:20210108231 2 lisi

排名

ZRANGE broadcast:20210108231 0 -1 WITHSCORES

redis遍历key

keys pattern 一次性匹配所有key,当key比较多时,对内存消耗和redis都是隐患

SCAN cursor MATCH pattern COUNT count 2.8.0版本之后加入

scan只会返回少量元素,每次调用用上次调用返回的游标,以此延续迭代过程,返回为0标识迭代结束。

count表示从数据集返回多少个匹配元素

redis的淘汰策略

过期键淘汰策略是定期删除和惰性删除
定期删除 是指:redis服务器定期操作redis.c/serverCron函数执行时,redis.c/activeExpireCycle会被调用。actvieExpire函数在规定时间内,分多次遍历服务期内的多个数据库,从过期字典中检查一部分key的过期时间并删除。

current_db记录当前检查数据库,函数处理2号数据库时间超限,返回后下次检查会从3号数据库开始检查。所有数据库检查完毕current_db重置为0,然后再次开启一轮的检查工作。
惰性删除是指用户请求,此时会检查过期,过期清除不会返回

大量key堆积,内存耗尽如何处理?

内存淘汰机制:

缓存击穿,缓存雪崩

  • 缓存穿透:缓存和数据库中都没有数据,多次重复访问导致数据库崩溃
    解决
    • 业务层校验:对于不合规的入参,直接返回
    • 不存在数据设置短过期时间
    • 布隆过滤器
  • 缓存击穿:热点key失效同时,大量请求进入,从而全部到达数据库,压垮数据库
    解决
    • 永不过期
    • 定时更新:过期时间1h,每到59min去更新
    • 互斥锁:redis根据key获取到的value为空时,先加锁,去数据库加载,加载完毕,释放锁。其他线程请求发现获取锁失败,则睡眠一段时间。
  • 雪崩:缓存大面积失效,或者Redis宕机,大量请求进入数据库,压垮数据库
    解决
    • 设计有效期均匀分布:避免缓存设置相近的有效期,可以设置有效期时增加随机值,或者统一规划有效期,使得过期时间均匀分布。
    • 缓存预热:流量大时,提前访问一遍,将数据存储到redis中并且设置不同的过期时间
    • 保证Redis的高可用

redis的锁机制

redis一般用作缓存,多读少写,只支持乐观锁

Redis事务命令主要包括 WATCH, EXEC, DISCARD, MULTI。

事务使用MULTI开启,这时可以执行多条命令,Redis在这些事务中加入命令,当用户执行Exec命令时才真正的执行队列当中的命令。执行discard,丢弃队列中的命令。

Watch命令是Exec执行的条件,watch的key没有修改则执行事务,否则事务不会被执行。

Watch命令可以被调用多次,一个watch命令可以监控多个key。watch命令调用则开启监视功能,直到exec命令终止。

Redis的watch命令给事务CAS机制,如果key在执行exec前有变动,则整个事务被取消。

事务中,采用watch加锁,unwatch解锁,执行EXEC命令或者Discard命令后,锁自动释放,不需要进行unwatch操作。

redis分布式锁

参考:Redis实现分布式锁的7种方案

分布式锁需要保证:

1.互斥性:只能有一个客户端获得锁

2.安全性:锁只能被持有该锁的客户端删除

3.死锁:锁超时释放,避免死锁

4.容错:当redis部分节点宕机,客户端仍能获取锁和释放锁

1.一种实现

setnx k v; 成功返回1 失败返回0;

getset k v;返回key的旧值;

expire k secondsl;给key设置超时时间

del key key ...

1.1setnx key 当前时间+过期时间

1.2. 失败获取锁失败,成功 expire 超时时间

1.3.执行业务 del key

问题:如果获取锁成功未设置超时时间的时候进行重启,会产生死锁。

(如果不是kill线程,而是shutdown可以用springBean的predestory注解,进行删除key操作)

优化:获取锁失败后,查看当前key的value值,如果不为空,并且当前时间大于该值,说明当前锁失效,通过getset获取值。如果getset获取的值,和一开始的旧值相同,则获取锁成功。

问题:多节点时间需要尽可能的保持一致。getset即便失败也会延长之前锁的时间。

2.使用lua脚本

保证setnx和expire的原子性
3.set扩展命令

SET key valueEX secondsPX millisecondsNX\|XX

  • NX :表示key不存在的时候,才能set成功,也即保证只有第一个客户端请求才能获得锁,而其他客户端请求只能等其释放锁,才能获取。
  • EX seconds :设定key的过期时间,时间单位是秒。
  • PX milliseconds: 设定key的过期时间,单位为毫秒
  • XX: 仅当key存在时设置值

问题:业务没执行完,锁就释放了;锁被别的线程误删。
4.SET EX PX NX + 校验唯一随机值,再删除

还是会存在业务没有执行完成,锁释放的问题。
5.Redisson框架

开源框架Redisson

加锁后启动一个watchdog线程,每隔10s检查是否持有锁,持有锁就延长,防止锁过期提前释放。

6.redlock+redisson

redis节点全为master,避免master加锁后未同步到slave然后宕机导致加锁失败的情况

按顺序向5个master节点请求加锁

根据设置的超时时间来判断,是不是要跳过该master节点。

如果大于等于3个节点加锁成功,并且使用的时间小于锁的有效期,即可认定加锁成功啦。

如果获取锁失败,解锁!

持久化方案

redis线程模型

参考 深入学习redis 的线程模型

redis内部采用事件处理器是单线程的,因此redis叫做单线程模型。采用IO多路复用机制同时监听多个socket,将产生的事件的socket压缩到内存队列中,事件分派器根据事件不同的类型选择对应的事件处理器进行处理。

文件事件处理器的结构

  • 多个socket
  • IO多路复用程序
  • 文件事件分派器
  • 事件处理器(连接应答处理器,命令请求处理器,命令回复处理器)

线程模型

多个socket可能并发产生不同的操作,每个操作对应不同的事件,但是IO多路复用程序会监听多个socket,将产生事件的socket放入队列中排队,事件分派器每次从队列中取出一个socket,根据socket对应的事件类型交给对应的事件处理器进行处理。

建立连接

  • redis服务端进程初始化时,将server socket 的AE_READABLE事件与连接应答处理器关联。
  • 客户端socket01向redis进程serverSocket请求建立连接,此时server socket 产生一个AE_READBLE事件,IO多路复用程序监听到server socket产生的事件后,将socket压入队列。
  • 文件事件分派器从队列中获取socket,交给连接应答处理器。
  • 连接应答处理器会创建一个能与客户端通信的socket01,并将socket01的AE_READABLE事件与命令请求处理器关联
    执行一个set请求
  • 客户端发送了一个set key value请求,此时redis中的socket01会产生AE_READABLE事件,IO多路复用程序,将socket01压入队列
  • 此时事件分派器从队列中获取到socket01产生的AE_READABLE事件,由于前面socket01的AE_READABLE事件已经和命令请求处理器关联
  • 事件分派器将命令交给请求处理器来处理。命令处理器读取k v并在自己内存中完成设置
  • 操作完成后,将socket01的AE_WRITEABLE事件与命令回复处理器关联
  • 如果此时客户端准备好了接受数据,那么redis中的socket01会产生一个AE_READABLE事件,同样压入队列中
  • 事件派分器找到相关联的命令回复处理器,由命令回复处理器对socket01输入本次操作的一个结果,比如ok,之后解除socket01的AE_READABLE事件与命令回复处理器的关联。

为什么redis效率高?

1.纯内存操作

2.核心是基于非阻塞的IO多路复用机制

3.C语言实现,语言更接近操作系统,执行速度相对会快

4.单线程反而避免了多线程的频繁上下文切换问题,预防了多线程可能产生的竞争问题。

redis的吞吐量:

单点TPS达到8万/秒,QPS达到10万/秒

qps是指每秒最大能接受的用户访问量,tps是指每秒钟最大能处理的请求数。

部署方式

单机,主从,哨兵

kafka

核心概念

Producer(生产者):负责将消息发送到 Kafka 集群中的某个主题(Topic)。生产者将数据发布到 Kafka 中,可以并行发送数据。

Consumer(消费者):从 Kafka 中消费消息。消费者可以独立工作,也可以作为消费组的一部分,并行消费同一主题的数据。

Broker(代理):Kafka 集群中的每个节点都被称为一个 Broker。Kafka 集群可以由多个 Broker 组成。它负责接收、存储和转发消息。每个 Broker 都管理一部分分区的数据。

Topic(主题):Kafka 中的消息被按主题分类。每个生产者将消息发送到某个主题,消费者可以订阅某个主题并从中消费消息。主题是 Kafka 消息流的一个分类单位。

Partition(分区):Kafka 中的每个主题可以划分为多个分区。每个分区内的消息有序,并且每个分区的数据是由一个 Broker 来管理的。分区使得 Kafka 可以实现水平扩展,提高吞吐量。

Offset(偏移量):每个消息在分区内都有一个唯一的偏移量。消费者通过这个偏移量来追踪自己消费的位置。偏移量是分区内消息的顺序编号。

ZooKeeper:Kafka 使用 ZooKeeper 来管理和协调集群的元数据,如 Broker 信息、消费者组的偏移量等。ZooKeeper 作为一个集群管理工具,确保 Kafka 集群的高可用性和一致性。

使用消息队列的原因

1.流量削峰(消息过多,处理有限) 落库采用异步消息的方式,减缓数据库压力

2.服务解耦(接口故障不影响生产和消费)消息发出去,发消息的应用down了,也不会影响后序微服务的消费

3.异步(提高响应速度,用户无感知)

kafka 如何解决消息重复

  • 生产者:生产者发送的消息没有收到正确的broker响应,导致producer重试。

    以及 ack=all 以及 retries > 1 。ack=0,不重试。可能会丢消息,适用于吞吐量指标重要性高于数据丢失,例如:日志收集

    启动kafka的幂等性,设置: enable.idempotence=true幂等生产者的原理:每个生产者都有唯一Pid,发次发送消息会累加seq。broker为每个topic的每个分区都维护了一个当前当前写成功的消息最大PID-seq,消息落盘+1,当收到小于当前最大PID-seq时就会丢弃该消息。

  • 消费者:

    offset手动提交,业务成功处理后,提交offset

    幂等性:多次操作结果一致

    获取消息的唯一id,会将id存入redis,记录为处理中,以后的消息就不会进行重复处理

kafka如何保证消息不丢失

1.生产者发送给服务器

acks机制 0 发送就成功,1 生产者收到leader分区的响应则认为成功 -1 当所有ISR中的副本全部收到消息,生产者才认为是成功的

2.服务器通过副本保存消息

3.消费者,关闭自动提交,在接收到消息,进行业务处理完毕后再提交偏移量

kafka什么时候进行rebalance

参考Kafka的Rebalance机制可能造成的影响及解决方案

每当有新的消费者加入或者订阅的topic数发生变化,会触发rebalance(再均衡:在同一个消费组当中,分区的所有权从一个消费者转到另一个消费者)机制,Rebalance顾名思义就是重新均衡消费者消费。

过程如下:

1.所有消费者向coordinator发送请求,请求加入comsumer group。一旦所有成员都发送了请求,Coordinator会从中选择一个consumer作为leader,并将组员信息发给leader

2.leader分配消费方案,指定哪个消费者消费哪些topic的哪些分区。发给coordinator,coordinator发送给消费者,组内成员知道自己该消费哪些分区了。

coordinator:每个consumer group会选择一个服务器作为自己的coordinator,负责监控整个消费者组内各个分区的心跳,以及判断是否宕机和开启rebalance的

partition:每个topic分区,备份在不同的服务器上

如何选择coordinator?

对groupid进行hash,然后对_consumer_offsets的分区数量进行取模,默认分区数量为50,可以配置。

发生的时机:

1.分区数量增加。

2.对topic的订阅发生变化

3.消费者组成员的加入或者离开。

影响:1.重复消费;2.集群不稳定;3.影响消费速度

kafka 消息积压怎么办

参考

1.修复消费者,然后停掉所有消费者

2.临时建立10倍或者20倍的queue数量(新建topic,分区是原来的10倍)

3.写一个临时分发消息的consumer,消费挤压数据不作处理,均匀写入临时建好10数量的queue中

4.征用10倍的机器来部署consumer,每一批consumer消费一个临时queue的消息

5.这种做法相当于临时将queue资源和consumer资源扩大10倍,以10倍速度来消费消息

6.消费完成之后,回复原有的部署架构,重新用原来的consumer机器来消费消息。

kafka分区和消费者的关系

1.生产者中的分区合理消费,消费者的线程对象和分区保持一致,多余的线程不会进行消费

2.消费者默认即为一个线程对象

3.消费者服务器数*线程数 = partition个数

分区数量

分区多可以增加吞吐量

分区过多:

  • 客户端服务端需要的内存变多,客户端生产者有个参数batchsize,默认16kb。为每个分区缓存消息,满了打包发送。
    分区越多,消费者获取数据所需的内存就增多。同时消费者线程数要匹配最大分区数,线程切换开销很大。
    服务器端维护许多分区界别的缓存。
  • 文件句柄的开销:每个分区在底层文件系统都有属于自己的目录。分区越多,要同时打开的文件句柄数就越多。
  • 降低高可用性:kafka通过副本来保证高可用。分区多,服务器上的副本就多,服务器挂掉,在副本之间进行重新选举的消耗就大。

目标吞吐量TT,消费者吞吐量TC,生产者吞吐量TP,分区数= TT/max(TP,TC)

分区和消费者的关系是多对一

一个分区只能对应一个消费者的原因是保证消息顺序性。

因此消息挤压,部署多台消费者实例是不能加快消费的,最多增加到和分区数量一致,超过的组员只会占有资源二不起作用。

消费者分区分配策略

1.range策略

  • 将消费者按名称排序,分区按照数字排序
  • 分区总数/消费者,除得尽均匀分配,除不尽位于前面的消费多负责分区

2.roundrobin 轮询

为了保证均匀分配,需要满足两个条件

1.同一个消费者组里每个消费者订阅的主题必须相同

2.同一个消费者里面所有消费者的num.streams必须相等

3.sticky分配策略

主要实现两个目的,如果发生冲突,优先实现第一个

1.分区分配尽可能均匀

2.分区的分配尽可能的与上次分配的保持相同

0.11.X版本引入,最复杂最优秀

区别于轮询,在消费者挂掉之后,不会全部分区重新轮询分配,而是将挂掉消费者消费的分区进行重新分配。

其他微服务组件

eureka特性

  • cap

    Consistency(一致性)

    Availability(可用性)

    Partition tolerance(分区容忍性)

    任意组合,不能兼得 eureka ap zk cp

    注册慢:ap特性,client延迟注册 30s;server 响应缓存 30s;server 缓存刷新 30s

  • 自我保护机制: eureka会检查最近15分钟服务正常心跳占比,低于85%出发自我保护模式,不剔除服务。但是服务也会过期,eureka在启动完成后,每隔60s检查服务健康状态,如果被保护的服务过一段时间默认90s还没有恢复就会把服务剔除。

    在此期间高于85%,自动关闭自我保护机制。

    自我保护原因:避免因为网络通信故障降低可用性。

    一般开发关闭,因为开发经常重启。生产开启。生产环境相对稳定,让eureka管理。

  • 服务注册:启动注册,发送主机名,端口号等

  • 服务续约:30s一次,90s没收到进行服务剔除

  • 服务下线:client优雅退出发送cancel命令,server接到命令删除节点

  • 获取注册列表:第一次全量更新,后续增量更新,30s一次

eureka注册中心机制

参考高频面试之Eureka

注册中心,包括服务发现,治理等功能。

@EnableEurekaServer作为注册中心,@EnableEurekaClient作为服务的提供者或消费者。

  • 注册服务
    EurekaClient将服务信息封装成Intanceinfo对象,通过EurekaHttpClient调用register方法发送post请求执行服务注册;
    EurekaServer提供了基于Jersey的Rest风格接口,在ApplicationResource类中提供了addInstance方法来接受注册信息。如果注册信息通过校验,将服务信息保存到本地注册表。数据结构为双层HashMap,key为应用名,内层map,Key是应用实例信息编号,value是InstanceInfo
    EurekaClient接受并解析注册结果,判断httpResponse的statusCode,如果是204则代表注册成功
    调用replicateToPeers方法将此次注册信息复制到对等的Eureka节点
  • 定时任务
    • 拉取服务器注册实例
      任务通过ScheduledExecutorService来实现任务调度,执行周期默认为60秒一次
      获取方式有两种,全量获取和增量获取。第一次全量获取,后序增量获取;获取到服务器注册实例信息后,保存或更新到本地
      • 续约
        任务通过ScheduledExecutorService来实现任务调度,执行周期默认为30秒一次
        通过Renew方法发起续约请求。将appname,appid以及intanceinfo作为参数,通过EurekaHttpClien发送Http请求
        EurekaServer通过renewLease()方法接受续约请求
        根据AppName从注册表获取对应的服务信息,并更新一些属性如renewsLastMin,lastUpdateTimestamp
        EurekaServer返回结果200或者204
        EurekaClient接受续约结果;如果是404重新发起,如果是200则表示续约成功,更LastSuccessHeartBeatTimestamp变量
      • 剔除服务
        通过 JDK 自带的 Timer 来实现任务调度,通过 evict() 方法执行具体的操作
        首先判断是否开启了实例自我保护机制,如果开启自我保护,则不做任何操作
        如果未开启,根据 lastUpdateTimestamp 收集已过期的服务,加入到List集合中
        通过 internalCancel() 方法,在该方法中从 registry 中剔除已经过期的实例。具体的剔除过程会通过打乱过期服务列表,并通过 Random 随机剔除,保证服务器剔除的均匀性

Eureka

feign ribbon eureka

feign在调用时会被ribbon拦截,RibbonLoadBalancerClient中构建了一个ILoadBalancer来确定应用名对应的真实ip,

内部调用eureka的服务发现获取服务发现缓存的服务信息。

更新是在RibbonClientConfiguration创建定时任务30s一次

eureka和nacos的区别

限流算法

一致性哈希

一致性哈希相较于普通哈希具有更好的可扩展性和容错性。

哈希是对节点个数取模,在进行扩容或者节点下线时,需要重新映射所有数据。

一致性哈希是对2^32取模,将哈希值空间映射到虚拟的闭环上,称为哈希环。取模所得值,进行顺时针寻找到的第一个节点为哈希环中的位置。节点扩容和下线时只需要迁移相邻节点的数据。

当分布不均衡时,采用虚拟节点来解决问题。

无状态的服务,消费降级

linux命令

cat 文件 | grep 关键字 | wc -l

参考 Linux系统中统计文件中某个字符出现次数命令详细教程

  • 不分大小写统计
    grep -o -i 'a' aaa.txt | wc -l
  • 统计多个文件中某个字符出现次数总和
    grep -o -i 'a' aaa.txt bbb.txt | wc -l

其他

分布式锁

1.数据库

在数据库中以资源唯一号为主键插入数据,处理完成后删除数据

问题:

  • 释放锁失败会导致死锁,需要定时任务定时清理
  • 锁的可靠性依赖数据库,建议设置备库,避免单点
  • 锁是非阻塞的,因为插入失败会报错;如果需要阻塞式的设置for,while循环等
  • 非可重入的锁,需要在数据库中添加字段获取主机信息,匹配的话重新分配给他。

乐观锁:查询数据和版本号,进行更新,更新成功加锁成功

问题:

  • 对表增加额外字段,增加数据库冗余
  • 并发量高的时候,会导致大量请求失败,以及大量请求对数据库的压力。

适合并发量不高,且操作不频繁的场景

悲观锁:增加排它锁 select for update;更新数据。

问题: 每次请求都会都会产生额外的加锁开销并且阻断等待锁的获取,高并发的情况下,容易造成大量请求阻塞,影响可用性。

2.缓存 redis redlock和redission实现,所有节点均为master,加锁轮询请求,超过半数即为加锁成功,否则加锁失败

3.zookeeper:

zk是一个为分布式提供一致性服务的开源软件。

它内部是一个分层的文件系统目录结构,规定同一个目录下只能有一个唯一文件名。

基于zookeeper实现分布式锁的步骤:

  1. 创建一个目录myLock
  2. 线程A获取锁就在myLock下创建临时顺序节点
  3. 获取目录下所有子节点,找到比自己小的,如果不存在,获得锁
  4. 线程B获取所有节点,判断不是最小节点,设置监听比自己小的节点。
  5. A处理完毕后,删除节点,线程B监听到变更事件,判断自己是不是最小节点,如果是则获得锁。
    可以使用zookeeper第三方库Curator客户端
    问题:
  • 性能没有缓存高,每次加锁释放锁都需要动态的创建,销毁临时节点来实现锁功能。zk中创建和删除节点都需要通过leader来执行,同步到fllower上。
  • zookeeper也可能有并发问题。当获取锁的客户端和zk的session连接断了,就会删除临时节点,其他线程就会获得锁。不常见是因为zk有重试机制,Curator客户端支持多种重试策略的配置。

参考堆的应用 -- Top-K问题(巨详细)

堆是二叉树,一般的二叉树用链表存储,用数组存储会浪费空间,但是堆是完全二叉树,用数组存储。

已知父节点下标n, 他的右节点为2n+2,左节点2n+1

已知子节点n,他的父节点为(n-1)/2

大根堆和小根堆

大根堆:根节点大于左右孩子节点

小根堆:根节点小于左右孩子节点

优先级队列

java提供这种数据结构,每次添加或者删除元素,都会变成小跟堆。

java 复制代码
// 默认得到一个小根堆
PriorityQueue<Integer> smallHeap = new PriorityQueue<>();
smallHeap.offer(23);
smallHeap.offer(2);
smallHeap.offer(11);
System.out.println(smallHeap.poll());// 弹出2,剩余最小的元素就是11,会被调整到堆顶,下一次弹出
System.out.println(smallHeap.poll());// 弹出11

 // 如果需要得到大根堆,在里面传一个比较器
 PriorityQueue<Integer> BigHeap = new PriorityQueue<>(new Comparator<Integer>() {
     @Override
     public int compare(Integer o1, Integer o2) {
         return o2 - o1;
     }
 });

top-K问题

数组,找出前三个最小元素

1.排序

2.放入小跟堆

3.在大根堆中放三个元素,循环数组每次往里放一个数据,弹出最大的数据,最后堆里就是结果。

堆的向下调整算法、堆的向上调整算法、堆的实现、Topk问题

数据格式标准化

xml到标准对象 thoughtworks.xstream 流

json到标准对象 hutools工具,底层反射调用set方法

javaBean

java语言中的可重用组件。

满足:1.类是公共的;2.有一个无参的公共构造器;3.有属性,且有对应的get和set方法。

其他开发者通过JSP,Servlet 其他JavaBean,applet程序或者应用来使用这些对象。用户可以认为JavaBean提供了一种随时随地复制粘贴的功能。

javaBean的任务就是一次性编写,任何地方执行,任何地方重用。

synchronized在哪用到

createMaxNo 开启数据库事务,sf for update 增加数据库排他锁

同一个应用有一个缓存,加同步锁,避免并发重复增加步长,造成浪费。

应用之间由数据库的排他锁协调。

ConditionalOnMissingBean注解

在beanFactory中没有指定的bean才能匹配,主要用来做自动配置,当没有指定类的时候,使用默认配置

确保使用注解的bean在指定bean的后面运行,否则会失效。

ConditionalOnBean

指定类存在时,实例化当前Bean

ConditionalOnClass

指定类名在类路径上存在,实例化当前Bean

ConditionalOnMissingClass

指定类名在类路径上不存在,实例化当前Bean

actuator

找到HealthContributor类型bean进行健康注册,健康检查的时候检查这些bean

redis池化

JedisPoolConfig

相关推荐
腻害兔6 小时前
【若依项目-产品经理视角】深度拆解 RuoYi-Vue-Pro 商城模块:从商品管理到交易引擎,50 张表撑起一整套电商系统
java·大数据·vue.js·产品经理·ai编程
码智社7 小时前
AES加密原理详解及Java实现加解密实战
java·开发语言
克里斯蒂亚诺更新7 小时前
ruoyi角色权限的对应关系
笔记
萧瑟余晖8 小时前
JDK 26 新特性详解
java·开发语言
马优晨9 小时前
Freemarker 完整讲解(后端 Java 模板引擎)
java·开发语言·freemarker·freemarker 完整讲解·freemarker模板引擎
a11177610 小时前
2FA 验证码生成器(github登录验证 app)
笔记·学习
我的xiaodoujiao10 小时前
API 接口自动化测试详细图文教程学习系列32--Allure测试报告2
python·学习·测试工具·pytest
维天说11 小时前
CLI-Switch 2026年3月版历史设计:Hook、TTY 隔离与 JSON 状态
java·服务器·json
破碎的南瓜11 小时前
sqli--sql注入过关笔记(1,2,3,4,5,9)
数据库·笔记·sql
Zane199412 小时前
并发 vs 并行:别再傻傻分不清了,一文讲透 Java 并发编程的第一课
java·后端