diff --git a/P7.md b/DESIGN.md similarity index 99% rename from P7.md rename to DESIGN.md index ca31b8c..acf98f9 100644 --- a/P7.md +++ b/DESIGN.md @@ -906,7 +906,7 @@ Netty中的ByteBuf **tcache 是每个线程私有的缓存**,tcache 每次从 arena 申请一批内存,在分配内存时首先在 tcache 查找,避免锁竞争,分配失败才会通过 run 执行内存分配。 -![image-20210504175101232](/Users/suhongliu/Library/Application Support/typora-user-images/image-20210504175101232.png) +![image-20211205121406792](https://tva1.sinaimg.cn/large/008i3skNly1gx2u1jn9b3j31e80hqjt5.jpg) Small 场景,如果请求分配内存的大小小于 arena 中的最小的 bin,那么优先从线程中对应的 tcache 中进行分配。首先确定查找对应的 tbin 中是否存在缓存的内存块,如果存在则分配成功,否则找到 tbin 对应的 arena,从 arena 中对应的 bin 中分配 region 保存在 tbin 的 avail 数组中,最终从 availl 数组中选取一个地址进行内存分配,当内存释放时也会将被回收的内存块进行缓存。 @@ -1309,6 +1309,7 @@ def backtrack(路径, 选择列表): 「**剪枝**」第 **46** 题 全排列 第 **47** 题 全排列② ```python +# 剪枝 def backtrack(temp_list, length): if length == n: res.append(temp_list) @@ -1324,6 +1325,7 @@ def backtrack(temp_list, length): 第 **39 **题 组合 | 第 **40** 题 组合② | 第 **216** 题 组合③ ```python +# 索引遍历 def helper1(idx, n, temp_list): if temp_list not in res: res.append(temp_list) @@ -1331,9 +1333,10 @@ def helper1(idx, n, temp_list): helper1(i + 1, n, temp_list + [nums[i]]) ``` -「**资源消耗**」第 **22** 题 夸号生成 +「 **资源消耗**」第 **22** 题 夸号生成 ```python +# 资源消耗 def backtrack(S, L, R): if not L and not R: ans.append(''.join(S)) @@ -1345,6 +1348,7 @@ def backtrack(S, L, R): 「**资源消耗**」第 **93** 题 复原IP ```python +资源消耗 def backtrack(i, tmp, flag): if i == n and flag == 0: res.append(tmp[:-1]) @@ -1359,6 +1363,7 @@ def backtrack(i, tmp, flag): 「**资源消耗**」第 **17** 题 电话号码 ```python +# 资源消耗 def dfs(path, remains): if not remains: res.append(path[:]) @@ -1379,6 +1384,7 @@ def dfs(pth,idx): 「**多重限制**」第 **37** 题 解数独 | 第 **51** 题 N皇后 ```python +# 多重限制 def backtrack(pos): if pos == n: return True @@ -1397,6 +1403,7 @@ def backtrack(pos): 「**递归**」第 **10** 题 正则匹配 ```python +# 递归 def isMatch(self, s: str, p: str) -> bool: if not p: return not s @@ -1410,7 +1417,8 @@ def isMatch(self, s: str, p: str) -> bool: ### 【并查集模板】 ```python -dummy #虚拟节点用以连接某一特征的全部节点,类似于链表的preHead +#虚拟节点用以连接某一特征的全部节点,类似于链表的preHead +dummy parent = {} size = collections.defaultdict(lambda:1) cnt = 0 @@ -1456,6 +1464,7 @@ for e in e2n: ### 【拓扑排序模板】 ```python +# 【拓扑排序模板】 ins = [0] * n ous = collections.defaultdict(list) for cur, pre in ps: @@ -1486,6 +1495,7 @@ for i in range(len(ns): 「**单调递增**」第 **84** 题 求最大矩形 ```python +# 第 **84** 题 求最大矩形 for i in range(len(hs)): while s and hs[i] < hs[s[-1]]: base = s.pop() @@ -1499,6 +1509,7 @@ for i in range(len(hs)): 「**单调递增,考虑剩余**」第 **316** 题 去除重复字符 ```python +# 第 **316** 题 去除重复字符 for i,c in enumerate(ss): if c not in s: while s and c < s[-1] and s[-1] in ss[i:]: @@ -1509,6 +1520,7 @@ for i,c in enumerate(ss): 「**单调递减**」第 **42** 题 接雨水 ```python +# 第 **42** 题 接雨水 for i in range(len(hgt)): while stack and hgt[i] > hgt[stack[-1]]: #递减栈 base = stack.pop() @@ -1523,6 +1535,7 @@ for i in range(len(hgt)): 「**单调递减**」第 **739** 题 每日温度 ```python +# 第 **739** 题 每日温度 for i in range(len(T)-1,-1,-1): while s and T[s[-1]] <= T[i] : #递减栈 s.pop() @@ -1545,6 +1558,7 @@ bisect.bisect(ps, T, L=0, R=len(ns)) 「**中位返回**」第 **33** 题 搜索旋转排序数组 | 第**374**题 猜数字大小 | 第**69**题 x平方根 ```python +# 中位返回 while L <= R: M = (L + R) // 2 if nums[M] == T: @@ -1558,6 +1572,7 @@ while L <= R: 「**区域压缩**」第**278**题 第一个错误版本| 第**162**题 寻找峰值 | 第**153**题 寻找数组最小值 ```python +# 区域压缩 while L < R: M = (L + R) // 2 if need in s[L:M]: @@ -1589,6 +1604,7 @@ for i in range(n) - 887 鸡蛋掉落 ```python + # 鸡蛋掉落 while cur[K] < N: # 还剩 j 个蛋 测 ans 次 覆盖多少层 for j in range(1, K + 1): # 覆盖总层数 碎了 -1 次层数 + 1 + 没碎 -1 次层数 cur[j] = prev[j - 1] + 1 + prev[j] @@ -1599,6 +1615,7 @@ for i in range(n) - 813 最大平均值分组 ```python + # 813 最大平均值分组 for k in range(K-1): #循环k次 for i in range(N): #每次均依赖上次的结果 for j in range(i+1, N): @@ -1608,6 +1625,7 @@ for i in range(n) - 410 分割数组最大值 ```python + # 410 分割数组最大值 for k in range(1,K): for i in range(N): for j in range(i): @@ -1619,6 +1637,7 @@ for i in range(n) #### 「**经典双串LCS问题**」 ```python +# 经典双串LCS问题 dp = [[0] * (M+1) for _ in range(N+1)] for i in range(N): for j in range(M): @@ -1634,10 +1653,9 @@ for i in range(N): - 1312 最长回文插入次数 ```python -dp = [[0] * (N) for _ in range(N)] # dp[i][j] 代表从 i 到 j 的最长子串满足条件的数量 # i-- < j++ ==> i 在 0~j 范围内 -- - +dp = [[0] * (N) for _ in range(N)] for j in range(N): dp[j][j] = 1 for i in range(j-1,-1,-1): @@ -1658,6 +1676,7 @@ for j in range(N): [546 移除盒子](***https://leetcode-cn.com/problems/remove-boxes/***) ```python +# 区间分治动态规划 def helper(self, ns: List[int]) : N = len(ns) dp = [[0] * N for _ in range(N+1)] @@ -1671,6 +1690,7 @@ def helper(self, ns: List[int]) : 「**卡特兰数**」 ```python +# 卡特兰数 g(n) = g(0)*g(n-1) + g(1)*g(n-2) ...g(n-1)*g(0) dp=[1] + [0] * n for i in range(1,n+1): @@ -1737,7 +1757,8 @@ return res 325 最长和为k 子数组 ```python -psd = {0: -1} # 前缀和初始化 +# 前缀和初始化 +psd = {0: -1} for i in range(len(s)): t ^= cd.get(s[i], 0) # 业务逻辑 if t not in psd: @@ -1750,9 +1771,10 @@ for i in range(len(s)): 560 和为K的子数组数量 -1248 统计优美子数组 + 统计优美子数组 ```python +# 累加和存数量 psd = {0:1} for i in range(len(ns)): s += ns[i] @@ -1768,6 +1790,7 @@ for i in range(len(ns)): 974 和被k 整除 子数组数量(存数量) ```python +# 模K状态前缀和 psd = {0:-1} ans = s = 0 for i in range(len(ns)): @@ -1785,6 +1808,7 @@ for i in range(len(ns)): - 1074 和为目标值的子矩阵数量 ```python +# 矩阵前缀和 for i in range(m): #固定左边界 ps = [0] * n for j in range(i, m): #固定右边界 @@ -1807,6 +1831,7 @@ return cnt ### 【双指针】 ```python +# 双指针 def removeElement(self, ns: List[int], val: int) -> int: slow = 0 n = len(ns) @@ -2084,9 +2109,8 @@ class Solution: ### 【广度优先】 -「**无向图的遍历**」 - ```python +# 「**无向图的遍历**」 q = collections.deque([i]) while q: cur = q.popleft() @@ -2096,9 +2120,8 @@ while q: q.append(nxt) ``` -「**二叉树层序遍历**」 - ```python +# 「**二叉树层序遍历**」 q = deque([root]) res = [] while q : @@ -2116,9 +2139,10 @@ return res ### 【图论】 -**「Dijkstra最短路径」** +**** ```python +#「Dijkstra最短路径」 dic = collections.defaultdict(list) for u, v, w in edges: dic[u].append([v, w]) @@ -2623,7 +2647,8 @@ class LRUCache { DNode prev; DNode next; int val; - int key;} + int key; + } Map map = new HashMap<>(); DNode head, tail; int cap; @@ -2632,7 +2657,8 @@ class LRUCache { tail = new DNode(); head.next = tail; tail.prev = head; - cap = capacity;} + cap = capacity; + } public int get(int key) { if (map.containsKey(key)) { DNode node = map.get(key); @@ -2640,7 +2666,9 @@ class LRUCache { addToHead(node); return node.val; } else { - return -1;}} + return -1; + } + } public void put(int key, int value) { if (map.containsKey(key)) { DNode node = map.get(key); @@ -2655,18 +2683,23 @@ class LRUCache { map.put(key, newNode); if (map.size() > cap) { map.remove(tail.prev.key); - removeNode(tail.prev);}}} + removeNode(tail.prev); + } + } + } public void removeNode(DNode node) { DNode prevNode = node.prev; DNode nextNode = node.next; prevNode.next = nextNode; - nextNode.prev = prevNode;} + nextNode.prev = prevNode; + } public void addToHead(DNode node) { DNode firstNode = head.next; head.next = node; node.prev = head; node.next = firstNode; - firstNode.prev = node;} + firstNode.prev = node; + } } ``` @@ -3524,8 +3557,6 @@ IP限流 | 验证码 | 单用户 | 单设备 | IMEI | 源IP |均设置规则 ### **4、热key问题如何解决?** - - redis集群+本地缓存+限流+key加随机值分布在多个实例中 1、**缓存集群**可以单节点进行**主从复制和垂直扩容** @@ -4484,31 +4515,30 @@ QPS = 1m,则需要建设一个1000台Web服务器的集群,考虑动态扩 3. 通过**领域事件通知机制**和**微服务调用**的推拉结合,将各个子域进行解耦关联 - **核心**: - - 通讯录 | 短信 | 推送通知 | 支付 | 文件服务 - + - **智慧通行** - + > 解决物业多品牌、多系统应用造成的**信息孤岛**,**数据混乱**的问题 - + - 人脸门禁 | 可视对讲 | 电梯梯控 | 停车系统 | 访客预约 - + - **安全社区** - + > 通过**图像视频识别**、**传感数据采集**,实现**报警联动**和**风险预警** - + - 视频监控 | 周界报警 | 高空抛物 | 跨域追踪 - + - **全屋智能** - + > 围绕业主需求,逐步引入社区医疗、社区养老、**社区团购**、**社区家政**等服务 - + - 超级面板 | 无线门锁 | 烟感雾感 - + - **增值服务** - + > 实现跨品牌的产品体验,支持基于**matrix引擎**的智能生活场景裂变能力 - + - 智能充电 | 云广播 | 出入提醒 | 定向投放 diff --git a/JAVA.md b/JAVA.md index e0a7826..c53b8ca 100644 --- a/JAVA.md +++ b/JAVA.md @@ -1,4 +1,4 @@ -- [一、基础篇](#一基础篇) +- sa[一、基础篇](#一基础篇) - [网络基础](#网络基础) - [**TCP三次握手**](#tcp三次握手) - [**1、OSI与TCP/IP 模型**](#1osi与tcpip-模型) @@ -3040,7 +3040,7 @@ disk_writer_threads:单个磁盘写线程数 | 可重复读 | 可能会导致幻读 | | 可串行化 | 不会产⽣⼲扰 | - +ms #### **3、默认隔离级别-RR** @@ -3854,7 +3854,7 @@ EVCache 是线性扩展的,可以在一分钟之内完成扩容,在几分钟 ​ **和Zookeeper一样,CP模型追求数据一致性,**越来越多的系统开始用它保存关键数据。比如,秒杀系统经常用它**保存各节点信**息,以便控制消费 MQ 的服务数量。还有些业务系统的**配置数据**,也会通过 etcd 实时同步给业务系统的各节点,比如,秒杀管理后台会使用 etcd 将秒杀活动的**配置数据实时同步给秒杀 API 服务各节点**。 -![image-20210418174251742](/Users/suhongliu/Library/Application Support/typora-user-images/image-20210418174251742.png) +![image-20210418174251742](https://tva1.sinaimg.cn/large/008i3skNly1gx2tg9qs00j30ta0g40vc.jpg) @@ -4915,6 +4915,8 @@ SequenceNumber:#对于每个PID发送数据的每个Topic都对应一个从0 增长推送间隔 max.poll.interval.ms=t+1 minutes ``` +[这些年,为了进阿里背过的面试题]() + #### ZooKeeper 的作用 @@ -5150,7 +5152,7 @@ public void refresh() throws BeansException, IllegalStateException { synchronize 2. 在类中定义⼀个ThreadLocal成员变量,将需要的可变成员变量保存在 ThreadLocal 中 - **ThreadLocal**: + **ThreadLocal**: ​ 每个线程中都有一个自己的ThreadLocalMap类对象,可以将线程自己的对象保持到其中,各管各的,线程可以正确的访问到自己的对象。 @@ -5176,7 +5178,7 @@ Spring中循环依赖场景有: ​ Spring 启动的时候会把所有bean信息(包括XML和注解)解析转化成Spring能够识别的BeanDefinition并存到Hashmap里供下面的初始化时用,然后对每个 BeanDefinition 进行处理。普通 Bean 的初始化是在容器启动初始化阶段执行的,而被lazy-init=true修饰的 bean 则是在从容器里第一次进行**context.getBean() 时进行触发**。 - +​ **三级缓存解决循环依赖问题** @@ -5776,7 +5778,6 @@ Hystrix区别: > Nacos是阿⾥巴巴开源的⼀个针对微服务架构中**服务发现**、**配置管理**和**服务管理平台**。 > > Nacos就是**注册中⼼+配置中⼼**的组合(Nacos=Eureka+Confifig+Bus) -> **Nacos**功能特性 @@ -5986,7 +5987,6 @@ Feign+配置中心实现动态日志 # **九、分布式篇** > 分布式系统是一个硬件或软件组件分布在不同的网络计算机上,彼此之间仅仅通过消息传递进行通信和协调的系统。 -> ### **发展历程** @@ -6112,15 +6112,15 @@ Raft使用**心跳机制**来触发选举。当server启动时,初始状态都 **全量缓存保证高效读取** -image-20210418185425386 +image-20211205121457205 所有数据都存储在缓存里,读服务在查询时不会再降级到数据库里,所有的请求都完全依赖缓存。此时,因降级到数据库导致的毛刺问题就解决了。但全量缓存并**没有解决更新时的分布式事务**问题,反而把问题放大了。因为全量缓存**对数据更新要求更加严格**,要求所有数据库**已有数据和实时更新**的数据必须完全同步至缓存,不能有遗漏。对于此问题,一种有效的方案是采用**订阅数据库的 Binlog** 实现数据同步 -image-20210418185457610 +image-20211205121611997 ​ 现在很多开源工具(如**阿里的 Canal**等)可以模拟主从复制的协议。通过模拟协议读取主数据库的 Binlog 文件,从而获取主库的所有变更。对于这些变更,它们开放了各种接口供业务服务获取数据。 -image-20210418185516743 +image-20211205121730145 ​ 将 Binlog 的中间件挂载至目标数据库上,就可以**实时获取该数据库的所有变更数据**。对这些变更数据解析后,便可**直接写入缓存里**。优点还有: @@ -6132,7 +6132,7 @@ Raft使用**心跳机制**来触发选举。当server启动时,初始状态都 **缺点**不可避免:1、增加复杂度 2、消耗缓存资源 3、需要筛选和压缩数据 4、极端情况数据丢失 -image-20210418185549520 +image-20211205121850418 可以通过异步校准方案进行补齐,但是会损耗数据库性能。但是此方案会隐藏中间件使用错误的细节,线上环境前期更重要的是记录日志排查在做后续优化,不能本末倒置。 @@ -6152,7 +6152,7 @@ Raft使用**心跳机制**来触发选举。当server启动时,初始状态都 #### **多机房实时热备** -6.png +image-20211205122631299 两套缓存集群可以分别部署到不同城市的机房。读服务也相应地部署到不同城市或不同分区。在承接请求时,不同机房或分区的读服务只依赖同样属性的缓存集群。此方案有两个好处。 @@ -6276,4 +6276,4 @@ Raft使用**心跳机制**来触发选举。当server启动时,初始状态都 - 基于JWT的Token,数据从cache或者数据库中获取 - 基于Tomcat的Redis,简单配置conf文件 -- 基于Spring的Redis,支持SpringCloud和Springb +- 基于Spring的Redis,支持SpringCloud和Springb \ No newline at end of file diff --git a/README.md b/README.md index 9e640bd..b722f0f 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,7 @@ -# javaP7 +# javaDesign - Hello ,大家好,我是一个JAVA后端研发工程师,之前在国企IT工作了7年,去年十月和女朋友规划了下,决定来互联网看看机会。从十月开始到今年三月,开启了812(每晚8点到12点)学习模式。 + Hello ,大家好,我是一个JAVA后端研发工程师,之前在国企IT工作,去年十月规划了下,决定来互联网看看机会。从十月开始到今年三月,利用下班时间开启了812(每晚8点到12点)学习模式。 - 今年三月开始找新工作,凭借着整理的这份资料,加上[leetcode](https://leetcode-cn.com/u/idasmilence/)刷的将近600道题, - - 一个月的时间内,拿到了蚂蚁金服、快手、拼多多、淘宝、微软等大厂offer + 今年三月开始找新工作,凭借着整理的这份资料,加上[leetcode](https://leetcode-cn.com/u/idasmilence/)刷的将近600道题,一个月的时间内,拿到了蚂蚁金服、快手、拼多多、淘宝、微软等大厂offer 凭我的经验,大纲基本囊括了90%的知识点,面试中总有一些疑难偏怪知识点,遇到这类我建议大方承认,但是记住一次面试最多承认一个知识点不是自己专业领域范围的知识,不懂的多的时候要靠临场发挥或者转移话题了。目前已入职阿里淘系交易,欢迎大家找我内推(idahenji@gmail.com)