- 博客(41)
- 收藏
- 关注
原创 Mysql进阶(四)——存储过程(1)
用户定义变量 是用户根据需要自己定义的变量,用户变量不用提前声明,在用的时候直接用 "@变量名" 使用就可以。其作用域为当前连接。1). 赋值SETSET赋值时,可以使用 = ,也可以使用 :=。SELECTSELECT 字段名 INTO @var_name FROM 表名;2). 使用SELECT@var_name;注意: 用户定义的变量无需对其进行声明或初始化,只不过获取到的值为NULL。-- 赋值set @mygender := '男',@myhobby := 'java'
2024-07-17 21:05:42
593
1
原创 Mysql进阶(四)——视图
视图(View)是一种虚拟存在的表。视图中的数据并不在数据库中实际存在,行和列数据来自定义视图的查询中使用的表,并且是在使用视图时动态生成的。通俗的讲,视图只保存了查询的SQL逻辑,不保存查询结果。所以我们在创建视图的时候,主要的工作就落在创建这条SQL查询语句上。
2024-07-17 21:03:25
938
原创 MQ-延迟消息
例如:我们在用户下单后的第10秒、20秒、30秒、45秒、60秒、1分30秒、2分、...30分分别设置延迟消息,如果提前发现订单已经支付,则后续的检测取消即可。如果消息的延迟时间设置较长,可能会导致堆积的延迟消息非常多,会带来较大的CPU开销,同时延迟消息的时间会存在误差。在电商的支付业务中,对于一些库存有限的商品,为了更好的用户体验,通常都会在用户下单时立刻扣减商品库存。例如,订单支付超时时间为30分钟,则我们应该在用户下单后的第30分钟检查订单支付状态,如果发现未支付,应该立刻取消订单,释放库存。
2024-07-16 23:12:40
1410
原创 Mysql进阶(三)——SQL优化(3)
在之前的测试中,我们发现,如果数据量很大,在执行count操作时,是非常耗时的。MyISAM 引擎把一个表的总行数存在了磁盘上,因此执行 count(*) 的时候会直接返回这个数,效率很高;但是如果是带条件的count,MyISAM也慢。InnoDB 引擎就麻烦了,它执行 count(*) 的时候,需要把数据一行一行地从引擎里面读出来,然后累积计数。
2024-07-16 13:08:01
557
原创 Mysql进阶(三)——SQL优化(2)
也出现 Using index, 但是此时Extra中出现了 Backward index scan,这个代表反向扫描索引,因为在MySQL中我们创建的索引,默认索引的叶子节点是从小到大排序的,而此时我们查询排序时,是从大到小,所以,在扫描时,就是反向扫描,就会出现 Backward index scan。因为创建索引时,如果未指定顺序,默认都是按照升序排序的,而查询时,一个升序,一个降序,此时就会出现Using filesort。F. 根据phone,age进行升序排序,phone在前,age在后。
2024-07-15 20:14:46
969
原创 Mysql进阶(三)——SQL优化(1)
如果我们需要一次性往数据库表中插入多条记录,可以从以下三个方面进行优化。1). 优化方案一批量插入数据2). 优化方案二手动控制事务3). 优化方案三主键顺序插入,性能要高于乱序插入。
2024-07-15 18:10:13
1058
原创 Mysql进阶(二)——索引(4)
在讲解索引的使用原则之前,先通过一个简单的案例,来验证一下索引,看看是否能够通过索引来提升数据查询性能。在演示的时候,我们还是使用之前准备的一张表 tb_sku , 在这张表中准备了1000w的记录。这张表中id为主键,有主键索引,而其他字段是没有建立索引的。我们先来查询其中的一条记录,看看里面的字段情况,执行如下SQL:🔔可以看到即使有1000w的数据,根据id进行数据查询,性能依然很快,因为主键id是有索引的。那么接下来,我们再来根据 sn 字段进行查询,执行如下SQL:🔔。
2024-07-14 20:17:13
1092
原创 Mysql进阶(二)——索引(3)
MySQL 客户端连接成功后,通过 show [session|global] status 命令可以提供服务器状态信息。通过如下指令,可以查看当前数据库的INSERT、UPDATE、DELETE、SELECT的访问频次:💡-- session 是查看当前会话;-- global 是查询全局数据;Com_delete: 删除次数Com_insert: 插入次数Com_select: 查询次数Com_update: 更新次数。
2024-07-14 14:22:11
816
原创 Mysql进阶(二)——索引(1)
MySQL的索引是在存储引擎层实现的,不同的存储引擎有不同的索引结构,主要包含以下几种:上述是MySQL中所支持的所有的索引结构,接下来,我们再来看看不同的存储引擎对于索引结构的支持情况。注意: 我们平常所说的索引,如果没有特别指明,都是指B+树结构组织的索引。
2024-07-13 11:11:54
1010
原创 Mysql进阶(一)——存储引擎
存储引擎就是存储数据、建立索引、更新/查询数据等技术的实现方式。存储引擎是基于表的,而不是基于库的,所以存储引擎也可被称为表类型。我们可以在创建表的时候,来指定选择的存储引擎,如果没有指定将自动选择默认的存储引擎。1). 建表时指定存储引擎🔔CREATE TABLE 表名(字段1 字段1类型[ COMMENT 字段1注释 ] ,......字段n 字段n类型[COMMENT 字段n注释 ][ COMMENT 表注释 ];
2024-07-12 16:18:44
1552
原创 消费者的可靠性
业务判断就是基于业务本身的逻辑或状态来判断是否是重复的请求或消息,不同的业务场景判断的思路也不一样。不过需要注意的是,交易服务并不知道用户会在什么时候支付,如果查询的时机不正确(比如查询的时候用户正在支付中),可能查询到的支付状态也不正确。因此,RabbitMQ必须知道消费者的处理状态,一旦消息处理失败才能重新投递消息。我们在用户支付成功后会发送MQ消息到交易服务,修改订单状态为已支付,就可能出现消息重复投递的情况。在程序开发中,则是指同一个业务,执行一次或多次对业务状态的影响是一致的。
2024-07-11 19:15:13
1473
原创 MQ的可靠性
在开启持久化机制以后,如果同时还开启了生产者确认,那么MQ会在消息持久化以后才发送ACK回执,进一步确保消息的可靠性。不过出于性能考虑,为了减少IO次数,发送到MQ的消息并不是逐条持久化到数据库的,而是每隔一段时间批量持久化。为了解决这个问题,从RabbitMQ的3.6.0版本开始,就增加了Lazy Queues的模式,也就是惰性队列。消息到达MQ以后,如果MQ不能及时保存,也会导致消息丢失,所以MQ的可靠性也非常重要。在控制台发送消息的时候,可以添加很多参数,而消息的持久化是要配置一个。
2024-07-11 19:08:58
629
原创 发送者的可靠性
的重试,也就是说多次重试等待的过程中,当前线程是被阻塞的。一般情况下,只要生产者与MQ之间的网路连接顺畅,基本不会出现发送消息丢失的情况,因此大多数情况下我们无需考虑这种问题。:当网络不稳定的时候,利用重试机制可以有效提高消息发送的成功率。消息发送的超时重试机制配置成功了!在开启确认机制的情况下,当生产者发送消息给MQ后,MQ会根据消息处理的情况返回不同的。首先第一种情况,就是生产者发送消息时,出现了网络故障,导致与MQ的连接中断。为了解决这个问题,SpringAMQP提供的消息发送时的重试机制。
2024-07-10 10:32:01
1023
原创 SpringAMQP
可以发现,由于消费者1处理速度较快,所以处理了更多的消息;正所谓能者多劳,这样充分利用了每一个消费者的处理能力,可以有效避免消息积压问题。没有充分利用每一个消费者的能力,最终消息处理的耗时远远超过了1秒。在之前的案例中,我们都是经过交换机发送消息到队列,不过有时候为了测试方便,我们也可以直接向队列发送消息,跳过交换机。当消息处理比较耗时的时候,可能生产消息的速度会远远大于消息的消费速度。启动consumer服务,然后在publisher服务中运行测试代码,发送MQ消息。接下来,我们就来模拟这样的场景。
2024-07-02 18:24:07
445
原创 RabbitMQ数据隔离
对于小型企业而言,出于成本考虑,我们通常只会搭建一套MQ集群,公司内的多个不同项目同时使用。这个时候为了避免互相干扰, 我们会利用。这里的用户都是RabbitMQ的管理或运维人员。目前只有安装RabbitMQ时添加的。的隔离特性,将不同项目隔离。比如,我们给黑马商城创建一个新的用户,命名为。切换到刚刚创建的hmall用户登录,然后点击。我们可以给黑马商城项目创建一个单独的。菜单,你会发现当前用户已经具备了对。别急,接下来我们就来授权。可以看到目前只有一个默认的。此时,点击页面右上角的。
2024-06-30 11:42:47
693
原创 RabbitMQ
会发现消息依然没有到达队列!发送到交换机的消息,只会路由到与其绑定的队列,因此仅仅创建队列是不够的,我们还需要将其与交换机绑定。首次访问需要登录,默认的用户名和密码在配置文件中已经指定了。我们点击任意交换机,即可进入交换机详情页面。这里是由控制台模拟了生产者发送的消息。由于没有消费者存在,最终消息丢失了,这样说明交换机没有存储消息的能力。相同的方式,将hello.queue2也绑定到改交换机。再以相同的方式,创建一个队列,密码为。交换机,进入交换机详情页,然后点击。队列,自然就能接收到消息了。
2024-06-27 22:54:54
3024
原创 消息队列(MQ基础)
而相关的微服务都可以订阅消息通知,一旦消息到达Broker,则会分发给每一个订阅了的微服务,处理各自的业务。由于我们采用了同步调用,调用者需要等待服务提供者执行完返回结果后,才能继续向下执行,也就是说每次远程调用,调用者都是阻塞等待状态。另外,不管是交易服务、通知服务,还是积分服务,他们的业务与支付关联度低。微服务一旦拆分,必然涉及到服务之间的相互调用,目前我们服务之间调用采用的都是基于OpenFeign的调用。也就是说每次有新的需求,现有支付逻辑都要跟着变化,代码经常变动,不符合开闭原则,拓展性不好。
2024-06-26 22:04:52
1037
原创 nacos配置管理
要实现动态路由首先要将路由配置保存到Nacos,当Nacos中的路由配置变更时,推送最新配置到网关,实时更新网关中的路由信息。添加一些共享配置到Nacos中,包括:Jdbc、MybatisPlus、日志、Swagger、OpenFeign等配置。配置热更新:当修改配置文件中的配置时,微服务无需重启即可使配置生效。基于NacosConfig拉取共享配置代替微服务的本地配置。基于NacosConfig拉取共享配置代替微服务的本地配置。当配置变更时,将最新的路由信息更新到网关路由表。
2024-06-25 22:09:22
522
原创 网关登录校验
GatewayFilter:路由过滤器,作用于任意指定的路由;默认不生效,要配置到路由后生效。GlobalFilter:全局过滤器,作用范围是所有路由;声明后自动生效。
2024-06-25 15:37:27
792
原创 Docker基础命令
docker rm 容器id # 删除容器(不能删除正在运行的容器)如果要强制删除:docker rm -f 容器id。[root@//]# docker rmi -f $(docker images -aq) # 删除全部的镜像。[root@//]# docker rmi -f 镜像id 镜像id 镜像id # 删除多个镜像(空格分隔)-q, --quiet # 仅显示镜像id (docker images -q)-a, --all # 显示所有镜像 (docker images -a)
2024-06-21 13:15:37
775
原创 Docker-快速入门
确保你的虚拟机已经安装Docker,且网络开通的情况下,执行下面命令即可安装MySQL:💡mysql当我们利用Docker安装应用时,Docker会自动搜索并下载应用镜像(image)。镜像不仅包含应用本身,还包含应用运行所需要的环境、配置、系统函数库。Docker会在运行镜像时创建一个隔离环境,称为容器(container)。镜像仓库:存储和管理镜像的平台,Docker官方维护了一个公共仓库:Docker Hub。Docker是做什么的?什么是镜像?什么是容器?什么是镜像仓库?
2024-06-20 21:14:37
296
原创 使用ThreadLocal
对于多任务,Java标准库提供的线程池可以方便地执行这些任务,同时复用线程。这种在一个线程中,横跨若干方法调用,需要传递的对象,我们通常称之为上下文(Context),它是一种状态,可以是用户身份、任务信息等。给每个方法增加一个context参数非常麻烦,而且有些时候,如果调用链有无法修改源码的第三方库,方法,它内部需要调用若干其他方法,同时,我们遇到一个问题:如何在一个线程内传递状态?没有被清除,该线程执行其他代码时,会把上一次的状态带进去。注意到普通的方法调用一定是同一个线程执行的,所以,
2024-06-20 15:40:48
306
原创 使用Atomic
Atomic类是通过无锁(lock-free)的方式实现的线程安全(thread-safe)访问。它的主要原理是利用了CAS:Compare and Set。包除了提供底层锁、并发集合外,还提供了一组原子操作的封装类,它们位于。在高度竞争的情况下,还可以使用Java 8提供的。这样的封装好的方法,因此,使用起来非常简单。CAS是指,在这个操作中,如果。通常情况下,我们并不需要直接用。的值,最终的结果也是正确的。实现复杂的并发操作,而是用。循环,即使其他线程修改了。,就什么也不干,返回。
2024-06-20 11:18:44
593
原创 使用Concurrent集合
因为所有的同步和加锁的逻辑都在集合内部实现,对外部调用者来说,只需要正常按接口引用,其他代码和原来的非线程安全代码完全一样。方法时,该方法内部可能会让线程变成等待状态,直到队列条件满足不为空,线程被唤醒后,非常有用,所以我们不必自己编写,可以直接使用Java标准库的。使用这些并发集合与使用非线程安全的集合类完全相同。但是它实际上是用一个包装类包装了非线程安全的。包也提供了对应的并发集合类。加锁,这样获得的线程安全集合的性能比。的意思就是说,当一个线程调用这个。集合要低很多,所以不推荐使用。
2024-06-20 11:14:38
325
原创 乐观锁StampedLock
显然乐观锁的并发效率更高,但一旦有小概率的写入导致读取的数据不一致,需要能检测出来,再读一遍就行。还提供了更复杂的将悲观读锁升级为写锁的功能,它主要使用在if-then-update的场景:即先读,如果读的数据满足条件,就返回,如果读的数据不满足条件,再尝试写。这样一来,我们读的数据就可能不一致,所以,需要一点额外的代码来判断读的过程中是否有写入,这种读锁是一种乐观锁。,会发现它有个潜在的问题:如果有线程正在读,写线程需要等待读线程释放锁后才能获取写锁,即读的过程中不允许写,这是一种悲观的读锁。
2024-06-19 22:47:08
600
原创 线程同步和解决死锁
当多个线程同时运行时,线程的调度由操作系统决定,程序本身无法决定。因此,任何一个线程都有可能在任何指令处被操作系统暂停,然后在某个时间段后继续执行。这个时候,有个单线程模型下不存在的问题就来了:如果多个线程同时读写共享变量,会出现数据不一致的问题。上面的代码很简单,两个线程同时对一个int变量进行操作,一个加10000次,一个减10000次,最后结果应该是0,但是,每次运行,结果实际上都是不一样的。这是因为对变量进行读取和写入时,结果要正确,必须保证是原子操作。原子操作是指不能被中断的一个或一系列操作。
2024-06-19 13:15:40
744
原创 线程的状态,中断及守护线程
在Java程序中,一个线程对象只能调用一次start()方法启动新线程,并在新线程中执行run()方法。一旦run()方法执行完毕,线程就结束了。run()sleep()run()用一个状态转移图表示如下:当线程启动后,它可以在RunnableBlockedWaiting和这几个状态之间切换,直到最后变成Terminated状态,线程终止。run()returnrun()Threadstop()一个线程还可以等待另一个线程直到其运行结束。例如,main线程在启动t线程后,可以通过t.join()等待t。
2024-06-18 20:25:32
944
原创 java多线程
在计算机中,我们把一个任务称为一个进程,浏览器就是一个进程,视频播放器是另一个进程,类似的,音乐播放器和Word都是进程。某些进程内部还需要同时执行多个子任务。例如,我们在使用Word时,Word可以让我们一边打字,一边进行拼写检查,同时还可以在后台进行打印,我们把子任务称为线程。进程和线程的关系就是:一个进程可以包含一个或多个线程,但至少会有一个线程。操作系统调度的最小任务单位其实不是进程,而是线程。
2024-06-18 18:37:56
712
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人