- 博客(54)
- 收藏
- 关注
原创 接口限流经典算法
为了保证系统的安全性和稳定性,防止恶意流量和突发大量流量短时间内大量请求接口,造成服务器崩溃,接口的限流是有必要的。控制水流稳定流出,进水就是向接口发起的请求,一定有时快有时慢,但是漏水的速度是一定的,只要桶装满了就拒绝请求。漏桶里面的任务是一点点执行的,令牌桶有可能一下子把令牌全用光一起执行,这样就可以很快的处理大流量的请求。如果切分越小,产生的块就多,窗口滚动越平滑,限流统计越准确,但是对服务器压力越大。把令牌以稳定的速度放入桶中,如果桶被放满了,多余的令牌就无法放入。以下是四种经典的限流算法。
2024-08-24 11:23:29
282
原创 nginx反向代理了解
cgi:通用网关(接口),主要解决的问题是从客户端发送请求和数据,服务端获取到请求和数据后可以调用cgi程序处理及相应结果给客户端的一种标准规范。正向代理代理的是客户端(如翻墙),反向代理代理的是服务端,用户请求代理服务器,代理服务器再将请求分发到服务端。客户端将请求发送给代理,代理再向服务端请求,并接受服务端响应,将响应返回给客户端,比如翻墙。客户端将请求发送给代理,代理将请求发送给不同的服务端,把服务端隐藏起来,降低服务端压力。设置被代理服务器地址,可以是主机名称,ip地址+端口形式。
2024-06-03 21:09:09
793
2
原创 ElasticSearch学习
拼音分词器会将词一个字一个字的转成拼音,而且没有中文,所以我们还要修改拼音分词器的配置es中的分词器组成包含三部分character filters:在tokenizer之前对文本进行处理,例如删除字符,替换字符tokenizer:将文本按照一定规则切割成词条tokenizer filter:将tokenizer输出的词条做进一步处理,例如大小写转化,同义词处理,拼音处理等可以在创建分词库时,通过setting来配置自定义的analyzer(分词器)PUT /test。
2024-05-19 18:32:03
1019
1
原创 Rabbitmq学习
如果我们向消息队列中发送Java对象,spring对消息对象的处理是由MessageConverter来处理的,而默认实现是SimpleMessageConverter,会基于jdk的ObjectOutputStream完成序列化。当一个服务完成后需要调用其他服务,这个服务不需要主动调用其他服务,可以向事件代理者(Broker)发布事件,事件代理者就会通知相应服务执行相关业务,这个服务也不需要等待其他服务执行完直接返回结果给用户即可。工作消息队列:一个队列绑定多个消费者,提高消息处理速度,避免消息堆积。
2024-04-28 15:47:22
1028
3
原创 Docker的使用
镜像是分层结构,每一层称为一个LayerBaseImage层:包含基本的系统函数库,环境变量,文件系统Entrypoint:入口,是镜像中应用启动的命令其他:在BaseImage基础上添加依赖,安装程序,完成整个应用的安装和配置。
2024-04-20 14:45:49
1197
2
原创 Redis分片集群
我们通过故意将一个master端口的Redis宕机,可以发现之后redis自动选取了他的从节点作为新的master,原来的宕机的那个在重新启动后,变成了slave,整个过程不需要哨兵,自动完成。实际业务中,可能由于某台master老旧,就为他添加了新的slave,想要将这个新的slave变成master,实现手动故障转移。而且,如果key时和节点绑定,节点宕机后,数据就丢失了,而和插槽绑定,节点宕机后将他上面的插槽转移即可。如果是新添加一个master,上面一开始是没有插槽的,我们可以使用。
2024-04-13 20:03:50
967
原创 消息队列Redis实现
但是由于$代表读最新的消息,如果我们处理一条消息的过程中,又有超过一条消息到达消息队列,则下次只能获取最新的那条消息,出现漏读消息的问题。消费者可以订阅一个或多个channel,生产者向对应channel发送消息后,所有订阅者都能收到相关消息,就实现了。一般不需要手动创建消费者,当我们指定一个组去监听消息时,如果他发现组中没有消费者,会自动帮我们创建。缺点:不支持数据持久化,无法避免数据丢失,消息堆积有上限,超出时数据丢失。pubsub:基本的点对点消息模型。消息可以回溯,可以被多个消费者读取。
2024-04-07 15:25:07
825
原创 基于Redis实现分布式锁
线程1拿到锁后执行业务完毕,对比完锁中的线程标识和自己的线程标识,正准备释放锁,但此时发生了阻塞(可能是jvm的full gc等问题),锁超时释放,线程2拿到了锁,此时线程1的阻塞结束,释放了锁,线程3又能拿到锁,这样线程2和线程3都在执行业务,产生并发问题。Redisson的可重试不是无休止的等待和重试,而是利用Redis的订阅发布和信号量,在锁彻底被释放时,发布一条消息,正在等待重试的线程一旦接收到这样的消息,就会先判断时间是否超出最大等待时间,没有就进行抢锁,期间也会不断校验是否超出最大等待时间。
2024-03-31 10:13:46
963
1
原创 ConcurrentHashMap源码分析
如果需要添加的链表已经存在哈希表table中,则通过tabAt方法,基于volatile机制,获取当前最新的链表头结点f,由于f指向的是ConcurrentHashMap的哈希表table的某条。如果当前需要put的key对应的链表在哈希表table中还不存在,即还没添加过该key的hash值对应的链表,则调用casTabAt方法,基于CAS机制来实现添加该链表头结点到哈希表。HashMap一样遍历该链表,如果该key对应的链表节点已经存在,则更新,否则在链表的末尾新增该key对应的链表节点。
2024-03-24 15:58:24
762
3
原创 AQS源码分析
自定义同步器的共享方式要么是独占(ReentrantLock),要么是共享(CountDownLatch/Semaphore),但是aqs也支持同时实现独占和共享的两种方式(ReentrantReadWriteLock)每个节点由线程封装,当线程抢夺锁失败后会封装成节点加入aqs队列中,通过cas,自旋以及LockSupport.park()的方式维护state变量状态,获取锁的线程释放锁后,随机从队列中唤醒一个阻塞的节点。Lock接口的实现类基本都是通过聚合了一个队列同步器的子类完成线程访问控制的。
2024-03-17 14:41:34
353
原创 AtomicInteger原理
AtomicInteger的本质:自旋锁 + CAS算法:当一个线程在获取锁时,如果锁已经被其他线程获取,当前线程就会不断循环检查锁是否被释放,直到获取到锁CAS的全成是: Compare And Swap(比较再交换);是现代CPU广泛支持的一种对内存中的共享数据进行操作的一种特殊指令。CAS可以将read-modify-write转换为原子操作,这个原子操作直接由处理器保证。CAS有3个操作数,内存值V,旧的预期值A,要修改的新值B。
2024-03-10 17:26:15
404
原创 ThreadLocal介绍
ThreadLocal中作为map中的key使用,而且ThreadLocalMap中的key是弱引用,弱引用对象在gc时会被回收,而ThreadLocalMap和Thread的生命周期一样长,就会存在key为null的情况,value访问不到,从而引发内存泄漏。ThreadLocal提供了线程局部变量,每个线程都可以通过set和get方法来对这个变量进行操作,但不会和其他线程的局部变量冲突,实现了线程的数据隔离。内存溢出:要求分配的内存超过了系统能给的。
2024-03-02 22:09:10
507
原创 JVM类加载机制
同时,在堆中生成一份与方法区中数据类似的java.lang.Class对象(用来在Java代码中去获取类的信息以及存储静态字段的数据,JDK8之后·这个静态字段数据就存放在堆区)类加载器加载完类后,Java虚拟机会将字节码中的信息保存到方法区,在方法区中生成一个对象InstanceKlass,保存所有类的信息,里边包含实现特定功能,如多态的信息。扩展类加载器和应用类加载器的源码位于rt.jar包中的sun.misc.Launcher.java,是按照jar包的位置来加载字节码文件。这种方式性能比较高。
2024-02-02 18:13:47
1015
1
原创 基础算法--搜索与图论(2)
实际上是对Bellman-ford算法的优化,主要思路是记录哪些点被更新了,再将和这些点有关系的点更新。所有边权重都是正数:朴素Dijkstra算法 n^2,堆优化版Dijkstra算法 mlogn。存在负权边:Bellman-Ford算法 nm ,SPFA 算法 一般是m,最坏nm。图中不能存在负权回路,否则在回路中一直转圈,最短路就变成负无穷即不存在最短路。**单源最短路:**一个点到其他点的最短距离。**多源汇最短路:**起点和终点都是不确定的。到集合的距离:指到集合中的最近的点的距离。
2024-01-27 18:21:10
2056
原创 基础算法--搜索与图论(1)
对于一个序列,对应图上每条边都是起点在终点前面易知,如果存在环的话,就一定不存在拓扑序列所以,有向无环图又被称为拓扑图入度为0的点可以作为起点,所以,拓扑排序步骤如下:把所有入度为0的点入队。
2023-12-31 11:12:39
531
原创 Manacher算法(马拉车)
作用:在On的时间复杂度下,求出字符串每个回文中心的最长回文半径回文半径:以回文中心为起点,到回文串两端的距离如:# a # b # a #以b为回文中心,最长回文半径就是 4如果回文字符串长度为偶数,那么回文中心就无法正好落在某个字符上,所以可以在每个字符之间添加一个“#”做前置处理(包括字符串首尾)
2023-12-19 10:21:59
414
原创 算法--数据结构基础
在读数据的同时维护一个栈,如果栈不为空,就比较栈顶元素和当前要加入的元素的大小,如果大于或等于当前元素,就将栈顶元素弹出,直到新的栈顶元素比当前元素小,就停止循环弹出栈顶元素,如果此时栈不为空,那么栈顶元素即答案,栈为空答案为-1,最后将当前元素入栈。定义数组q[ ] ,hh为头下标初始为0,tt为尾,初始为-1,尾部添加元素,添加时,q[++tt] = x,头部删除,删除hh++即可。size - -;查看队列是否为空,只用看hh<=tt,如果是,不为空,不是就为空,查看队头元素只用看q[hh]
2023-12-16 10:16:14
1098
1
原创 JVM垃圾回收
再次创建对象,如果伊甸园区又满了,再次触发Minor GC,这时不仅会回收伊甸园垃圾,也会回收幸存区垃圾,再将可用对象(伊甸园区和幸存区from)复制到TO中,之后交换两个幸存区,并让幸存区中对象寿命+1。软弱引用还可以配合,引用队列使用,因为软引用,弱引用本身就是一个对象,当他们所引用对象被回收时,他们就会进入这个引用队列,因为他们自身也会占有一定内存,如果想对他们的内存进行释放,就需要引用队列。在对象中添加一个引用计数器,当有地方引用时计数器就加一,引用失效时计数器减一,当计数器值为0时,进行回收。
2023-12-10 10:30:06
1939
原创 JVM运行时数据区域
现代垃圾收集器大部分都是基于分代收集理论设计的,如新生代,永久代等,而这些仅仅是一部分垃圾收集器的设计风格而已,不是虚拟机固有布局,也不是对堆的进一步细致划分。Java堆既可以是固定大小的,也可以是可扩展的,目前主流的虚拟机都是按照可扩展来实现的,如果堆中没有内存完成实例分配,并且堆无法扩展时,将抛出OOM异常。无论从哪个角度,堆中存储的都只能是对象的实例,将Java堆细分只是为了更好的回收内存,更快的分配内存。相对来说,方法区垃圾收集比较少见,这部分内存回收的目标是针对常量池的回收和对类型的卸载。
2023-12-02 22:43:24
2003
原创 基础算法学习
就是再定义一个长度和要存放数据的数组(a)等长的数组(s),在初始化存放数据数组时,将这个数组也初始化,每个位置存放前一个位置(s[i - 1])和 a[i] 的和。其中a数组和s数组下标最好都从1开始,这样在初始化前缀和数组时,是s[i] = s[i - 1] + a[i] 这里的i - 1,就不用单独判断。构造差分数组不是核心,差分数组的构造可以看做,将元素一个一个按照规则添加进一个全为0的差分数组中,核心是添加进差分数组的规则。快排同理,虽然每次不一定是平分的,但是期望是平分的。
2023-11-26 23:01:41
1156
原创 HashMap源码分析
HashMap会根据用户指定的初始容量获取一个既大于 cap 又最接近cap的 2的整数次幂数值作为阈值。如果key == null 返回0,key的hashCode值的高16位异或低16位。一个数字左移一次就是乘2 左移2次就是乘两次2。HashMap底层数组长度为何总是2的n次方。把高低位都利用起来,减少hash冲突。JDK1.8中HashMap的改变。
2023-11-19 16:44:45
61
原创 MySQL事务和Redis事务对比
批量操作在执行exec命令前被放入队列缓存中,并没有被实际执行,也就不存在事务内的查询会被看到,事务外的看不到,从而也不会出现并发事务问题。单条命令的执行是保证原子性的,而事务是不保证的,且没有回滚,事务中任意命令失败,其他命令仍会执行。因为事务的隔离性,可能会引发一系列问题。性能逐渐降低,安全性逐渐升高。
2023-11-06 21:13:47
202
原创 Redis缓存穿透与雪崩
指某个时间段,缓存集中过期失效,于是所有的请求都会达到存储层,集中创建缓存,存储层的调用量会暴增,造成周期性压力。其中,最要害的问题,就是数据的一致性问题,从严格意义上讲,这个问题无解。这个key过期的瞬间,持续的大并发就穿破缓存,直接请求数据库,同时回写缓存,这时给数据库造成很大压力。Redis 缓存的使用,极大的提升了应用程序的性能和效率,特别是数据查询方面。数据库和缓存中都没有,这样缓存无法拦截,也无法在数据库中查询到存到缓存中,查询一个数据,如果缓存中存在,则返回数据。另外的一些典型问题就是,
2023-08-28 08:20:12
60
原创 Redis主从复制——哨兵模式
假设哨兵1先检测到master宕机,系统不会马上进行failover(故障转移) 过程,仅仅是主观下线,等到一定数量的哨兵检测到主机宕机,就会进行一次投票选取新的主机,切换成功后,会通过发布订阅模式,各个哨兵告诉自己监控的从机切换主机,称为客观下线。哨兵模式是一种特殊的模式,首先 Redis 提供了哨兵的命令,哨兵是一个独立的进程,它会独立运行。在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务,分担服务器负载。当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复。
2023-08-20 07:57:45
87
原创 Redis订阅发布
这些命令被广泛用于构建即时通信应用,比如网络聊天室(频道当做聊天室,将信息回显给所有人)和实时广播、实时提醒等。Redis客户端可以订阅任意数量的频道。redis发布订阅是一种消息通信模式。稍微复杂的场景会用消息中间件 MQ等。发布(pub) 订阅(sub)
2023-08-13 08:25:18
56
原创 Redis持久化——RDB AOF
先将数据写入一个临时文件,等持久化过程都结束了,再用这个临时文件替换上次持久化好的文件,整个过程主进程不进行IO操作,确保及高性能。会单独创建一个子进程来进行持久化(fork作用是复制一个与当前进程相同的进程,这是个全新的进程,作为原来进程的子进程)Redis是内存数据库,如果不将内存中的数据库状态保存到磁盘,一旦服务器进程退出,数据库状态将丢失,以日志的形式将所有的命令都记录下来(读数据操作不记录),恢复时,将这个文件全部执行一遍。aof默认是文件的无限累加,文件越来越大,所以设置了重写机制。
2023-08-05 21:55:18
53
原创 Redis基础学习
redis基于内存操作,所以 cpu不是redis的性能瓶颈,redis的瓶颈是网络带宽和内存,可以使用单线程来实现。Redis中单条命令的执行是保证原子性的,而事务是不保证的,且没有回滚,事务中任意命令执行失败,其余命令仍会被执行。若命令中存在语法错误(类似Java中的1/0,运行时异常),执行exec时,错误命令抛出异常,其它命令正常执行。redis将所有数据放在内存中,所以使用单线程效率最高,多线程会有cpu中的上下文切换,这是耗时操作。位图,也是radis的数据结构。如果数据较多,可能会有误差。
2023-07-30 11:23:15
72
2
原创 SpringBoot整合Druid数据源并配置数据监控
springboot2.0以上默认使用com.zaxxer.hikari.HikariDataSource数据源,可在配置文件中使用spring.datasource.type 自定义数据源。如果允许时报错 java.lang.ClassNotFoundException: org.apache.log4j.Priority,则导入 log4j 依赖即可。配置完毕后,访问 :http://localhost:8080/druid/login.html 即可。数据源切换成功后,可以设置相关属性。
2023-06-11 08:59:44
866
原创 Spring事务 过滤器和拦截器的区别
在业务层,通常在接口中(而非实现类)的要开启事务的方法上写注解@Transactional,以此来降低耦合(注解事务可以添加到业务方法上表示方法开启事务,告诉Spring,在Spring的配置类中写@EnableTransactionMangment,开启事务管理驱动。Spring事务并不是每次遇到异常都自动回滚,只有遇到error系异常和运行时异常才会自动回滚。想要其他的异常也能自动回滚,需要设置@Transactional中的。若要改变事务传播行为,可对该事务中的@Transactional中的。
2023-06-04 11:46:38
68
原创 Spring相关概念 IoC思想
spring可以降低代码书写的耦合度(因为实现业务层逻辑时,我们需手动创建service的对象,如果service发生改变,需重新创建新的对象,下面的代码也需重新调试,很麻烦)解决方案:使用对象时,在程序中不要主动使用new产生对象,转换为由提供对象。
2023-05-21 17:12:52
47
原创 AOP和拦截器
返回后通知:@AfterReturning底层,value属性用来存放切入点表达式,returning属性用来存放获取的返回值,所以想获取返回值,可以这样做。环绕通知中获取了参数数组后,可将这个参数传递给proceed方法,即传回给原始方法,且在传回之前,可对参数数组进行操作,操作完再传回,生效。:多个连续的任意符号,可独立出现,常用于简化包名与参数的书写。*:单个独立的任意符号,可独立出现,也可作为前缀或后缀。只有环绕通知,抛出异常后通知可以获取异常。只有返回后通知,环绕通知可以获取返回值。
2023-05-07 09:55:38
229
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人