分布式锁最佳实践
在单体的应用开发场景中涉及并发同步的时候,大家往往采用 Synchronized(同步)或者同一个JVM内Lock机制来解决多线程间的同步问题。在分布式集群工作的开发场景中,就需要一种更加高级的锁机制来处理跨机器的进程之间的数据同步问题,这种跨机器的锁就是分布式锁。 超卖问题复现现象存在如下的几张表: 商品表 订单表 订单item表 :::danger 商品的库存为1,但是并发高的时候有多笔订单。 ::: 错误案例一:数据库 update 相互覆盖直接在内存中判断是否有库存,计算扣减之后的值更新数据库,并发的情况下会导致相互覆盖发生: 123456789101112131415161718192021222324252627@Transactional(rollbackFor = Exception.class)public Long createOrder() throws Exception { Product product = productMapper.selectByPrimaryKey(purchaseProductId); ...
存储器
存储器的类型有哪些? 随机存储器(random access memory,RAM):RAM是易失性存储器 静态随机存储器(SRAM)。静态RAM只要电源供电不断就可以维持所需要的数据。 动态随机存储器(DRAM)。动态RAM由一个小电容构成,因为电容会泄露电荷,因此每隔几毫秒就需要为DRAM充电, SRAM速度更快,价格更高。DRAM的存储密度更高(单块芯片存储更多的位数),消耗功耗更低,产生的热量小得多。通常将两种技术组合,DRAM用作主存储器(primary memory可读写存储器)。SRAM用作高速缓存存储器。 只读存储器(read-only memory,ROM):ROM为非易失性存储器,采用硬连线,可长久保持所存放的数据,也可应用于嵌入式系统、计算机外围设备等,基本的ROM可分五种不同类型:ROM、PROM、EPROM、EEPROM和闪存。计算机里面有小rom用于存放启动计算机所必须的程序 PROM:可编程只读存储器,内部有熔断丝,通过烧断熔断丝对芯片编程,一旦编程完成所有数据和指令都不能更改。 EPROM:可擦除PROM,用发射紫外线的特殊工具将原有芯片内容擦...
并发给ConcurrentHashMap赋值
低性能使用 ConcurrentHashMap 来统计,Key 的范围是 10。 使用最多 10 个并发,循环操作 1000 万次,每次操作累加随机的 Key。 如果 Key 不存在的话,首次设置值为 1。 12345678910111213141516171819private Map<String, Long> normaluse() throws InterruptedException { ConcurrentHashMap<String, Long> freqs = new ConcurrentHashMap<>(10); ForkJoinPool forkJoinPool = new ForkJoinPool(10); forkJoinPool.execute(() -> IntStream.rangeClosed(1, 10000000) .parallel().forEach(i -> { String key...
必先利其器,常用工具分享
Chrome 插件效率Workspaces网页有用但是要关闭浏览器了,想下次打开恢复现场,这个插件很合适。 借助工作空间的概念,可以不同窗口放置不同类型的内容。 GitHub加速 Octotree - GitHub code treegithub 目录 JSON-handlejson 格式化工具 Markdown Nice在线微信公众号 Markdown 排版工具 OneTab助长拖延症,不推荐使用,使用 Workspaces 就够了。 沙拉查词-聚合词典划词翻译 稀土掘金启动页 百度搜索 快捷打开 baidu.com 浏览器增强AdBlock — 最佳广告拦截工具Better History历史记录管理,比自带的更好用 暂停标签 (Tab Suspender)打开很多页面的时候电脑占用内存紧张 这个插件会将固定时间内没有浏览的网页暂停,避免消耗太多内存。 Clear Cache快捷清除浏览器缓存 EditThisCookie编辑cookie 图片助手(ImageAssistant) 批量图片下载 Neater Bookmarks方便的书签管理 Tampermonkey...
Spring踩坑二
Spring Webhttp 请求处理流程总览1234567@RestController public class HelloWorldController { @RequestMapping(path = "hi", method = RequestMethod.GET) public String hi(){ return "helloworld"; }; } 请求的 Path: hi 请求的方法:Get 对应方法的执行:hi() 那么,假设让你自己去实现 HTTP 的请求处理,你可能会写出这样一段伪代码: 1234567891011public class HttpRequestHandler{ Map<RequestKey, Method> mapper = new HashMap<>(); public Object handle(HttpRequest http...
序列图
展示对象之间的交互顺序纵向是时间轴,时间沿竖线向下延伸。 横向轴代表了在协作中各独立对象的类元角色。类元角色用生命线表示。当对象存在时,角色用一条虚线表示,当对象的过程处于激活状态时,生命线是一个双道线。生命线代表一个类的特定实体。 生命线:每一个类元角色延伸出来的竖线 **同步消息:**发送人在它继续之前,将等待同步消息响应 **异步消息:**在发送方继续之前,无需等待响应的消息 注释 约束:格式是: [Boolean Test] 组合片段:解决交互执行的条件及方式,为任何生命线的任何部分定义特殊条件和子进程。 抉择Alt:在两个或更多的消息序列之间的互斥的选择,相当于经典的if..else..。 选项(Opt):包含一个可能发生或不发生的序列。 可以在临界中指定序列发生的条件。 **循环(Loop):**片段重复一定次数。 可以在临界中指示片段重复的条件。 并行(Par):
多数据源热切换(请求级别)spring+druid+mybatis-plus
删除旧租户的数据库DROP DATABASE ?; 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657### 租户的多数据源切换的aop```java/** * 租户的多数据源切换的aop */@Aspectpublic class TenantSourceExAop implements Ordered { private final Logger log = LoggerFactory.getLogger(this.getClass()); /** * 拦截控制器层 */ @Pointcut("execution(* *..controller.*.*(..))") public void cutService() { } @Around("cutService()") public Obje...
异步任务的坑
Spring Boot 中编写异步任务两个注解: @EnableAsync:开启当前项目的异步功能 @Async:当前方法标记为异步方法 注意一个规则:有没有返回值。 没有返回值的例子: 返回值实现了 Future 接口: 下 异步任务的线程池配置默认情况下,异步任务的线程池是怎么配置的,是否满足我们的需求呢? 配置线程池参数默认是启动下面的线程池: 线程池对应的自动配置类如下: 可以使用下面的参数配置异步任务线程池相关的参数: 异步任务返回超时对于异步任务有返回的情况,如果获取结果超时怎么办呢? get 有重载方法可以设置超时的时间,超时之后就会抛出 TimeOut 异常: 没有返回值的异步任务抛异常对于异步任务没有返回的情况(有返回的直接 get 的时候就会抛异常),但是下面的异步任务执行的时候抛出异常,但是没有任何的其他返回: Spring 默认的异步任务异常处理器,会将对应的异常打印到日志里面: 自定义异步线程池和异常处理器 自定义异步线程池的实现: 自定义异常处理器
快速排序
题目连接: 912. 排序数组 代码 (三路快排)1234567891011121314151617181920212223242526272829303132333435class Solution: def sortArray(self, nums: List[int]) -> List[int]: self.quick_sort(nums, 0, len(nums) - 1) return nums def quick_sort(self, nums: List[int], left: int, right: int) -> None: if left >= right: return le, gt = self.partition(nums, left, right) self.quick_sort(nums, left, le - 1) self.quick_sort(nums, gt, right) def partit...
持久化配置最佳实践
RDB 持久化配置 手动触发RDBsave:会阻塞当前 Redis 服务器,直到持久化完成,线上应该禁止使用 bgsave:该触发方式会 fork 一个子进程,由子进程负责持久化过程,因此阻塞只会发生在 fork 子进程的时候 定时触发RDB根据我们的 save m n 配置规则自动触发 从节点全量复制时,主节点发送rdb文件给从节点完成复制操作,主节点会触发 bgsave 执行 shutdown 时,如果没有开启 aof,也会触发 AOF 持久化配置 AOF 重写:当 AOF 文件的大小超过所设定的阈值时,Redis 就会启动 AOF文件的内容压缩,只保留可以恢复数据的最小指令集 触发机制:Redis 会记录上次重写时的 AOF 大小,默认配置是当 AOF 文件大小是上次 rewrite 后大小的一倍且文件大于 64MB 时触发 bgrewriteaof 可以手动触发 重写原理:将整个内存中的数据库内容用命令的方式重写了一个新的 AOF 文件,这点和快照有点类似 持久化数据恢复