- 博客(26)
- 收藏
- 关注
原创 Feed流推拉模式设计:高并发场景下的性能优化之道
Feed流是一种内容分发机制,指讲一些动态更新的内容排序后主动推送给用户。它的核心就是“内容流”,比喻成一个信息瀑布主动流向用户,狭义上说用户不需要自己去查询。典型的场景使用例如常用的新浪微博,用户登录进入后,展现给我们的就是feed信息流。新浪微博的信息,来自于你关注人所发布的内容。还有微信的朋友圈,今日头条的信息流,好友发布的美拍等,这些都是Feed。
2025-06-14 23:37:55
151
原创 Redis网络模型
在这之前我们先了解一下io,网络io又可以为,BIO(阻塞io),NIO(非阻塞io)AIO(异步io)。BIO:当我们应用层想去获取数据时,由于操作系统还没有我们想要的数据,此时recvfrom函数会一直等待直到能获取数据,这个等待的过程就像被阻塞了一样。NIO:当我们每一次调用recvfrom函数获取数据时,由于数据不存在,操作系统会直接返回结果,并不断的发起recvfrom直到获取数据。就像你们追心爱的女神一样,尽管被拒绝多次,还不停的示爱,总觉得他一定会返回你想要的结果。
2025-03-07 23:48:23
570
原创 redis分布式锁
在分布式系统下,通过锁机制来控制资源的访问,与传统的单体项目中的sychrise,他是基于jvm的锁,即在一个springboot服务下能保证线程同步的问题,但现在我们大部分的项目部署不局限于一台服务器,此时会出现多把jvm锁无法保证对数据的互斥原则。分布式锁就像是把锁单独抽出来为一个应用,让所有springboot项目公用同一把锁。
2025-03-06 14:55:23
926
转载 Redis底层数据结构
redis是通过对象来表示存储的数据的,redis 也是键值对存储的方式,那么每存储一条数据,redis至少会生成2个对象,一个是redisObject,用来描述具体数据的类型的,比如用的是那种数据类型,底层用了哪种数据结构,还有一个对象就是具体存储的数据。这个存储对象数据就是通过redisObject这个对象的指针来指引的。
2025-01-09 22:55:38
96
转载 Java限流
限流是对某一时间窗口内的请求数进行限制,保持系统的可用性和稳定性,防止因流量暴增而导致的系统运行缓慢或宕机。在高并发系统中,出于系统保护角度考虑,通常会对流量进行限流。在分布式系统中,高并发场景下,为了防止系统因突然的流量激增而导致的崩溃,同时保证服务的高可用性和稳定性,限流是最常用的手段。本文介绍的实现方式属于应用级限制,应用级限流方式只是单应用内的请求限流,不能进行全局限流。假设将应用部署到多台机器,我们需要分布式限流和接入层限流来解决这个问题。
2025-01-07 23:48:35
73
原创 排序算法——堆排序
建立好大根堆后,堆顶就是数组里面最大的元素,如果要实现堆排序只需要每次移除这个堆顶元素,然后将堆尾元素替换,再重新以堆顶进行调整。每一个节点都当作是一个大根堆,我们通过维护每一个节点的堆结构进而将整个二叉树变成堆。由于叶子节点没有子节点,所有不需要对他维护。堆中某个节点的值总是不大于或不小于其父节点的值;大根堆:根节点最大,每个节点都小于或等于父节点。小跟堆:根节点最小,每个节点都大于或等于父节点。小根堆代码实现类似不在赘述 大家可以自己实现。堆又可以分为大根堆和小根堆。堆总是一棵完全二叉树。
2025-01-06 19:35:54
363
原创 数据库与缓存一致性的问题
缓存一致性问题主要表象就是查缓存得到的数据跟数据库不一致。问题出现在当我们对数据更改的时候,缓存更新和数据库更新两个操作到底谁先执行。即再操作结束之后的很短时间在删一次缓存,这样再查数据库的时候就能保证是新的数据并写入缓存中。可以使用分布式锁,保证线程1在执行的时候,线程二只能阻塞等待。显然无论是先删缓存还是先更新数据库,都会存在不一致的问题。,然后再同步到缓存中,这也能保证最终一致性。结果缓存中的数据跟数据库不能保持一致。有一个能保证最终一致性的解决方案就是。先删缓存再更新数据库。
2025-01-05 23:49:35
139
原创 Redis缓存三剑客
我们要知道我是引路缓存的主要目的是减少大量对数据库的直接访问请求导致数据库扛不住这么多并发而宕机。如果单单只把数据放入缓存这个操作,在某些情况下还是会发生大量请求打在数据库。比如当我们一个(经常被访问的数据)突然过期了,从缓存中获取不到数据就会从数据库中查,如果此时有大量的请求,这些请求都会打在数据库层面而数据库扛不住。1.很容易想到的就是不给这个热key设置过期时间,让他们。2.提前通过的方式将他们全部写入缓存可以避免大量的请求访问3.使用来控制访问数据库的请求数量。下面我用代码演示一下第3种方案。
2025-01-04 23:39:54
995
原创 mysql索引
表示连接的类型,性能有好到差的连接类型 NULL,system,const,eq_ref,ref,range,index,all。查看当前sql的执行频率。1.最左前缀法则:如果使用了联合索引,查询时从最左侧索引开始且最左侧索引必须存在否则将不使用索引,且不跳过任何一个索引,如果跳过某一列索引,则从该列索引之后(包括自己)的索引都会失效。再考虑使用索引前,你需要关注当前业务主要的业务功能,是增删改比较多占的比重多还是查询占的比重多,如果业务需要进行频繁的查询操作,这是可以考虑使用索引可以大大提高效率。
2025-01-03 23:28:54
905
原创 cookie、session、Token区别
Session是一段服务器上的存储区域,用于存储用户信息和状态。session 是基于 cookie 实现的,session 存储在服务器端,sessionId 会被存储到客户端的cookie 中。cookie由服务器生成,发送给浏览器,浏览器把cookie以kv形式保存到某个目录下的文本文件内,下一次请求同一网站时会把该cookie发送给服务器。由于cookie是存在客户端上的,所以浏览器加入了一些限制确保cookie不会被恶意使用,同时不会占据太多磁盘空间,所以每个域的cookie数量是有限的。
2025-01-02 23:57:56
240
原创 设计模式之单例模式
然而在高并发的情况下,不管该对象是否已经创建了,每调用一次getINSTANCE都要走一遍锁的逻辑,效率是在的太低下了。的问题,比如线程1在还没有成功new之前,线程2已经判断INSTANCE为null,此时两个线程都会new一个对象从而违反了单例模式。Singleton(单例模式)就是指只能被实例化一次的类,实现单例模式的类无法被继承,原因是构造方法被设为私有。还有一个点,就是无论懒汉式还是饿汉式,都不能保证实例的唯一性,因为我们仍可以通过。的机制来获取到类的私有方法来创建实例。但是懒汉式的方式存在。
2025-01-01 21:42:57
367
原创 MVCC版本并发控制
为了理解,你可以把它当作是一个记录副本,在不同事务隔离级别下快照读的方式是不一样的,在RC隔离级别下,事务中的每一次select都会创建一个快照,记住是每一次,而在RR隔离级别下,事务中的第一次select会创建快照,其他select都是读取这个快照,主要是为了解决不可重复读的问题,上篇文章说过。1.当前记录的事务id如果等于create_try_id,是不是说明该记录的版本是当前记录事务更改的,我自己的事务是不是能读到我自己所修改的内容。,指的是最近的一次修改该记录的事务id,事务的id是自增的。
2024-12-25 11:44:01
265
原创 Mysql进阶
举个例子,在一个商城系统中,如果我们在数据备份的时候,一个用户来下单了,此时插入一条订单数据并同步在数据备份中,用户在数据备份结束的时候后支付完该订单,此时备份的数据并不知道这个操作,这就是数据不一致的问题。事务就是一些sql的集合,为什么要有事务,你想想如果没有事务,此时你有一万条sql要执行,执行一般服务突然就挂了,那你怎么知道我的这些sql到底执行到哪一条?还记不记得我们上面说的间隙锁,当根据主键查询不存在的数据时,就会为该主键值所在的两个记录的间隙加上锁,这样线程二就会被阻塞,解决了幻读的问题。
2024-12-24 12:33:57
866
原创 springboot自动配置原理
2.其中@EnableAutoConfiguration是实现自动化配置的核心注解。该注解通过@import注解导入对应的配置选择器。内部就是读取了该项目和该项目引用的jar包的classpath路径下的META-INF/spring.factories文件中的所配置的类的全类名,在这些配置中所定义的Bean会根据条件注解来决定是否要将其导入到容器中。条件注解会像@conditionOnclass这样的注解,判断对应的class文件,如果有则加载该类,把这个配置类的所有bean注入到容器中去。
2024-10-08 11:04:48
191
原创 Spring事务传播方式
main方法和test方法都存在事务,所以当main方法出现异常时,main方法将回滚,但不影响test方法,应该两者时不同的事务互不影响,所以结果只有test方法插入成功。mian方法存在事务,当test方法出现异常时,test方法会回滚,但不影响原事务(main方法里面的事务),所以结果只有main插入成功。如果当前存在事务,则在嵌套事务(你可以简单理解就是原事务)中执行,但嵌套事务的执行不影响原事务,如果不存在,则创建一个新事务。当前如果没有事务将创建一个事务,如果当前存在事务,还是会创建一个事务。
2024-09-27 17:32:19
640
原创 SpringBean生命周期
45销毁:当Bean不在需要时,Spring会调用Bean的销毁方法进行资源的释放清理工作。这个方法可以通过实现DisposableBean接口的destory方法,或者在配置文件通过destory——method属性指定。1.Bean的实例化:spring会根据bean的配置信息或者注解,通过反射机制调用构造函数创建实例对象此时类的所有参数都被设为默认值。2.属性赋值:实例化之后,通过依赖注入或者属性赋值将bean的属性值设置好。4.使用初始化完成后,Bean进入可以使用的状态,可以被其他对象引用。
2024-09-27 10:19:01
342
原创 SpringAOP原理
在AOP编程中,如果一个类被标记为目标对象,则spring的IOC容器会为该类生成一个代理对象,在获取此目标对象的时候,返回的式代理对象。在调用代理对象的方法时,会依次执行目标对象的前置通知,目标方法,目标方法的后置通知。Aop(Aspect Oriented Programming)面向切面编程,指的是抽取重复加在业务前后的代码,通过切面的方法应用在目标方法上。1.连接点:连接点是一个非常抽象的概念,它表示一个时机,比如某个方法方法执行前后,或者方法出现异常时都是连接点。目标方法通常指切点映射的方法。
2024-09-13 17:11:53
1238
原创 jvm内存结构
程序计数器是用来存储字节码指令地址的,虚拟机在将字节码指令读取到内存中之后,会将源文件中的偏移量转化为内存地址。每个字节码指令都有一个内存地址。存放运行时的一些局部变量,本质是类似一个数组,每一个局部变量对应一个下标,和若干个卡槽,不同类型的局部变量分配的卡槽数量不同int是一个,long是两个。3.2当方法正确执行或者出现异常时都会将当前栈帧弹出,同时返回上一个栈帧中的第一条指令地址,所以帧数据应该存储上一个栈帧的第一条指令地址,这个就叫方法出口。分为虚拟机栈,本地方法栈,程序计数器,堆,方法区。
2024-08-24 22:40:12
507
原创 类的加载器
当我们需要加载一个类的信息时,他会先从应用程序加载器判断该类是否有没有被加载,如果没有,则会抛给扩展类加载器,扩展类加载器也没有的话,会交给启动类加载器。如果这些加载器都没有加载过当前类的话,则会再从启动类加载器开始向下判断能否加载该类。2.能够避免恶意代码替换jdk中核心的类库,比如,我在外层自定义一个java.lang.string类,启动时,这个类并不会被类加载器加载。第一类加载器主要加载一些自定义的类和一些通用的类,这类加载器包括。1.能够避免重复加载某一个类,每个类只能由一个加载器加载。
2024-08-23 13:28:35
455
原创 jvm——类的生命周期
验证字节码内容是否复合java虚拟机规范,包括一些版本号啊,魔数(用来标识只属于java的.class文件),元信息验证,例如类必须有父类,还有一些执行指令的语义,是否访问其他类中的privcate方法等等。3.访问一个类的静态方法或者静态变量,(注意,用final修饰的静态变量不会导致类的初始化,因为用final修饰的静态变量,在准备阶段就会直接赋值而不是赋予初始值)类的生命周期分为加载——连接——初始化——使用——卸载,连接又可以分为验证——准备——解析。将常量池中的符号引用替换为直接引用。
2024-08-22 22:58:17
416
原创 设计模式之工厂模式
可以发现,我们创建对象的过程存在业务代码里面,当我们需要新增一个咖啡品种的时候,就需要动业务代码,这样不利于维护。我们可以利用工厂思想,将对象创建的过程另置再一个工厂类中,然后再业务层调用工厂来下单咖啡,这样就能将业务层和coffee实现类解耦。如果有一个场景,当我们需要对产品进行品牌标识,一个品牌可以用多个产品,一个产品可以属于多个品牌,如果继续按上面。这样,每个咖啡都有自己对应的工厂制作,解决了工厂和实现类的耦合,这样就完全完全符合“来实现,有N个产品,N个品牌的话,就需要创建N*N个产品类和工厂类。
2024-08-08 22:07:20
476
原创 用静态工厂方法代替构造器
如何对于小型的枚举类型,RegularEnu'm'Set的性能优势不复存在,这个类就有可能再未来发行版中被删除,而这不会造成任何不良的影响,同样的,如果能提升性能,未来的发行版本中可能会添加Enum的第三个甚至第四个实现,客户端即不知道也不关心他们从这个静态工厂方法得到的对象的具体类,他们只关心一点,这类是EnumSet的某个子类。这个例子展示了静态工厂方法在JDBC服务提供者框架中的应用,其中返回的对象的类在编写包含该方法的类时并不一定存在,而是根据具体的实现在运行时动态加载和使用。
2024-08-03 21:12:09
716
原创 rabbitmq
rabbitmq是一个异步处理消息的框架,在一个商品下单的项目中,用户成功下单后,需要扣除金额,产生订单信息,发送短信通知等等,如果整个业务逻辑都写再一个service层,则就会导致请求耗时大大增加,在高并发的场景下,这是不可取的。而rabbitmq则能帮我们解决这个问题。当业务逻辑本身是异步操作时,我们就可以利用mq异步来处理来减少业务执行的耗时时间。
2024-07-25 20:31:25
1433
原创 String为什么是不变的
这是因为String字符串一但初始化了,其值就无法改变了,当我们再给他赋值的时候,实际是重新new了一个新的字符串。你会发现,String类和存储value的数组都用了final修饰,这就意味着String不会有子类修改他的行为,他的值也无法被修改。当我们初始化了一个字符串“a”后,先打印他的哈希值,然后,我们再将字符串“a”重新赋值,再打印他的哈希值。第二,可以保证其哈希值不会频繁变更,毕竟string常作于哈希表的键,频繁的变革键值,哈希表性能会很差。要知道String的为什么不变的先要知道。
2024-07-25 20:28:08
258
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人