- 博客(1139)
- 收藏
- 关注
原创 【Docker】容器操作
docker run,这个命令不仅仅可以帮助我们创建一个容器,而且还可以让这个容器处于运行状态。容器除了运行状态,还会有暂停、停止这两个状态。运行:进程正常运行暂停:进程暂停,CPU不再运行,并不释放内存停止:进程终止,回收进程占用的内存、CPU等资源可以让容器从运行进入暂停。可以让容器从暂停恢复运行。可以让容器从运行变成停止。可以让容器从停止恢复运行。停止和暂停差别主要在于操作系统的处理方式。
2024-11-10 08:50:13 400
原创 【Docker】镜像操作
如下图:这里有一个mysql:5.7的镜像,冒号前的mysql就是一个repository,而冒号之后的5.7就是tag(版本),合一起就是镜像名称,代表5.7版本的MySQL镜像。Usage后面给出的是命令的示例,IMAGE:你要导出的是哪个镜像,写的是镜像的名字。点进去后,可以看见它有很多不同的版本,如果不指定版本的时候,它就是默认最新版(latest), 它的作用就是:列出所有的镜像,并且还有各种各样的参数,每个参数什么含义这里都有说明。在没有指定tag时,默认是latest,代表最新版本的镜像。
2024-11-10 08:49:20 994
原创 【Docker】CentOS安装Docker
Docker可以安装在各种系统上。企业部署一般都是采用Linux操作系统,而其中又数CentOS发行版占比最多,因此我们在CentOS下安装Docker。Docker 分为 CE 和 EE 两大版本。CE 即社区版(免费,支持周期 7 个月),EE 即企业版,强调安全,付费使用,支持周期 24 个月。Docker CE 分为stabletest和nightly三个更新频道。官方网站上有各种环境下的安装指南,这里主要介绍 Docker CE 在 CentOS上的安装。
2024-11-08 20:43:51 900
原创 Docker架构
为了避免这些重复劳动,人们就会将自己打包的应用镜像,例如Redis、MySQL镜像放到网络上,共享使用,就像GitHub的代码共享一样,GitHub是做代码托管的,而DockerHub是做镜像托管的。比如之前讲过的MySQL镜像,它里面就有各种各样所需要的依赖,这些东西最终落地到硬盘,其实就是硬盘中的文件,例如下图有MySQL写数据的data目录文件、还有logs日志文件、bin里的可执行文件,还有就是MySQL所需要的各种各样的函数库了。这个文件包是只读的。及其运行的操作系统依赖打包,形成QQ镜像。
2024-11-08 20:42:54 546
原创 【Docker】Docker和虚拟机的区别
我们的虚拟机它是在一个系统里装了另外的一个系统,所以当应用执行时它会以为自己在一台真实的电脑上,因此它会去调用这个内置的操作系统,然后它再与Hypervisor进行交互,然后再把信息传递给了我们的web操作系统,web操作系统再去调用计算机硬件,于是我们的应用执行就完成了,此时它经过了层层的传递,所以它的性能相对来讲是比较差一点的。Docker可以让一个应用在任何操作系统中非常方便的运行。并且虚拟机启动的时候需要启动虚拟的计算机的操作系统,等于把这个计算机重启了一遍,然后再去启动虚拟操作系统上面的应用。
2024-11-01 10:03:36 465
原创 【Docker】初识Docker
可以将程序及其依赖、运行环境一起打包为一个镜像,可以迁移到任意Linux操作系统运行时利用沙箱机制形成隔离容器,各个应用互不干扰启动、移除都可以通过一行命令完成,方便快捷。
2024-11-01 10:02:55 668
原创 【MySQL】数据库中有个字段为JSON,需求:筛选JSON里面的字段
需求:写出mapper xml文件,我想要查找sys_data表中data字段,其中data字段是一个JSON,图二中的map参数,需要让JSON中的key与map中的key相等并且value也相等的数据,图三为sys_data表结构,请拿map中存储’key1’->'1’举例。
2024-09-11 18:15:04 406
原创 MyBatisPlus3向数据库中存入List
官网:https://baomidou.com/guides/type-handler/#%E9%85%8D%E7%BD%AE。
2024-08-17 17:06:52 427
原创 【SpringCloud】搭建eureka-server(Eureka注册中心)
依赖的结尾是:eureka-server,说明它是eureka的服务端依赖,中间的starter,是SpringBoot里面的自动装配,也就是说在这个依赖里面已经把eureka所有的配置都已经做好了,也就是说我们可以做到0配置就能拿来用了。如果有多个,则以逗号隔开,但由于这里是单机,所以这里配的是自己。后面显示不像IP的原因是,这里是windows,后面显示的是计算机名,理论上讲,这里应该显示ip,这里理论上讲可以理解成:localhost(即自己电脑的名称)这里的服务名称和服务地址其实是在做服务注册。
2024-08-08 11:05:23 1322
原创 【SpringCloud】Ereka-eureka原理分析
这样的一种写法,它其实是有一定问题的:在公司里开发的时候,我们会有开发环境、测试环境、生产环境等等,每一次环境的变更,可能服务的地址也会发生变化。然后再利用负载均衡从三个user-service中挑一个,向挑好的发请求,并且挑好的这个不可能是挂的,因为服务每隔30秒钟都会向Eureka发一次心跳,来确认一下自己的状态。如果有一天它不跳了,就会把它从列表中剃掉。这些问题都需要利用SpringCloud中的注册中心来解决,其中最广为人知的注册中心就是Eureka,其结构如下,起到的作用就是:记录和管理微服务。
2024-08-07 12:10:37 729
原创 【SpringCloud】Kureka-提供者与消费者
但是,服务提供者与服务消费者的角色并不是绝对的,而是相对于业务而言。如果服务A调用了服务B,而服务B又调用了服务C,服务B的角色是什么?:一次业务中,调用其它微服务的服务。(调用其它微服务提供的接口):一次业务中,被其它微服务调用的服务。(提供接口给其它微服务)提供者与消费者角色其实是。
2024-08-07 12:09:52 329
原创 【SpringCloud】服务拆分-服务远程调用
在order-service服务中,有一个根据id查询订单的接口:根据id查询订单,返回值是Order对象,如图:其中的user为null在user-service中有一个根据id查询用户的接口:修改order-service中的根据id查询订单业务,要求在查询订单的同时,根据订单中包含的userId查询出用户信息,一起返回。从订单模块向用户模块发起远程调用,然后把查到结果做一个组合。
2024-08-07 12:09:22 461
原创 【SpringCloud】认知微服务-SpringCloud
其中,Hoxton 是 Spring Cloud 的一个大版本系列名称,而 .SR10 表示它是 Hoxton 系列的第10个 Service Release(修正版或更新版)。在软件开发中,Service Release 通常是针对前一个正式版发布之后收集到的问题和需求进行修复与改进的一个版本,相比于主要版本更新,它更注重于对现有功能的稳定性和错误修复。这些功能其实大多数都是从其他公司开源的组件整合进来的。我们课堂学习的版本是 Hoxton.SR10,因此对应的SpringBoot版本是2.3.x版本。
2024-08-07 12:08:13 391
原创 【SpringCloud】微服务技术对比
所以阿里巴巴也认识到了这一点,因此在近几年,其实也是在不断地去奋起直追,想办法追赶SpringCloud的脚步,它逐渐的实现了自己的注册中心、配置中心、服务监控等等组件,形成一套技术栈,起了个名字叫:SpringCloudAlibaba。首先,它们都需要去做微服务的拆分,形成微服务集群。将来如果需要有些配置要修改,手动修改会十分麻烦,所以在微服务里面还会有一个配置中心,可以统一的去管理整个微服务群的配置,如果将来有变更,我们也可以利用通知的方式去让对应的服务监控到配置的变化,从而实现配置的热更新。
2024-08-07 12:07:37 722
原创 【SpringCloud】服务架构演变
单体架构特点?简单方便,高度耦合,扩展性差,适合小型项目。例如:学生管理系统分布式架构特点?松耦合,扩展性好,但架构复杂,难度大。适合大型互联网项目,例如:京东、淘宝微服务:一种良好的分布式架构方案优点:拆分粒度更小、服务更独立、耦合度更低缺点:架构非常复杂,运维、监控、部署难度提高。
2024-08-07 12:07:02 1107
原创 【Redis】分布式锁-Redission快速入门
并且官方还提供了一个Redission-springboot-starter,但这种方式并不推荐大家去使用,因为它会去替代spring官方提供的对于redis的这套配置和实现。Redission的配置其实有两种方式,这是一种利用Java配置方式来实现,事实上它也可以利用yml文件跟SpringBoot去整合实现。注入RedissonClient。
2024-08-07 12:04:37 233
原创 【Redis】分布式锁-redission
我们一路走来,利用添加过期时间,防止死锁问题的发生,但是有了过期时间之后,可能出现误删别人锁的问题,这个问题我们开始是利用删之前 通过拿锁,比锁,删锁这个逻辑来解决的,也就是删之前判断一下当前这把锁是否是属于自己的,但是现在还有原子性问题,也就是我们没法保证拿锁比锁删锁是一个原子性的动作,最后通过lua表达式来解决这个问题。
2024-08-07 12:03:55 1079
原创 【Redis】利用Java代码调用Lua脚本改造分布式锁
现在我们实现的分布式锁其实就已经是一个生产可用的、相对完善的分布式锁了。小总结:基于Redis的分布式锁实现思路:获取锁的时候利用set nx ex获取锁,set nx目的是互斥,确保只有一个线程能拿到锁,ex是一个兜底方案,防止宕机导致锁无法释放。释放锁时先判断线程标示是否与自己一致,一致则删除锁,防止误删并且使用Lua脚本保证它的原子性,这样避免在多线程的情况下因为阻塞导致的误删。那这样的分布式锁有什么特性呢?利用set nx满足互斥性。
2024-08-07 12:03:23 673
原创 【Redis】Lua脚本解决多条命令原子性问题
而且它事务中多个操作,其实是一个批处理,是在最终一次性趣执行的,也就是说没有办法先去查询,然后判断,最后释放。因为编写这个脚本的是一个叫做Lua的编程语言,并且我们不需要熟练精通Lua语言,你只需要懂它的一些基本用法就行了,它的基本语法大家可以参考网站:https://www.runoob.com/lua/lua-tutorial.html,我们最终要做的事情是:利用Lua语言编写脚本调用redis。表示参数的数量,我们这个脚本内容全都是写死的,内容固定的,脚本可以理解为一个函数,里面有一堆的代码。
2024-08-07 12:02:47 358
原创 【Redis】分布式锁的原子性问题
同样的是线程1一上来就申请锁,线程1现在持有锁之后,在执行业务逻辑过程中,他正准备删除锁,而且已经走到了判断锁标识的过程中,由于这把锁是自己的,因此肯定返回ok,紧接着就要执行释放锁的动作了。锁一旦超时释放,其他的线程又可以乘虚而入了,例如此时线程2进来,由于锁被释放掉了,因此它可以继续获取锁,可以开始执行自己的业务,而就在他获取锁成功的那一刻,如果GC结束了,阻塞结束,我们的线程恢复运行,此时它就会去执行释放锁的动作了,因为判断已经执行过了,它认为锁还是自己的,但现在锁已经是线程2的了。
2024-08-07 12:02:12 234
原创 【Redis】解决Redis分布式锁误删问题
之前使用的是线程的id,线程id是一个递增的数字,JVM内部每创建一个线程,它的数字就会递增。但是如果我们是在集群的模式下,我们有多个JVM,这样一来,每个JVM内部都会维护这样一个递增的数字,那两个JVM很有可能出现线程id冲突的情况,所以说我们直接使用线程的id去作为线程标识是不够的,我们还要去区分不同的JVM,让它们产生一些差异,因此这里使用UUID。总结:在存入锁时,放入自己线程的标识,在删除锁时,判断当前这把锁的标识是不是自己存入的,如果是,则进行删除,如果不是,则不进行删除。
2024-08-07 11:58:13 937
原创 【Redis】Redis分布式锁的实现核心思路
我们利用redis 的setNx 方法,当有多个线程进入时,我们就利用该方法,第一个线程进入时,redis 中就有这个key 了,返回了nil;还有一种方式就是非阻塞式的获取,也就是说我来尝试获取锁,如果我获取失败了,我就会立即结束,返回一个结果,而不是一直尝试一直等待。其实在我们JDK中提供的锁有两种机制,一种是:如果获取失败,就会阻塞等待,等到有人释放锁为止,也就是说是一种阻塞式的获取。因此我们会利用非阻塞的方式,也就是说我尝试一次,成功返回true,失败返回false,然后我就不再尝试了。
2024-08-06 20:50:31 274
原创 【Redis】分布式锁
经过上节课的演示,可以发现在集群模式下synchronized锁失效了,synchronized只能保证单个JVM内部的多个线程之间的互斥,而没有办法让我们集群下的多个JVM进程之间互斥,要想解决这个问题,我们必须使用分布式锁。
2024-08-06 20:49:40 1559
原创 【Redis】优惠券秒杀 —— 一人一单
但是以上代码还是存在问题,问题的原因在于当前方法被spring的事务控制,如果你在方法内部加锁,可能会导致当前方法事务还没有提交,但是锁已经释放也会导致问题,因此当方法结束后,锁其实就已经释放了,锁释放了就意味着其他线程可以进来了,而此时因为事务尚未提交,如果有其他线程进来去查询订单的话,那我们刚刚新增的这个订单还没有写入数据库,因为你还没提交事务,因此这个线程查询的时候依然不存在,就有可能出现并发安全问题。思考一下,像这种秒杀券(特有券),它的优惠力度非常大,商家可能会赔本,那这种券的目的是什么?
2024-08-06 20:46:14 812
原创 【Redis】乐观锁解决超卖问题
超卖这样的线程安全问题,解决方案有哪些?1.悲观锁:添加同步锁,让线程串行执行优点:简单粗暴缺点:性能一般2.乐观锁:不加锁,在更新时判断是否有其它线程在修改优点:性能好缺点:存在成功率低的问题有些业务中不是库存,它只能通过数据有没有变化来去判断是否安全,这种情况下想要提高成功率,我们还可以采用分批加锁的方案,即分段锁,即我可以将数据的资源分成几份,例如库存总共是100,我可以将100库存分到十张表中,每张表中库存量是10,然后抢的时候就可以去多张表中分别抢,这样一来成功率相当于提高了十倍。
2024-08-06 20:45:21 801
原创 【Redis】库存超卖问题分析
乐观锁:会有一个版本号,每次操作数据会对版本号+1,再提交回数据时,会去校验是否比之前的版本大1 ,如果大1 ,则进行操作成功,这套机制的核心逻辑在于,如果在操作过程中,版本号只比原来大1 ,那么就意味着操作过程中没有人对他进行过修改,他的操作就是安全的,如果不大1,则数据被修改过。,因为之前查询出来的version是1,如果执行这个条件时version依然等于1,说明跟我们之前查询到的一样,说明在我执行修改之前,是没有人修改过这个数据的,既然没有人修改过,我就可以放心大胆的去减了。
2024-08-06 20:44:24 1200
原创 【Redis】实现秒杀下单
比如时间是否充足,如果时间充足,则进一步判断库存是否足够,如果两者都满足,则扣减库存,创建订单,然后返回订单id,如果有一个条件不满足则直接结束。下单核心思路:当我们点击抢购时,会触发右侧的请求,我们只需要编写对应的controller即可。当用户开始进行下单,我们应当根据ID去查询优惠卷信息,查询到优惠卷信息,判断是否满足秒杀条件。
2024-08-06 20:43:51 270
原创 【Redis】添加优惠卷
而代金券由于优惠力度大,所以像第二种卷,就得限制数量,从表结构上也能看出,特价卷除了具有优惠卷的基本信息以外,还具有库存,抢购时间,结束时间等等字段。tb_seckill_voucher:优惠券的库存、开始抢购时间,结束抢购时间。特价优惠券才需要填写这些信息。每个店铺都可以发布优惠券,分为平价券和特价券。**新增普通卷代码: **VoucherController。tb_voucher:优惠券的基本信息,优惠金额、使用规则等。平价卷由于优惠力度并不是很大,所以是可以任意领取。这两张表对应的数据库表如下。
2024-08-06 20:43:13 262
原创 【Redis】Redis实现全局唯一Id
全局唯一ID生成策略:UUID这个直接利用JDK自带的工具类UUID工具类就能生成了。这种生成策略生成的其实是16进制的一长串的数值,因为这一长串是十六进制,因此它返回的结果其实是字符串结构,并且也不是单调递增的一种特性。因此虽然可以做唯一ID,但是并不够友好,没有满足之前我们所说的哪些特性,因此这种用的比较少。Redis自增这种方法相对来讲各种特性都能满足,而且整体是单调递增的,数值的长度也不大,总共也不超过long,而且它是一个数字类型它存储的数据库里占用的空间相对来讲也比较小,比较有好一些。
2024-08-06 20:42:26 1016
原创 【Redis】封装Redis工具类
经过前面几节的学习,我们已经解决了缓存使用过程中的各种各样的一些问题,但是我们发现无论是解决缓存穿透还是解决缓存击穿,她们的代码逻辑都是挺复杂的,如果说我们每次开发的时候都要去写这些逻辑,其实开发的成本还是挺高的,所以将来我们一定会将这些解决方案封装成工具。这四个方法你可以认为这个方法是两两配对的,方法一和方法三对应起来,即对应一些常见的、普通的缓存,可以解决缓存穿透、设置TTL过期。因为你封装的这个工具类,它并不知道使用者要操作的数据是什么类型,因此这个方法在使用的时候需要指定类型,然后才能做反序列化。
2024-08-06 20:37:27 519
原创 【Redis】利用逻辑过期解决缓存击穿问题
顾名思义,逻辑过期不是真正的过期,它要求我们在存储数据到redis的时候,额外的要添加一个过期时间的字段,这个key本身是不用去设置ttl的,所以它的过期时间不是由redis控制的,而是由我们程序员自己去判断它是否过期,这样我们的业务上就会复杂很多,因此我们先来看一下整个业务流程上有什么变化。由于我们在单元测试的时候已经向redis中插入了一条数据了,并且这条数据当时设置的过期时间也比较短,大概是10秒钟的样子,因此理论上这些数据应该早就过期了,但是它依然还在这里,这就是逻辑过期。
2024-08-06 20:36:29 1389
原创 【Redis】利用互斥锁解决缓存击穿问题
核心思路:相较于原来从缓存中查询不到数据后直接查询数据库而言,现在的方案是 进行查询之后,如果从缓存没有查询到数据,则进行互斥锁的获取,获取互斥锁后,判断是否获得到了锁,如果没有获得到,则休眠,过一会再进行尝试,直到获取到锁为止,才能进行查询。,这两种,拿到锁了就执行,没拿到锁就需要一直等待。接下来回到IDEA看一下日志,可以发现对数据库的查询其实只触发了一次,证明在高并发的场景下,我们并没有出现所有的请求都打到数据库的情况,而是只有一个人进来了,说明我们这块基于互斥锁的解决方案已经成功了。
2024-08-06 20:34:35 1367
原创 【Redis】缓存击穿问题及解决思路
如果缓存雪崩是无数key同时过期而引发的问题,那么缓存击穿就是部分key过期而导致的严重后果。那为什么部分key过期也会导致严重的后果?这是因为这部分key不是普通的key。缓存击穿问题也叫热点Key问题,就是一个被高并发访问并且缓存重建业务较复杂的key突然失效了,无数的请求访问会在瞬间给数据库带来巨大的冲击。高并发访问:这个Key访问的非常多,可能是在做活动的某一件商品的缓存,同一时刻可能会有无数的请求来访问这一个key。
2024-08-06 20:33:52 1050
原创 【Redis】缓存雪崩问题及解决思路
所谓多级缓存:之前讲过,缓存的使用场景是多种多样的,不仅仅是说可以在应用层添加,请求从浏览器发出,浏览器是可以添加缓存的,但是浏览器的缓存一般缓存的是静态的数据,而对于需要从数据库中查询的动态数据是无法做缓存的,对于这部分我们还可以在反向代理服务器Nginx层面做缓存,Nginx缓存未命中,再去找我们的redis,redis未命中,到达我们的JVM,我们还可以在JVM内部建立本地缓存,最后是数据库,即在多个层面建立缓存,这样redis这一环崩了,还有很多别的缓存可以去弥补。的随机数,此时它的有效期就会在。
2024-08-06 07:36:28 442
原创 【Redis】编码解决商品查询的缓存穿透问题
缓存穿透产生的原因是什么?用户请求的数据在缓存中和数据库中都不存在,这样的请求一定会到达我们的数据库。如果不断发起这样的请求,就会给数据库带来巨大压力缓存穿透的解决方案有哪些?缓存null值(我们采用的方式)布隆过滤(采用一种哈希算法)上面两种是我们之前提到过的,但是缓存穿透任然不仅仅靠这两种解决,这两种其实属于一种被动的方案:人家已经来穿透你,然后你想办法去弥补。事实上我们也可以主动采取一些措施去解决缓存穿透。增强id的复杂度,避免被猜测id规律,这样一来它就不太容易输入一些自己编的id了。
2024-08-06 07:35:52 1009
原创 【Redis】缓存穿透问题的解决思路
并不是的,如果是这样,我们就多余存储了很多数据了。当我们客户端访问不存在的数据时,先请求redis,但是此时redis中没有数据,此时会访问到数据库,但是数据库中也没有数据,这个数据穿透了缓存,直击数据库,我们都知道数据库能够承载的并发不如redis这么高,如果大量的请求同时过来访问这种不存在的数据,这些请求就都会访问到数据库,如果是一个不怀好意的人,它整了无数的线程,并发的向这个不存在的数据发起请求,这样所有的请求都会到达数据库,很有可能就将我们的数据库搞垮,这就是缓存穿透带来的危害了。
2024-08-05 21:04:39 997
JDBC-1500行学习笔记,真的超级详细!!!
2023-08-25
F12开发者工具中,如下图小眼睛是代表啥
2024-01-12
框起来的地方为啥报错?
2023-08-25
jdbc中的批量操作,我明明都是按照步骤写的,但最后的执行时间并没有优化,这是为什么?
2023-08-24
我这一段的存储函数哪里写错了?
2023-08-06
下面是N叉树层次遍历的代码,为什么改变list时,也会将ans中对应的list改变?list = ans.get(depth)时,难道不是只是将ans中的list拷贝给了list吗
2023-08-02
下面是N叉树层次遍历的代码,为什么改变list时,也会将ans中对应的list改变?list = ans.get(depth)时,难道不是只是将ans中的list拷贝给了list吗
2023-08-02
标点,空格,有没有拼错,都检查了一遍,还是没发现自己错在哪。
2023-07-23
用这种方式创建文件,明明已经输出了创建成功,但为什么D盘并没有这个文件?
2023-07-17
这样创建文件错在哪里?我明明也将IOException异常抛出去了,为什么依旧报错?
2023-07-17
他们题解里的case和base case一般是指什么,感觉翻译成“案例”又不太对
2023-07-17
为什么1处的<>里面的可以省略,而2处省略却报错?
2023-07-12
为什么Idea里面的List.of会报错?但是我明明引了头文件
2023-07-11
框起来的部分如何理解?
2023-07-07
我感觉我和题解写的一模一样,但是为什么题解可以编译通过,但是我的这段代码不行?
2023-07-07
改变了str也应该改变了s哇,但当我打印时,s并没有发生改变,这是为什么?
2023-07-03
这里为啥报红线?该如何修改?
2023-06-22
idea划紫线是啥意思,可以替代成Comparator.comparingInt?
2023-06-22
Array.sort()中的第二个参数是什么意思,是java里面的哪个知识点?
2023-06-22
为什么框起来的没有输出出来,箭头指向的是将StringBuffer类转为String类
2023-06-21
这两种算法如何正确理解,除了死记硬背
2023-06-20
他们这里说的掩码是啥意思,感觉找了资料还是不能很理解这个的意思
2023-06-20
这里为啥显示标识符未标识?
2023-06-19
java如何将int转化为无符号整型?最简便的方法
2023-06-18
Operator '&&' cannot be applied to 'int', 'int'该如何改正该错误?前面为真,我就不想执行后面的,除了用if-else语句,还能如何改正?
2023-06-18
如图所示,报错原因是啥?
2023-06-15
如图所示,框出来的两个单词是哪两个单词的缩写?分别代表什么意思?
2023-06-15
我这段代码为什么i = 9的时候就直接跳出了循环?
2023-06-14
Arrays.stream这个方法的作用是做什么的,还有底下那个点是什么用法
2023-06-13
我这里的拓扑排序为啥没有输出来?
2023-06-07
求关键路径,这里为啥会报错?
2023-06-06
TA创建的收藏夹 TA关注的收藏夹
TA关注的人