看到了一段话送给还在努力的大家
人生的容错率大到你难以想象,功利主义导向的思考方式往往使我们忘却了生命的本质是一场历程。无数人忽略了一个真相,很多事情其实根本没有意义。吃喝玩乐不是虚度光阴,吃苦耐劳也不一定值得歌颂。人生本就是不停的去感受去体验,爱你所爱。可是我们总爱去和别人比较,徒增自己的焦虑内耗。不一定要做世俗大家认为有意义的事,如果你想发呆,看日落数星星都有意义。你只是来体验生命的,不是用来演绎完美的,慢慢接受自已身上那些灰暗的部分,原谅自己的迟钝和平庸,允许自己出错,允许自己偶尔断电,带着缺憾拼命绽放,不断尝试、收获、感受然后放下。换成我们都能理解的话就是:在吃汉堡比赛里,输赢并不重要,因为怎么样你都能吃到汉堡。在这里祝全天下的道友,念头通达!
接口幂等性问题实践
接口幂等性问题实践接口幂等性问题,对于开发人员来说,是一个跟语言无关的公共问题。本文分享了一些解决这类问题非常实用的办法,绝大部分内容我在项目中实践过的,给有需要的小伙伴一个参考。
不知道你有没有遇到过这些场景:
有时我们在填写某些form表单时,保存按钮不小心快速点了两次,表中竟然产生了两条重复的数据,只是id不一样。
我们在项目中为了解决接口超时问题,通常会引入了重试机制。第一次请求接口超时了,请求方没能及时获取返回结果(此时有可能已经成功了),为了避免返回错误的结果(这种情况不可能直接返回失败吧?),于是会对该请求重试几次,这样也会产生重复的数据。
mq消费者在读取消息时,有时候会读取到重复消息(至于什么原因这里先不说,有兴趣的小伙伴,可以找我私聊),如果处理不好,也会产生重复的数据。
没错,这些都是幂等性问题。
接口幂等性是指用户对于同一操作发起的一次请求或者多次请求的结果是一致的,不会因为多次点击而产生了副作用。
这类问题多发于接口的:
insert操作,这种情况下多次请求,可能会产生重复数据。
update操作,如果只是单纯的更新数据,比如:update user s ...
聊聊如何解决MySQL深分页问题
前言最近遇到接口慢查询问题,仔细排查发现涉及mysql深度分页问题,于是便查阅各种资料寻求解决方案。这里总结一下可能会用到的解决方案。
我们日常做分页需求时,一般会用limit实现,但是当偏移量特别大的时候,查询效率就变得低下。本文将分4个方案,讨论如何优化MySQL大量数据的深分页问题。
limit深度分页为什么会变慢?先看下表结构:
1234567891011CREATE TABLE account ( id int(11) NOT NULL AUTO_INCREMENT COMMENT '主键Id', name varchar(255) DEFAULT NULL COMMENT '账户名', balance int(11) DEFAULT NULL COMMENT '余额', create_time datetime NOT NULL COMMENT '创建时间', update_time datetime NOT NULL ON UPDATE CURRENT_TIMESTAMP COMME ...
高性能:负载均衡的常见算法有哪些?
什么是负载均衡?负载均衡 指的是将用户请求分摊到不同的服务器上处理,以提高系统整体的并发处理能力以及可靠性。负载均衡服务可以有由专门的软件或者硬件来完成,一般情况下,硬件的性能更好,软件的价格更便宜(后文会详细介绍到)。
从下图中可以看出,系统的商品服务部署了多份在不同的服务器上,为了实现访问商品服务请求的分流,我们用到了负载均衡。
负载均衡是一种比较常用且实施起来较为简单的提高系统并发能力和可靠性的手段,不论是单体架构的系统还是微服务架构的系统几乎都会用到。
负载均衡通常分为哪两种?负载均衡可以简单分为 服务端负载均衡 和 客户端负载均衡 这两种。
服务端负载均衡涉及到的知识点更多,工作中遇到的也比较多,因为,我会花更多时间来介绍。
服务端负载均衡服务端负载均衡 主要应用在 系统外部请求 和 网关层 之间,可以使用 软件 或者 硬件 实现。
下图是我画的一个简单的基于 Nginx 的服务端负载均衡示意图:
硬件负载均衡 通过专门的硬件设备(比如 F5、A10、Array )实现负载均衡功能。
硬件负载均衡的优势是性能很强且稳定,缺点就是实在是太贵了。像基础款的 F5 最低也要 2 ...
有哪些常见的 SQL 优化手段?
避免使用 select *
select * 会消耗更多的 CPU。
select * 无用字段增加网络带宽资源消耗,增加数据传输时间,尤其是大字段(如 varchar、bolo、text)。
select * 无法使用 MYSQL 优化器覆盖索引的优化(基于 MYSQL 优化器的 “覆盖索引” 策略又是速度极快,效率极高,业界极为推荐的查询优化方式)
select <字段列表> 可减少表结构变更带来的影响。
分页优化普通的分页在数据量小的时候耗费时间还是比较短的。
12# 从第10000行开始,获取10条记录。SELECT `score`,`name` FROM `cus_order` ORDER BY `score` DESC LIMIT 10000, 10;
如果数据量变大,达到百万甚至是千万级别,普通的分页耗费的时间就非常长了。
12# 从第1000000行开始,获取10条记录。SELECT `score`,`name` FROM `cus_order` ORDER BY `score` DESC LIMIT 1000000, 10
如何优化呢? ...
MySQL 索引:索引为什么使用 B+树?
面试题 :
MySQL 的索引结构为什么使用 B+树?
红黑树适合什么场景?
在 MySQL 中,无论是 Innodb 还是 MyIsam,都使用了 B+树作索引结构(这里不考虑 hash 等其他索引)。本文将从最普通的二叉查找树开始,逐步说明各种树解决的问题以及面临的新问题,从而说明 MySQL 为什么选择 B+树作为索引结构。
二叉查找树(BST):不平衡二叉查找树(BST,Binary Search Tree),也叫二叉排序树,在二叉树的基础上需要满足:任意节点的左子树上所有节点值不大于根节点的值,任意节点的右子树上所有节点值不小于根节点的值。如下是一颗 BST(图片来源)。
当需要快速查找时,将数据存储在 BST 是一种常见的选择,因为此时查询时间取决于树高,平均时间复杂度是 O(lgn)。然而,BST 可能长歪而变得不平衡,如下图所示(图片来源),此时 BST 退化为链表,时间复杂度退化为 O(n)。
为了解决这个问题,引入了平衡二叉树。
平衡二叉树(AVL):旋转耗时AVL 树是严格的平衡二叉树,所有节点的左右子树高度差不能超过 1;AVL 树查找、插入和删除在平均 ...
如何基于Redis实现延时任务
基于 Redis 实现延时任务的功能无非就下面两种方案:
Redis 过期事件监听
Redisson 内置的延时队列
考虑了这两种方案,但最后发现 Redis 过期事件监听这种方案存在很多问题,因此最终选择了 Redisson 内置的 DelayedQueue 这种方案。
Redis 过期事件监听实现延时任务功能的原理?Redis 2.0 引入了发布订阅 (pub/sub) 功能。在 pub/sub 中,引入了一个叫做 channel(频道) 的概念,有点类似于消息队列中的 topic(主题)。
pub/sub 涉及发布者(publisher)和订阅者(subscriber,也叫消费者)两个角色:
发布者通过 PUBLISH 投递消息给指定 channel。
订阅者通过SUBSCRIBE订阅它关心的 channel。并且,订阅者可以订阅一个或者多个 channel。
在 pub/sub 模式下,生产者需要指定消息发送到哪个 channel 中,而消费者则订阅对应的 channel 以获取消息。
Redis 中有很多默认的 channel ...
PriorityQueue 源码分析
PriorityQueue 简介PriorityQueue 是 Java 中的一种队列数据结构,被称为 优先级队列 。它和普通队列不同,普通队列都是遵循先进先出(FIFO)的原则,即先添加的元素先出队,后添加的元素后出队。而 PriorityQueue 则是按照元素的优先级来决定出队的顺序,默认情况下,优先级越小的元素越优先出队。
如下图所示,如果是普通队列,我们按照元素 1 到元素 4 的顺序依次入队的话,那么出队的顺序则也是元素 1 到 4。
而优先队列的逻辑存储结构和普通队列有所不同,以 PriorityQueue 为例,其底层实际上是使用 小顶堆 形式的二叉堆,即值最小的元素优先出队。
可能很多读者对二叉堆的不是很理解,这里笔者以小顶堆为例。假如我们的元素 1 到元素 4 的优先级分别是:2、1、3、4。那么按照 JDK 所提供的小顶堆,元素的排列就会以下面这种形式呈现,可以看到二叉堆这种数据结构符合以下几种性质:
二叉堆是一个完全二叉树,即在节点个数无法构成一个满二叉树(每一层节点都排满)时,叶子节点会出现在最后一层,不足双数的情况下叶子节点会尽可能靠左,如下图最后一层 ...
ArrayBlockingQueue 源码分析
阻塞队列简介阻塞队列的历史Java 阻塞队列的历史可以追溯到 JDK1.5 版本,当时 Java 平台增加了 java.util.concurrent,即我们常说的 JUC 包,其中包含了各种并发流程控制工具、并发容器、原子类等。这其中自然也包含了我们这篇文章所讨论的阻塞队列。
为了解决高并发场景下多线程之间数据共享的问题,JDK1.5 版本中出现了 ArrayBlockingQueue 和 LinkedBlockingQueue,它们是带有生产者-消费者模式实现的并发容器。其中,ArrayBlockingQueue 是有界队列,即添加的元素达到上限之后,再次添加就会被阻塞或者抛出异常。而 LinkedBlockingQueue 则由链表构成的队列,正是因为链表的特性,所以 LinkedBlockingQueue 在添加元素上并不会向 ArrayBlockingQueue 那样有着较多的约束,所以 LinkedBlockingQueue 设置队列是否有界是可选的(注意这里的无界并不是指可以添加任务数量的元素,而是说队列的大小默认为 Integer.MAX_VALUE,近乎于无限大)。
...
ConcurrentHashMap 源码分析
上一篇文章介绍了 HashMap 源码,反响不错,也有很多同学发表了自己的观点,这次又来了,这次是 ConcurrentHashMap 了,作为线程安全的 HashMap ,它的使用频率也是很高。那么它的存储结构和实现原理是怎么样的呢?
1. ConcurrentHashMap 1.71. 存储结构
Java 7 中 ConcurrentHashMap 的存储结构如上图,ConcurrnetHashMap 由很多个 Segment 组合,而每一个 Segment 是一个类似于 HashMap 的结构,所以每一个 HashMap 的内部可以进行扩容。但是 Segment 的个数一旦初始化就不能改变,默认 Segment 的个数是 16 个,你也可以认为 ConcurrentHashMap 默认支持最多 16 个线程并发。
2. 初始化通过 ConcurrentHashMap 的无参构造探寻 ConcurrentHashMap 的初始化流程。
1234567/** * Creates a new, empty map with a default initial capacity (16) ...









