自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(50)
  • 收藏
  • 关注

原创 ConcurrentHashMap的sizeCtl含义纠正

引言:本文基于JDK1.8版本,而且对ConcurrentHashMap有一定了解的人,本文并非科普该类的用法,而是针对sizeCtl的含义做出纠正科普文章推荐:深入浅出ConcurrentHashMap1.8sizeCtl定义及注释 /** * Table initialization and resizing control. When negative, the ...

2020-04-06 23:41:06 8535 13

原创 单调栈,求解 数组区间中最小数*区间和的最大值

题目描述:思路来源:求数组中区间中最小数*区间所有数和的最大值原文写的很好,本文附上Java版本代码,以及自己的注释理解public int getMaxSum(int[] nums) { int maxSum = Integer.MIN_VALUE; int[] preSum = getPreSumArr(nums); // 维持一个单调栈,存下标。 栈内下标对应元素单调非递减 LinkedList<Integer> s

2021-04-30 15:36:51 338 1

原创 secKill项目 --- 总结 + 推荐阅读顺序 + 源码地址

先上源码地址:https://github.com/HermanCho/seckill项目总结本项目基于慕课网的秒杀项目,源代码的参考很多来源于以下博客商城秒杀系统改进的地方:(主要是前两个)消息可靠性传输的实现,包括投递、持久化、消费 + 幂等性, 3 + 1 的实现redis预减库存的库存补充方案改进了 @AccessLimit的使用整合了log4j2,方便维护进行了springboot版本升级整合。源项目的版本太低,导致rabbitMQ很多问题,踩

2020-08-15 12:03:03 3190 1

原创 Redis分布式锁的注意点总结 + 参考代码

推荐阅读:Redis分布式锁的正确实现方式介绍直接说重点:setnx命令,key自然是锁名。value是requestId,即请求标识,能够区分不同的客户端,保证锁只能由加锁的客户端释放expireTime 直接作为setnx的参数,而不是单独的设置过期时间,保证原子性释放锁时,判断value是否相等,然后再释放锁。但**关键是用lua脚本,保证原子性**因为文章里都讲得很好很清楚,我就不赘述了。感叹一下在实际做项目前,准备面试点,只理解到setnx一同设置过期时间,还觉得这个问题很简单

2020-08-15 11:31:37 558

原创 secKill项目 --- 限制同一用户只有一个请求生效 + 回补Redis库存如何反馈到内存标识的思考(有库存,买不到)

完成了redis的库存的补充,redis库存和数据库库存,现在已经可以保证最终一致性了。但这并不等同于项目的正确性。先来回顾一下秒杀控制器的逻辑(核心部分源代码,其余伪代码。)此处已实现库存补偿篇所说的优化 : 先检查重复秒杀,再预减库存 @RequestMapping(value="/{path}/do_miaosha",method=RequestMethod.POST) @ResponseBody public Result<Integer> doMiaosha() {

2020-08-15 11:14:48 919

原创 secKill项目 --- Redis预减库存的存在的问题 及 库存补偿

本文建立在已完成可靠性传输的基础上,建议先阅读另一篇博文,不然可能难以理解。点击跳转先看看秒杀接口的源代码: @RequestMapping(value="/{path}/do_miaosha",method=RequestMethod.POST) @ResponseBody public Result<Integer> doMiaosha(Model model,MiaoshaUser user, @RequestParam(value="goodsId",defaultVal

2020-08-14 23:25:41 3156 1

原创 secKill项目 --- 可靠性传输的实现 及 易错点总结

本文只讨论可靠性传输相关的问题,预减库存的问题在另一篇博客:如何实现消息的可靠性传输,已在其他两篇博文中总结了,此处不赘述RabbitMQ实现可靠性传输 理论篇RabbitMQ实现可靠性传输 代码篇这里记录一下易错的,需要注意的点:消息的唯一ID是需要手动分配的,消息的持久化也是需要额外做的。两者都需要通过MessagePostProcessor完成限制重发次数交由定时任务完成。重发需要注意的点:超出限制后,记得移除redis中的相关key,并入库记录重发时,消息的co

2020-08-14 15:04:05 1367 1

原创 RabbitMQ实现可靠性传输 代码篇

本文为代码篇,建议先看理论篇,点击跳转实现可靠性传输的理论篇对应的实操代码。业务相关的都用了伪代码,方便理解。环境:springboot 2.1.9.RELEASE + amqp-client-5.4.3.jar生产者确认模式application.propertiesspring.rabbitmq.publisher-confirms=true主动分配唯一Id:(这里其实需要预处理器MessagePostProcessor,在持久化的内容中有讲)public void sendMe

2020-08-13 23:23:35 592

原创 RabbitMQ实现可靠性传输 理论篇

本文为理论版,另有代码版:本文内容是在参考了大量资料的同时,自己实操得出来的结论。笔者代码环境:springboot 2.1.9.RELEASE + amqp-client-5.4.3.jar如图所述,需要从三个方面解决问题:生产端,MQBroker,消费端。文章目录生产者确认模式如何保证投递成功无法被路由的消息处理如何持久化消息队列如何保证消费成功(或限流处理)生产者确认模式定义:当消息确认到达Broker后回调,(即只确认是否正确到达 Exchange 中),broker会发送一

2020-08-13 23:19:35 651

原创 需要根据异常,进行相关处理代码应该放MVC哪一层的思考

当需要根据异常进行处理,但同时也希望service回滚事务时。笔者之前的做法一直都是service层进行操作try{...}catch(xxxException e){相关处理throw e}但这个其实是不对的,常见于 controller层调用service层,应该把相关处理做法放到controller层。原因:对service来说,你是希望它回滚的,catch再抛就有点冗余。controller层本就应该处理异常,需要返回错误信息给应用人员。更本质的是,这个相关处理很多时候是与

2020-08-13 12:04:16 363

原创 RabbitMQ 消费者确认auto 和 manual 模式对异常的处理区别(含重试、requeue的影响)

本文用于解答下述疑问:消息在下面四个条件的处理方式:两种模式是否有异常、是否捕获异常是否设置重试requeue为true / false ( + default-requeue-rejected的影响)看似是 2 4 种方案,让人头疼,但其实没那么复杂。总结中也会给出简洁的答案。文章目录正文auto自动确认manual人工确认default-requeue-rejected 属性导致死循环的情况总结正文本文环境: springboot 2.1.9.RELEASE + amqp-cli

2020-08-12 09:49:16 4492 2

原创 RabbitMQ 消费者如何获取生产者设置的correlationId + 得到CorrelationId为空的解决方案 + 源码解析

本文解决:RabbitMQ消息者如何获取生产者设置的correlationId获取到的CorrelationId为空本文环境:springboot 2.1.9.RELEASE + amqp-client-5.4.3.jar本文分两部分,第一部分先直接给代码实现,第二部分进行原理解析。实现代码交换机、路由那些就自己改吧,附上全部代码很累赘,只说关键点注册一个bean@Beanpublic MessagePostProcessor correlationIdProcesso

2020-08-11 09:28:53 5752

原创 RabbitMQ,消费者获取correlationId或correlationIdString均为null的解决方案 + 源码层面解析

请留步找这个问题的,估计很多人都是找的资料都是一样的,多个抄袭的网站都是下图的答案。但实际操作就发现,这个代码是不全的,比如:this.buildMessage(content,correlationId.getId()),这个方法就是没附上的。直接黑人问号。先下个结论:按照该网站的做法,还是无法解决问题本文环境:springboot 1.5.8.RELEASE + amqp-client 4.0.3,后续版本可能修复。原本没有指定version,但2020.8.10,尝试用了最新版本的amq

2020-08-10 16:29:39 2732

原创 RabbitMQ---重新投递到不存在的exchange 导致MQ无法提供服务

记一个很神奇的bug。场景:开启生产者确认模式,指定了自定义ConfirmCallback实现类。尝试投递到不存在的exchange,成功回调confim接口,随后再次重发该信息。但意外的是,不止没有回调confirm接口。还导致整个rabbitMQ卡死,发送消息到其他交换机一样无作用。原因:上述操作:“尝试投递到不存在的exchange”,会产生一个ERROR:ERROR org.springframework.amqp.rabbit.connection.CachingConnectionF

2020-08-09 18:54:27 1272 2

原创 log4j2 输出指定单一日志级别(不是该级别及其以上!!!)

只输出单一级别,而不是本级及以上的级别日志。直接上代码eg: 只输出WARN级别<!--经测试,console标签里面也可以用,RollingFile没有测试,应该也可以--><File name="FileWarn" fileName="${FILE_PATH}/warn.log" append="false"> <Filters> <ThresholdFilter level="ERROR" onMatch="DENY" onMisma

2020-08-07 17:53:34 2992 1

原创 CAP原则“大总结“及单机集群redis的所属

本来觉得CAP原则挺简单的,但一搜网上一大堆,翻译的版本不一,对概念的解析也各不相同。甚至有种越看越蒙的感觉…因此分享下CAP原则的理解,主要指出了很多版本说法存在的问题。当然,这是个人理解,如果有错。欢迎各位指出。CAP原则一致性Consistency : 访问所有节点,得到结果一致。(特别是更新操作完成后)这里不采用"同一时刻"的说法,因为数据同步是需要时间的。关键是访问得到的数据一致可用性Availability :客户端访问集群中任意一个节点,系统能在有限的时间内给出非

2020-08-05 11:20:04 1417

原创 生产者消费者模式模板总结

模板的核心:消费 / 生产方法上锁try{ while(...){ 等待 } 进行消费 / 生产 通知}catch (InterruptedException e) { e.printStackTrace();} finally { 需要手动解锁,则释放锁}关键点:try{} 扩住整个逻辑,这是不会影响性能的。具体请百度了解。这样后续的finally,就可以在ReetrankLock等实现中,手动地释放锁,不需要则为空即可。不用担心忘

2020-08-04 15:40:46 262

原创 secKill项目 --- @AccessLimit用法的问题

先附上原本的代码:项目中,用了拦截器,用于简化限流判断@Servicepublic class AccessInterceptor extends HandlerInterceptorAdapter{ @Autowired MiaoshaUserService miaoshaUserService; @Autowired RedisService redisService; @Override public boolean preHandle(HttpServletRequest re

2020-07-24 15:29:41 1605

原创 Mybatis传参方法总结

本文Mybatis版本: 3.4.5简单数据类型的单参数:(基本类型 + String)parameterType可省略,且参数名为任意都可。多参数 : (Map、对象属于本范围而不是单一参数)顺序无需任何额外处理使用: 按顺序获取参数#{0},#{1} (此版本会报错,原因详见)#{arg0} , #{arg1}#{param1},#{param2}拓:arg和param 可以混用,即 #{param1} .. # {arg1}是合法的源码层面看,最后都是解析成 ar

2020-07-13 16:03:55 367 1

原创 Controller入参简化(HandlerMethodArgumentResolver)

场景:MVC三层框架中,Controller层经常传输对象,而这些对象经常需要校验。简单的参数校验一般指对象的变量非空、长度限制的,可以参考另一篇文章:@Validated 简化参数校验本文指比较复杂的参数校验,比如需要通过报文体内容(eg:Cookie)进行判断。而这些又与业务无关。因此把这部分提取出来,降低耦合性核心:自定义方法参数解析器HandlerMethodArgumentResolver 接口添加该解析器到配置中: addArgumentResolvers方法自定义方法参数解析

2020-07-10 21:26:20 290

原创 @Validated 简化参数校验

场景:MVC的三层框架中,在Controller层传对象后(一般是xxVO),经常需要对该对象进行参数校验,非空、长度等。但这些代码会大量重复,非常冗余。因此我们把相应处理提取,直接在对象上用注解实现功能其中JSR-303就是比较常用的一种。导入依赖:(此处为springboot环境)<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spri

2020-07-10 14:28:49 454

原创 Arrays.fill无法用于填充对象类型

记录一个bug:List[] edges = new LinkedList[numCourses];Arrays.fill(edges, new LinkedList<>());操作后,edges数组的全部元素都指向同一个LinkedList。而不是独立个体。原因:Arrays.fill 源码,第二个参数为 Object val ,所做操作也只是循环赋值而已public static void fill(Object[] a, Object val) { for (

2020-05-17 23:16:29 524

原创 Mysql普通索引和唯一索引触发next-key和行锁的时机总结

最近学完next-key,有点搞不清什么时候会使用next-key,什么时候会降级为行锁,所以测试了一下,归纳一下。普通索引参考的文章:MySQL使用普通索引检索时产生的next-key lock和gap lock的范围测试想要自己测试的朋友可以参考一下改文章的做法。本文用的数据以10为间隔,[0,100]。测试的都是会正常触发next-key的情况,即以下这些情况 ,本文统一以"查询"为例,但其他操作都是一样的select .. for updateselect .. in share m

2020-05-17 18:34:40 2032 4

原创 Redis 6379端口连接失败

首先排几个"简单"的坑:(估计很多人都是这里栽了)telnet ip port : ip 和 port 之间不是 :,而是空格。若telnet完不报错,跳转空白窗口,说明测试成功ip 除了用 127.0.0.1 外,试试用linux的ip地址,ifconfig就可以查看,笔者就是这种情况,设置了静态ip。所以127.0.0.1无效如果不是,接下来就是简单的几种原因:防火墙要么关闭,要么开放端口防火墙命令有iptables 跟 firewalld两个,注意都关上笔者是建议关闭并

2020-05-08 18:32:28 4257

转载 IDEAgit常见用法

IDEA中Git的使用

2020-05-08 17:49:37 304

原创 Vmware虚拟机克隆详解:固定ip + 修改uuid等内容

分两大步设置固定ip克隆后修改相关配置本文引用的其他地方的图片。会附上链接若侵权,删一、设置静态ip先进行虚拟网络的编辑接下来的操作需要管理员权限。(给权限就完事了)接下来设置网卡:网络和共享中心→ 更改适配器设置→VMware Network Adapter VMnet8 -> 右键属性修改TCP/Ipv4的配置,网上常见是这种,笔者是英文的...

2020-05-08 14:31:26 7588

转载 IDEA找不到符号或包不存在

解决办法:命令行输入:mvn idea:idea转载自:IDEA项目突然提示找不到符号或程序包不存在

2020-05-07 15:58:01 401 1

原创 泛型数组List和数组转换常见方法归纳 + 流方法解析

本文为归纳总结,不会具体说明用法或案例,但会附上相关链接此外,迭代可以完成任意操作,但没什么好讲的。所以解决方法并没有写迭代分两类:泛型数组(List为例)和引用类型数组转换基本类型数组转换前置知识:泛型必须是引用类型,不能是基本类型文章目录引用类型数组转换泛型数组 to 引用类型数组引用类型数组 to 泛型数组基本类型数组转换泛型数组 to 基本类型数组基本类型数组 to...

2020-04-16 14:40:02 2156

原创 AQS排它锁的获取acquire、释放release详解

大量源码注释警告,请耐心阅读AQS实现了代码块的并发控制,通过内置的FIFO双向队列来完成线程的排队工作基于模板方法模式设计,因此子类只需对五个方法,进行部分重写4个try:{独占 | 共享} + {获取 | 释放} ; 1个独占判断 //2个独占式的获取、释放 同步状态protected boolean tryAcquire(int arg) protected b...

2020-04-11 00:05:48 662

原创 java的Unsafe类解析

Unsafe性质sun.misc.Unsafe,“后门”类,可以直接操控内存和线程的底层操作,应用于java.nio和并发包等实现Unsafe是final类,不能被继承-获取Unsafe实例的"唯一"正常手段:Unsafe unsafe = Unsafe.getUnsafe();因为有使用限制,看源码就知道了//构造器私有private Unsafe() {}@CallerS...

2020-04-08 00:09:47 185

原创 ConcurrentHashMap之transfer()扩容深入源码分析

引言:首先“打个广告”,对于sizeCtl变量,如果读者还认为取值-N 时代表有N-1个扩容线程(因为基本资料都是这么说的),建议先阅读我的另一篇文章:ConcurrentHashMap的sizeCtl含义纠正引言:看了很多资料,有说的好的,但感觉有些地方讲得不是很好,所以加入了自己的理解,写出了这篇博文,希望对各位有一点帮助。精华分析因为源码跟注释都很多,我先直接把精华的分析总结...

2020-04-07 17:53:35 1141 1

原创 HashMap源码之resize()详解

首先说明本文并没有采取直接把源代码拷贝出来然后在这之上“翻译”或者写注释的形式。因为笔者认为源码还是要自己阅读,并辅以资料的形式会更容易理解,也会有更多收获。本文所述HashMap为 jdk1.8重点:if (newThr == 0)的原理因为笔者找到的资料相关的内容都不太全,希望能对大家有一点帮助。进入正文:四种扩容情况(oldCap、oldThr、newCap、newThr...

2020-03-29 17:08:51 838

原创 volatile禁止重排序详解

首先说明本文并不是讲解volatile不保证原子性、如何保证可见性xxxx,还不懂的请参考让你彻底理解volatile并发关键字volatile(重排序和内存屏障)本文针对以下两个问题解答1. 重排序规则中,volatile读写跟普通读写有什么关系,为什么要限制它们2. volatile读操作的内存屏障的LoadLoad屏障到底是在读前还是读后直接进入主题重排序规则中,volatil...

2020-03-22 15:25:56 2968 23

原创 泛型PECS的理解

首先说明本文不是解释或教学PECS的,如果还不懂的读者可以参考下文。Java泛型中的PECS原则本文针对上述两个下划线部分阐述自己的理解。extends不能写入吗?确切地说,并不是。就比如List的常用实现类ArrayList是允许存null的,当然这个是视不同数据结构规则不一样。但除了null外,任何对象(包括Obeject)也不能写入,如图。super不能读数据吗?确切地说,...

2020-03-16 22:23:14 235

转载 leetCode169. 多数元素Boyer-Moore 投票算法

求众数本质上,Boyer-Moore 算法就是找 nums 的一个后缀 sufsuf ,其中 suf[0]suf[0] 就是后缀中的众数。我们维护一个计数器,如果遇到一个我们目前的候选众数,就将计数器加一,否则减一。只要计数器等于 0 ,我们就将 nums 中之前访问的数字全部 忘记 ,并把下一个数字当做候选的众数。直观上这个算法不是特别明显为何是对的,我们先看下面这个例子(竖线用来划分每次...

2020-03-13 15:38:54 135

原创 力扣面试题 17.08. 马戏团人塔

马戏团人塔,如本题,要求身高、体重分别递增,且都只能<,不能<=Arrays.sort(person, (a, b) -> a[0] == b[0] ? b[1] - a[1] : a[0] - b[0]);用NlogN的二分查找法完成的最长递增子序列时,身高递增,必须按照身高相同时,体重递减排序,否则会出现多个身高相同,而体重递增的答案,则不符合<的要求。而原因就...

2020-03-13 15:04:25 274

转载 SecureCRT的常见操作

在远程主机和本地之间传输文件SecureCRT与SshClient不同的就是,SecureCRT没有图形化的文件传输工具,不过也不影响,用命令来实现的话,其实会方便快捷很多。第一种方式:上传文件只需在shell终端仿真器中输入命令”rz”,即可从弹出的对话框中选择本地磁盘上的文件,利用Zmodem上传到服务器当前路径下。下载文件只需在shell终端仿真器中输入命令”sz 文件名”,即可利用...

2020-03-09 22:39:22 634

原创 位运算获取、去除二进制中最右边的1

2的幂刷LeetCode看到题解的时候,不禁膜拜神奇的位运算,O(1)时间即可完成,因此mark下这篇文章获取二进制中最右边的1x&(-x)就是这么简洁,就能实现获取到二进制中最右边的 1,且其它位设置为 0。原因:首先在补码表示法中,负数的补码 = 取反 +1,这个都知道,但你可能没发现:取反后:最右边的 0 的位置对应于 最右边的 1 的位置,而取反后 +1 ,则会把该...

2020-03-05 14:29:25 4371 4

原创 Linux纯命令行安装VMwareTools具体步骤

刚接触linux,也没有安装图形界面,在纯命令行进行操作时踩了不少坑,因此来分享一下,算是汇总加补充点细节首先为求方便,以下操作全部在root账号下操作拍摄快照!!!!在进行安装前,建议先拍摄快照,出现问题也不用像笔者那么闹心而且浪费时间:具体操作:我的计算机->选定虚拟机->右键快照->拍摄快照并备注,如图进入正题:导航栏->虚拟机->安装VMwar...

2020-03-04 22:57:30 6373

原创 用putty连接linux(本地或云端)

先测试ping命令首先测试ping命令是否起效,若报name or service not know,请看我另一篇博文并先解决。ping命令name or service not knowifconfig获取ip然后再在命令行输入ifconfig这样我们就得到了linux的ip地址。ifconfig命令无效如果ifconfig命令无效,请按照ping命令name or ser...

2020-03-03 22:18:02 637

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除