八奈见 level
获赞
1012
粉丝
201
关注
225
看过 TA
7941
蚌埠坦克学院
2025
golang
IP属地:湖北
只期待后来的你能快乐
私信
关注
2024-08-26 21:53
已编辑
蚌埠坦克学院 golang
放在以前是比较冷的项目,现在已经人手一个了有空建议阅读极客兔兔原文手敲一遍这里来个速成版作为个人原理复习也供各位快速回顾,有什么问题希望能不吝赐教 实现了哪些基本功能?我们从最简单的内存 kv 缓存开始认知:● 直接一个 map[string]any 就行了。必要功能 1: 内存过期● 实现方案考虑开一个协程计时,或者直接懒删除等用到再删。分别的缺点就是耗 cpu 和耗内存。● 一般最优解还是学 redis 的懒删除 + 定时清理,综合了两者的优点必要功能 2:被动缓存、自动回源● 一个简单的缓存是不用回源的,这个适用于我们在业务逻辑中控制了所有手动设置缓存的场景。但更多场景的缓存设置逻辑是相同的,就是简单的不存在就设置,所以我们将其抽象成自动回源策略。● 自动回源除了自动被动缓存以外,也可以设置定时的主动回源,方便一些我们想做缓存预热的情况。● 回源的实现,在一些框架里边是直接接 db 的。但是这里的设计是直接留一个接口供用户自己实现。然后由于这块我们其实只抽象了一个函数,所以可以用‘接口型函数’的技巧省去一个结构体的定义。优化点 1:并发不安全● 首先考虑直接加互斥锁。● 其次可以锁分片降低锁粒度 + 用 hash 来固定定位到某个分片。这个是泛用性更强的做法,同时这种思想也用在其他很多地方,数据库的分片横向扩展也有减少锁竞争这样的好处。● 直接上 sync.Map 来主要用在增长型 set 读多写少或者插入多不怎么需要更新的场景。优化点 2:内存泄露● 必要性只是因为内存是理论会无限增长的,我们加一个兜底淘汰保护就好了。参考 redis 的策略默认是不提供服务,但是也能选择淘汰算法。● 我们可以实现一个基础的 LRU 来做淘汰,当然如果确有热点数据的话,可以微调出 LRU-K 来应付实际情况。一些细节● 值没有使用 any,抽象了 一个 byteview,没有类型问题和反射的性能消耗,然后通过返回拷贝的方式来实现只读实际这个项目里面其实没实现那么多后面的变化大概就是从 go-cache 到 groupcache 了,实现源码也可以参考这两个项目 怎么解决分布式下的几个问题的:怎么定位节点,节点数量变化。● 一致性 hash + http pool● 一致性哈希  ○ 一个哈希环,可以理解为首尾相接的数轴。我们的 key 和 ip 分别通过某种哈希算法,可以得到一个值,取模落到哈希环上。  ○ 节点 ip 的哈希是环上的常驻值,然后 key 得到的值,落到环上以后,顺时针去找到它应该在的节点,这样就不用担心节点数量变化了。  ○ 这种情况下容易存在的问题,就是数据倾斜,可能太多数据在一个节点上。解决方案就是‘虚拟节点’,我们增加节点数,但是不增加实际机器数。把虚拟节点映射到真实机器节点上● http pool   ○ 回顾 v 获取流程:当前机器是否有内存?没有->是否在其他机器?没有->回源  ○ pool 的作用:提供 http 服务(实现 handler) + 保存定位其他 peers  ○ picker + getter,一个封装一致性哈希,一个封装从 http 请求中获取缓存值 singleflight 怎么实现?singleflight,概括来说,当并发获取缓存的时候,最先来的去拿缓存,其他的等这个最先去的结果,相同时间段内只走一趟,牺牲极小时间的即时性一致性来大量减少回源 db 的情况。实现方案:● key 标识一次调用,map 存储是否在调用,经过 map 走两个不同的路径,有就直接等,没有就正常调用,然后删除。  ○ 参考:https://paste.mozilla.org/VvqBqQ0X● 几个要点  ○ map 的三次访问都要加锁  ○ 利用 wg 来同步,阻塞和通知其他协程第一到的协程调用完了我记得还有别的实现方案,有空来补一下,或者评论区大佬可以说一下。这个我暂时学不过来了。然后这个问题还确实被问过。 protobuf 干嘛的? 和 rpc 的关系?● 单独 protobuf 其实很好理解,一种通用性扩展性极强的用来序列化结构数据的编码方式。● 在分布式缓存里,他的作用就是用来代替 json 的。不过相比 json 因为他需要实现泛用性,需要写 proto 接口定义,我们一般也叫做 idl 接口定义语言。● protobuf 就是 gprc 使用的序列化方案。一般的 rpc 其实最终还是落到用 http 来传输,主要是为了兼容性,否则每个客户端都需要做单独的适配。--#每天一篇简单博客 day1 (个人打卡,欢迎监督
0 点赞 评论 收藏
分享
2024-08-18 23:08
已编辑
蚌埠坦克学院 golang
选择:红黑树什么时候会反转、哪个页面置换算法会触发belady多选:(分值最高),inode、进程优先级会影响调度的什么、有关分库的场景方案哪个是正确的、排序是否稳定整体来说,这里笔试算有意义的一些题目了,不过还是有几个比较偏的。规则特性:编程题可以返回重复改,可以用本地ide编程题,比上一次简单很多多,一个飞机走一个 01数组,初始朝右遇到1或者边界顺时针转90,最终能遍历到多少个块。我直接模拟,不知道为什么只过了三个答案用例。一个小时都在想这个了,选择题根本没挣扎余地希望有大佬做出来的说下可能的原因--每次这种编程题只能过一半就特别痛苦,基本能过的情况十几分钟就写出来,找后面的情况浪费很多没用的时间,不重要的笔试这种情况还是直接放弃性价比更高一点。我自己有反思过,一般就是分边界情况和逻辑不完全正确。后者一般我就多清空一下思路,多重新看看题,但是很多时候还是没办法发现问题。有经验的牛佬也希望能分享下--然后我平常确实非常不喜欢过笔试题,所以还是应该抓住机会现场学习好。这次应该快结束再看一遍前面选择题的。下面直接过一下笔试内容:红黑树:完全不想学原理,直接记结论插入节点时的反转情况 —— 插入节点的父节点和叔叔节点都是红色删除节点时的反转情况 —— 删除节点导致的双重黑色 稳定排序- ologn 里边只有归并是稳定的,因为归并合并子问题用的是合并两个有序数组那种算法,是能保证相对顺序的- on 插入选择冒泡,只有选择是不稳定的(艹这个我选错了。我当时不知道为什么跟插入搞混了)插入稳定是因为你是按顺序去从后面找元素插入的,插入的时候也保证相对顺序就行;而选择是每次都选择最值,假如你有多个最值,你原来的顺序,和你应该要插入的顺序容易出现矛盾具体我们看一个例子:[4, 3, 2, 3, 1]操作的时候,第二个2会因为最小值的规则跑道前面来- 其他排序,希尔不稳定,别的都稳定 页面置换- belady:增加页框命中率反而降低的异常现象- 结论:fifo是会触发的 一个inode可能对应多个文件吗?我理解应该是不能对应多个文件,但是能对应多个文件名复习linux文件系统- 文件:文件实际是硬盘上的区域- inode:存储文件元信息,主要就是文件是怎么存在磁盘上- 目录和文件名:文件名是我们直接看到的东西,目录用来组织文件名的,多个文件名对应同一inode就是硬连接 进程优先级具体有哪些影响?方面:调度算法选择权重、响应时间 / 饥饿老化可能性、资源时间片、抢占优先级具体选项:- 会影响调度队列中的顺序- 在抢占起作用,但是不仅在- 在某些调度算法中,会获得更长cpu时间,但是不一定扩展:sre 相关操作- `$ ps -eo pid,comm,pri,nice` 查看优先级- `nice 设置进程优先级`--  
查看4道真题和解析 投递大疆等公司6个岗位
0 点赞 评论 收藏
分享
2024-08-24 20:21
已编辑
蚌埠坦克学院 golang
这类问题定位其实很明确,性价比确实没那么高,不算是高频八股。但是如果自己项目有涉及,加上恰好被问到的话,那就可以成为加分项。(但是确实难以去作为一个主动介绍的程度,只能说是一个防备式的准备)以及 Nginx 实现原理有涉及一些常见八股,所以在各种深层原理中性价比就偏高。虽然被问的概率还是总体相对低。反正还是来速成一下。上面和下面的说法都是个人见解,欢迎指出错误。--- 内存池:常见的优化,几乎高性能框架都会设计到内存池池这种思想我个人概括为:不是要用就分配用完就释放,而是用完不马上销毁,后边就能像是预分配一样反复利用nginx 里的要点是: 在os内核层的页式管理上的应用层继续使用了「内存块」的管理方案来管理申请到的大片内存,减少应用层分配碎片和频繁的系统调用effective-go里面就有一个挺有意思的简单例子,这里也分享一https://github.com/bingohuang/effective-go-zh-en/blob/master/14_Concurrency.md 翻到最后概括来说就是 rpc 标准包里边在网络io接受字节流数据的时候,用户态缓冲区我们预分配好放在一个channel中来维护,在用完之后可以回来被复用我觉得这种简单漏桶模型的思想其实是跟池类似的,不过没有池那么灵活了 基于Reactor的多进程并发模型处理大量反向代理等连接事件:(评论区学习的)反向代理,大家应该都知道,就是你的请求过来了,我们帮请求放拿到响应再返回给你。Reactor 模型是一种设计模式,在很多高并发高性能IO系统中也都有用到,比如 Redis、RabbitMQ。Reactor 模型的主要特点可以概括为:事件循环、事件分发、非阻塞io。除了这些高性能系统,浏览器运行js和epoll本身也算是利用了这种设计思想。而 Nginx,概括来说就是:**多进程、非阻塞异步IO** 的并发模型。我们从典型的运行过程来认识这个模型:1. 主进程负责管理配置和生成 worker 进程2. 每个worker开自己的单线程进行事件循环,基于特定的多路复用模型进行单线程处理连接建立和响应事件(其实这里我个人有一定疑问,除非说epoll_wait本身就算是一种异步了)为什么不用多进程?(评论区大佬贡献的问题)这里我个人理解原因主要是:1. 为了 worker 隔离从而确保稳定性2. worker 的设计具有一定独立性,本身就有进程的体量,也是为了实现横向扩展的能力nginx实际实现,就是在每个工作进程(worker process)中都开一个事件循环来等待事件,得到之后进行分发,分发之后的处理也使用非阻塞io,完成之后回调相关函数做后续操作(事件驱动)。然后其中我们获取事件的方式,就交给了os内核的io多路复用机制:这里我们知道,epoll解决的问题是进行网络io的时候如何高效建立连接和监听请求的。传统建立tcp连接的方式,分阻塞和非阻塞两种。阻塞就是监听连接建立和io过程都阻塞不能做其他事;非阻塞就是通过忙轮询的方式来看是否有连接,可以暂时做别的事情,不过io过程也是阻塞的。这里结合网络编程伪代码理解会更好而epoll可以实现多路复用,在单线程内,我们可以同时处理多个连接。具体来说,epoll用红黑树存储事件和他们对应的socket,当有网络连接事件过来的时候,红黑树会扫一遍看看哪些事件要被触发,然后相关socket会进入就绪队列。一般最简单的一种用法,我们通过阻塞的方式获取到当前所有就绪队列的socket,如果是 我们用来监听的 server socket,那么就accept然后建立新的事件和 client socket加入红黑树,如果是client socket我们就正常处理io事件。总结就是有高效查找、事件触发等优势,以此可以高效处理大量连接(和io过程关系不大,主要还是连接建立和连接事件触发两大块)始终使用「边缘触发」的就绪队列维护方式(用户必须一次处理完阻塞获取的所有事件,否则会清理掉)来应付高并发。不过确实nginx只在linux上使用epoll,而且这个其实反向代理关联不会特别大,多一个建立连接的目标而已,上游的连接建立依然会使用 epoll。复杂还是复杂在网络编程的实现,不过能说出来这些感觉已经够了。 零拷贝处理静态文件:就是除了kafka,nginx也用了零拷贝nginx 利用 location 来进行动静分离。动态资源我们反向代理直接丢给服务器处理。nginx 可以利用他自己的优化来单独去处理对静态文件的请求,除了缓存就是零拷贝了。详细原理就不多说了,看小林会更好点。要说详细了我也不会,实际实现还挺复杂的,除了sendfile还有其他调用,只能跟面试官嘤嘤嘤了我感觉说简单了到知道dma是用来承接cpu的一部分操作来处理一次磁盘io过程,然后零拷贝是用来继续减少从用户缓冲区发送到内核socket的两次拷贝和一次上下文切换的。---个人笔记有不对请指出牛佬们其他有关于nginx的常见考点也可以分享下 非常感谢
0 点赞 评论 收藏
分享
2024-08-09 09:55
已编辑
蚌埠坦克学院 golang
ManCity:项目深度这方面我感觉可以参考项目的一些架构设计,就比如说你的项目具体是如何应对高并发,大数据量,如何保证高可用,使用了那些组件,运用了哪些技术,解决了哪些问题,前后修改的对比,未来的优化点等等
0 点赞 评论 收藏
分享
0 点赞 评论 收藏
分享
2024-08-06 23:46
蚌埠坦克学院 golang
随缘写写日记,实在是无处可以发泄,也不打标签了这次来传播一点正能量,谈谈我对自己焦虑心态的反思也算是督促自己不要被对秋招影响最大的焦虑心态给打败了---鼠鼠上周日看了大型恋爱动画片义妹生活第三集,有句话挺有启发的「所以才要重新审视对吧?绫濑同学重新审视自己的行为后,已经有所反省。这么一来,我想就没必要继续烦恼了。我不认为妳是那种无法对反射行为有所反省并修正的人喔。」有点复杂了。简单来说,这集的标题叫做「反射与修正」,其实也不是什么深奥的东西。所以我有个想法,首先接受自己会反射性地焦虑:- 就像是我今天,我还在面暑期实习呢,别人已经提前批oc准备谈薪了- 简历挂了面试挂了笔试挂了- 秋招不自觉就来了,提前批错过了....然后我现在尝试去思考,他们就是秋招过程中最大的敌人可能不只是我这样的fw,是所有人都需要打败的一些敌人有了审视,有了这样模型化定义化的认知让自己更容易意识到,或许就能解决这个问题了所以第一点,知道自己有哪些地方是焦虑的就好了。另一个角度是试着了解一下他们底层意味着什么:意味着不合理的期望,对自己的认知不够清晰,以及一个不关注做一件事情的过程而内心只想着去验证不合理的结果等等人性上不加以冷静思考就容易陷入的一些地方...---与此无关的另外一点是:接受一定程度的风险,随时学会从压力焦虑中抽离出来转移注意力去放松最近很大的一个感受是,陷入了非常严重的恶性循环中我一整天都是紧绷的,精神紧张,症状会持续到晚上睡觉,失眠然后第二天醒的时候,可能没紧张了,只是被迫起床,完全没睡饱整个上午上班混混噩噩,到下午四点才会来精神然后工作做不完,秋招又没空准备,又开始紧张如此以往,咖啡慢慢也没用了有时候会想,生活还是有点乐趣,有点松弛感才好让自己持续不断努力下去的人生是没有尽头的任何时候都不应该把自己逼的太死从这一次开始就让不要求自己做到完美,反正也做不到我就完全不是一个有松弛感的人,非常容易焦虑的人可能我这种废物确实难得一见所以才真的花了足够的时间,还是没达到一个想要的水平所以反过来想很多时候的紧绷确实毫无必要我察觉到我上一阶段最大的进度就是学会慢下来慢慢去学习一些东西扯远了。反正我意识到放松是非常重要的。你上班上累了,是不可能马上就能去做下一阶段的学习的,这不符合心理学。你就是需要一个合理的放松状态,而且你必须不去担心那些你想了也没有改变的结果。
zeddic:一样的兄弟,现在面了几场感觉已经升华了哈哈,与自己和解,才是人生最好的治愈
0 点赞 评论 收藏
分享

创作者周榜

更多
关注他的用户也关注了:
牛客网
牛客企业服务