时间复杂度
Big-O Notation - For Coding Interviews
Big-O Notation - For Coding Interviews
处理了一个现场问题,现场部署了多个agent但是就一个agent离线。
agent是部署在单独的服务器A上,且使用docker部署,该agent需要与另外一台服务器B通信,当前的状态即是无法通信。
agent->docker->服务器A->….->服务器B
先搞清楚请求要从agent到服务器B是个什么过程,找出其中的关键环节,逐个排查。
容器B中的某个服务程序(比如web服务器)需要向服务器C发送数据。它会调用socket接口,传入目标地址等信息来生成数据包。
数据包被传递给容器B的网络堆栈。该堆栈会为数据包添加上以太网头(包含源MAC、目标MAC等),然后发送到容器的虚拟接口veth pair。
veth pair会将数据包传递给Docker主机的网络命名空间。这里包含一个Bridge接口docker0。
docker0收到数据包后,查找路由表,确定应该通过主机的物理接口eth0发送。
数据包被传递至主机的网络协议栈,这里会为数据包添加物理层头信息(比如Ethernet II头)。
添加完头信息的数据包通过主机的物理接口eth0发送出去。
数据包到达主机所在物理网络的交换机,交换机根据MAC地址转发到路由器。
路由器剥离二层头信息,查找三层信息,确定应向ISP上的默认网关发送。
在各个ISP路由器之间,重复着提取IP头,查询路由表,转发的过程。
最终数据包到达服务器C,服务器C的网络栈处理数据包,将其传递给目标服务。
在Docker容器的网络中,还存在一个默认网关,它是容器访问外部网络的桥梁。
当容器B的网络栈处理数据包时,会查看目标IP是否在容器内网段:
如果目标IP在容器内网段,则直接通过veth pair发送给docker0。
如果目标IP不在容器内网段,则需要先发送给容器的默认网关。
容器的默认网关其实是一个在主机网络命名空间内的虚拟接口,IP地址属于docker0子网,比如172.17.0.1。
所以数据包的流程可以补充为:
容器B网络栈 -> 容器默认网关(172.17.0.1) -> docker0 -> eth0
默认网关负责帮助容器正确地将数据包发送到外部网络,从而实现网络访问。
容器内默认路由未正确设置
容器需要有默认网关来路由外部网络的访问。如果默认路由未设置或设置错误,可能导致容器内无法访问外部网络。
docker0桥接问题
docker0是连接容器和主机网络的桥梁。如果docker0配置错误,无法正确转发容器的数据包,会造成网络访问故障。
容器访问外部网络规则问题
可能由于iptables等防火墙规则错误配置,导致容器无法访问外部特定网络或端口。
容器网络命名空间隔离问题
查了下agent所在的服务器与主业务是能telnet通的,但是进入agent容器内部则不行,不管是ping还是curl都不行。
首先怀疑容器的网络配置可能存在问题。检查容器的网络设置,先后检查了iptables、DNS、检查默认路由都没有异常。又因为容器外能访问,且该agent与其它2、3个agent属于同一个子网下,所以也侧面证明了,服务器的网络配置确实没问题。
那接下来基本确定是docker网络配置的问题了。
基于nsenter,验证网络问题,发现确实存在网络问题,ping docker默认网关不通。
现场反馈更新过agent的网络地址,随即检查daemon.json 、docker-compose.yml文件
发现docker-compose.yml内定义的subnet为16为子网掩码,而daemon.json为24位子网掩码,
因为16比24的IP范围大,这种情况下,容器获得的IP地址可能不在docker-compose网络的子网范围内,从而无法连接到该网络,造成网络通信失败。
将docker-compose.yml和docker daemon中的子网掩码设置为相同。例如都使用24位子网掩码。
最近遇到一个现场问题,客户反馈产品页面提示连接错误,一查是ws不能链接,借此复习下ws的内容。毕竟之前写ws功能是好几年前了。温故知新。
https://ably.com/topic/websockets
https://www.rfc-editor.org/rfc/rfc6455
https://websockets.spec.whatwg.org/#websocket-opening-handshake
最近处理一个现场故障,现象是系统用一段时间就会变得很慢,clickhouse会重启,etcd发生长时间起不来,业务日志有代码报错。
总结下来大体发现如下几个问题:
业务代码问题先给到业务方进行排查,我们先看clickhouse和etcd问题
因为对于基础组件都没开系统日志,所以只能从观察系统的指标开始,通过netdata,发现clickhouse会不断的打到峰值
所以先从clickhouse查起,因为没有开日志,所以就从clickhoue提供的系统表开始查起
我们找了下官方资料,先锁定了如下几张表
1 | -- 查看可疑的sql |
最近处理一个现场,80端口正常开放,但是从外部curl无法访问,pod内部是没问题的
初步判断时k8s内部的转发出了问题
https://www.tkng.io/services/clusterip/dataplane/iptables/
https://kubernetes.io/blog/2022/09/07/iptables-chains-not-api/
https://dustinspecker.com/posts/iptables-how-kubernetes-services-direct-traffic-to-pods/
https://medium.com/swlh/manage-iptables-firewall-for-docker-kubernetes-daa5870aca4d
https://livebook.manning.com/concept/kubernetes/iptable
https://serenafeng.github.io/2020/03/26/kube-proxy-in-iptables-mode/
https://jimmysong.io/en/blog/understanding-iptables/
https://blog.csdn.net/cloudvtech/article/details/79728920
最近看了本书《价值》,高瓴资本的张磊写的,人和其所在的行业虽然我都不熟,但是当时在书店随便拿了本看看。
这是目前唯一一本从序,开始就抓住我眼球的书,当然我看的书不多就是了,我估计是因为刚好最近有些焦虑和颓废的原因吧,这本书仿佛是孙悟空派来叫醒我的。
坚持长期主义,这是一条越走越不孤独的路,这是一条越走越行稳致远的路。
长期主义-把时间和信念投入到能够长期产生价值的事件中,尽力学习最有效率的思维方式和行为标准,遵循第一性原理,永远探求真理。
长期主义与个人而言,是一种清醒,帮助人们建立理性的认知框架,不受短期诱惑和繁杂噪声的影响。
对企业而言,是一种格局,帮助企业拒绝狭隘的零和游戏,在不断创新、不断创造的价值历程中,重塑企业的动态护城河。
一个人的知识、能力和价值观,才是深藏于心,并真正属于自己的”三把火“
方法和策略能战胜市场,但对长期主义的信仰却能够赢得未来。
发表自己真实的想法和意见,不去争论谁是对的,而是去争论什么是对的。
更多的研究是为了更少的决策,更久的研究是为了更准的决策。
很多时候迷恋数据是为了拿数据当挡箭牌,抵挡因为懒惰带来的错误,从而把责任怪到数据上。
正确的理解应该是:精确的数据无法代替大方向上的判断,战术上的勤奋不能弥补战略上的懒惰
克莱顿·克里斯坦森关于创新的诠释:创新不在于技术进步,更不在于科学发现,而在于对市场变迁的主动响应。
世界上只有一条护城河,就是企业家门不断创新,不断疯狂地创造长期价值。
克莱顿·克里斯坦森《创新者的窘境》将创新定位两类:
不断完善和改进现有产品,通过精耕细作满足更挑剔的需求。但是偶然的非主观的主义则无法融入企业创新流程。
追求的根本性的改变,从底层出发改变现有的技术发展路径和思维方式,创造出区别于现有主流市场的全新产品合服务,这种创新可能会对原油的护城河降维打击。
较长的员工成长的还得益于足够扁平的组织机制。扁平的组织机制能够保证更多有价值的想法随时听到,“多汇报,少请示”。特别是对于新人,即使反馈,从而得到反馈,能得到足够的尊重。
团队内营造更好的倾听反馈和给予关怀的氛围。
自我驱动能力。
员工的成长有两方面:
对于有潜质、价值观一致的员工,我们奉行长期主义,不着急,慢慢来,给予其充分的成长时间。
全力打造学习型组织。倡导“传、帮、带”文化与跨团队的交流和分享,创造一切条件促进内部学习。“传、帮、带”不是为了消灭个性。
分享周?跨团队分享机制。
团队协作,复盘和纠错机制。
第二曲线理论。
《七律·和柳亚子先生》
问题也是源于一个客户现场问题。
经查原因如下:
You:
什么是OSIV
ChatGPT:
我不确定你指的是什么是 “OSIV”。 请问您能否提供更多上下文或信息,以便我更好地回答您的问题?
You:
spring里的
ChatGPT:
在Spring中,”OSIV” 是 “Open Session In View” 的缩写,它是一种用于在Web应用程序中处理Hibernate(或其他ORM框架)延迟加载异常的技术。
具体而言,当在Web应用程序中使用Hibernate时,通常会在每个HTTP请求上打开一个Hibernate会话,以便加载数据并填充视图。 在没有OSIV的情况下,当在视图中使用延迟加载属性时,可能会发生”LazyInitializationException”异常。
通过启用OSIV,Spring会在Web请求处理期间保持Hibernate会话打开状态,从而避免延迟加载异常。但是,这种技术也可能导致一些不良影响,例如过度加载和缓存问题,因此使用时应谨慎。
You:
优点缺点分别是什么
ChatGPT:
以下是 “Open Session In View”(OSIV)的优点和缺点:
优点:
避免延迟加载异常:OSIV 可以确保在Web请求处理期间Hibernate会话一直处于打开状态,从而避免了在视图中使用延迟加载属性时可能出现的 “LazyInitializationException” 异常。
简化开发:启用OSIV可以简化开发过程,因为开发人员不需要显式管理Hibernate会话的打开和关闭。这使得代码更加简洁易懂。
提高性能:由于会话不需要在每次需要数据时重新打开和关闭,因此启用OSIV可能会提高应用程序的性能。
缺点:
过度加载:启用OSIV可能会导致过度加载,即在应用程序的生命周期中始终保持数据库连接处于打开状态,这可能会导致性能下降和资源消耗过高。
缓存问题:在使用缓存时,启用OSIV可能会导致缓存中的数据变得过时,从而导致数据不一致性。
难以调试:由于会话在整个请求周期中处于打开状态,因此在调试时可能很难确定哪个代码块打开和关闭了会话,从而导致问题的难以定位。
You:
缓存问题具体是什么意思
ChatGPT:
启用 “Open Session In View”(OSIV)可能会导致缓存问题,这是因为Hibernate具有一个二级缓存机制,它可以缓存从数据库中检索的实体对象,以避免在每次需要访问它们时都要进行数据库查询。而当启用OSIV时,Hibernate会话保持打开状态,从而可能会导致缓存中的数据变得过时。
具体而言,如果在请求期间Hibernate会话中的某些实体对象被更新或删除,但是由于启用了OSIV,Hibernate会话没有关闭,那么缓存中仍然包含过时的实体对象。如果在同一请求中需要访问这些实体对象,那么就会使用缓存中的过时数据,这可能会导致数据不一致性的问题。
为了避免这种情况,通常建议在处理请求后立即关闭Hibernate会话,以确保缓存中的数据始终与数据库中的数据保持同步。
You:
那就是不建议打开OSIV呗
ChatGPT:
是否启用 “Open Session In View”(OSIV)通常取决于应用程序的具体需求和开发人员的偏好。虽然启用OSIV可以简化开发过程并避免延迟加载异常,但也可能会导致过度加载和缓存问题等不良影响。
因此,建议在决定是否使用OSIV时需要考虑应用程序的实际需求。对于一些简单的应用程序,可能不需要使用OSIV,而对于一些复杂的应用程序,启用OSIV可能会带来实际的好处。
同时,如果您决定使用OSIV,请注意使用它的潜在风险,并遵循最佳实践,例如在请求结束后立即关闭Hibernate会话以避免缓存问题。
You:
如果开启了OSIV,怎么避免这类问题呢
ChatGPT:
如果您决定启用 “Open Session In View”(OSIV),可以采取以下措施来避免缓存问题:
只缓存只读数据:在使用缓存时,只缓存只读的实体对象,而不是缓存可以进行修改的实体对象。这可以避免缓存中的数据被过时数据污染。
显式刷新缓存:在每个请求的结束处,显式地刷新Hibernate的二级缓存。这可以确保缓存中的数据与数据库中的数据保持一致。
使用版本控制:在实体类中使用版本控制可以帮助确保在多个事务中不会出现数据不一致的问题。Hibernate会在更新实体时使用版本控制,并在并发修改发生时抛出异常。
禁用缓存:如果缓存问题太棘手,或者您无法控制缓存中的数据,那么可以考虑完全禁用Hibernate的二级缓存。这虽然会降低性能,但可以避免缓存问题。
总之,如果您决定启用OSIV,则应该注意缓存问题,并采取适当的措施来避免数据不一致性。同时,建议在开发过程中进行充分测试,以确保应用程序在使用OSIV时不会出现问题。
You:
怎么刷新缓存
ChatGPT:
要刷新Hibernate的二级缓存,可以使用以下方法之一:
SessionFactory 的 getCache() 方法获取二级缓存,然后调用 evictAllRegions() 方法刷新缓存,示例如下:1 | SessionFactory sessionFactory = ... // 获取SessionFactory实例 |
hibernate.cache.use_second_level_cache 和 hibernate.cache.use_query_cache 属性为 true,并在事务提交时自动刷新缓存。示例如下:1 | <property name="hibernate.cache.use_second_level_cache">true</property> |
此外,还可以通过在实体类上使用 @Cache 注解来控制实体类的缓存策略,例如:
1 | @Entity |
在这个例子中,实体类 User 将被缓存,并使用 READ_WRITE 缓存策略。如果在更新 User 对象时使用了 Hibernate 的缓存,则会自动刷新该对象的缓存。
总之,要刷新Hibernate的二级缓存,可以手动刷新缓存或在事务提交时自动刷新缓存,还可以通过使用 @Cache 注解来控制实体类的缓存策略。
You:
怎么使用使用版本控制
ChatGPT:
在Hibernate中使用版本控制可以帮助确保在多个事务中不会出现数据不一致的问题。Hibernate通过使用版本号来实现版本控制,每个实体类都必须定义一个版本号属性。当更新实体时,Hibernate会自动更新版本号,并在并发修改发生时抛出异常。以下是如何使用版本控制的步骤:
@Version 注解,示例如下:1 | @Entity |
StaleObjectStateException 异常,示例如下:1 | User user = session.get(User.class, 1L); |
如果在此之前,有另一个事务更新了同一行记录,那么在第二个事务中更新实体时,Hibernate会抛出 StaleObjectStateException 异常,示例如下:
1 | User user = session.get(User.class, 1L); |
1 | User user = session.get(User.class, 1L); |
总之,在Hibernate中使用版本控制可以帮助确保在多个事务中不会出现数据不一致的问题。可以在实体类中定义版本号属性,并在更新实体时处理并发修改异常。
You:
请给一个完整的版本冲突的代码实现
ChatGPT:
以下是一个简单的版本冲突的代码实现,其中使用乐观锁处理并发修改异常:
1 | @Entity |
在上面的代码中,首先获取要更新的实体,并将其名称设置为新名称。然后调用 session.update() 方法将实体标记为“脏”并更新到缓存中。最后,使用 session.flush() 方法将更改保存到数据库。如果在此之前有另一个事务更新了同一行记录,则在当前事务中调用 session.flush() 方法时,Hibernate会抛出 OptimisticLockException 异常。可以在异常处理程序中处理并发修改异常,并根据需要回滚事务。
You:
怎么回滚事务
ChatGPT:
在Java中,可以使用try-catch语句块和异常处理程序来回滚事务。如果在事务中出现异常,则可以在异常处理程序中调用 rollback() 方法来回滚事务。以下是一个简单的示例:
1 | // 在事务中执行数据库操作 |
在上面的代码中,使用了 Spring Framework 的事务注解 @Transactional 来标记方法作为事务。在方法中,执行数据库操作,然后使用try-catch语句块捕获异常。如果出现异常,则调用 TransactionAspectSupport.currentTransactionStatus().setRollbackOnly() 方法将事务标记为回滚状态,并将异常抛出给调用者。这将导致 Spring 回滚事务并将异常传播给调用者。
You:
怎么禁用二级缓存
ChatGPT:
禁用二级缓存需要在Hibernate的配置文件中进行设置。以下是禁用Hibernate二级缓存的配置示例:
1 | <hibernate-configuration> |
在上面的配置中,设置了 hibernate.cache.use_second_level_cache 属性为 false,表示禁用了Hibernate的二级缓存。
需要注意的是,如果应用程序使用了Hibernate的查询缓存,仍然需要将 hibernate.cache.use_query_cache 属性设置为 true,否则查询缓存也会被禁用。
另外,如果使用Spring框架进行数据访问,可以在 application.properties 文件中配置 spring.jpa.properties.hibernate.cache.use_second_level_cache 属性来禁用Hibernate二级缓存:
1 | spring.jpa.properties.hibernate.cache.use_second_level_cache=false |
You:
OSIV什么情况下才会关闭session
ChatGPT:
在开启 Open Session In View (OSIV) 模式的情况下,session 会在请求结束时自动关闭。具体来说,一般情况下,在控制器方法执行完毕后,Spring 框架会调用 DispatcherServlet 的 processDispatchResult 方法,该方法会在返回响应之前关闭 Hibernate Session。这样可以确保在整个请求处理过程中都可以访问数据库并且避免了一些潜在的问题,比如:延迟加载异常等。
但是,需要注意的是,在使用某些数据访问方式时(如 JdbcTemplate),并不会自动开启 Hibernate Session,因此也就不会自动关闭。在这种情况下,需要手动开启 Session,并在使用完毕后手动关闭 Session,以避免潜在的连接泄漏问题。
总之,在使用 Open Session In View 模式时,要注意确保 session 在请求结束时被正确地关闭,以免出现连接泄漏等问题。
https://stackoverflow.com/questions/30549489/what-is-this-spring-jpa-open-in-view-true-property-in-spring-boot
https://medium.com/@rafaelralf90/open-session-in-view-is-evil-fd9a21645f8e
先得翻墙,有境外的vps。
能接收国外的短信,我用的sms-activate
如果境外的也被封禁,在服务器上安装Cloudflare Warp,让Warp接管ChatGPT域名的访问流量即可。亲测有效。
需要chatgpt的api token
输出比较慢,估计是一次性把完整结果给出来的原因。可写代码、注释、找bug、重构分析代码等

可写代码、注释、找bug、重构分析代码等
https://www.cursor.so/

没啥好说的,就是把文档解析后,可以通过提问的方式从文档里找答案
https://chatdoc.com/
需要chatgpt的api token
可以与google搜索无缝集成,且可以直接下载结构为md文档
https://github.com/josStorer/chatGPTBox

各种基于chatgpt的工具,但是这个最原始的反而是我最喜欢用的,简洁明了
https://chat.openai.com/chat

事件缘起于遇到的一个现场问题
先问原因:
如果是主机不正常关机,很可能是 操作系统的文件系统损害
如果是docker的某种操作,那就修改docker
如果以上都没问题,再考虑修复clickhouse
如果是主机问题,还需要用户解决呢;如果是二、三记录场景,看看如何避免。
不论哪个,先询问情况吧。可以用uptime、docker ps等看看启动时间,然后对照日志时间,看看是否对的上
16:16
估计是主机非正常关机,linux系统很稳定,很少出现文件系统损害。
如果是这样,需要开远程,慎重验证、修复。并向用户澄清,有丢失数据的风险(毕竟文件系统坏了),在首肯之后再操作
如果挂载了特殊的 硬件,如:RAID、NAS,由用户的主机管理员解决。(坚决禁止NAS)
非正常关机了?或者升级k8s重启?
merge过程分多阶段:
生成新文件夹
将待合并的多个文件夹,读取合并到新文件夹
删除旧文件夹
修改相关的系统表(分区表等)
这个问题,可以到github看clickhouse源代码,然后猜测问题点
df -T -x tmpfs
看来文件夹都在,只是文件系统记录的 状态 和 落盘 不一致了
文件系统需要卸载,所以先要看 有哪些应用在使用 /opt/local-path-provisioner,将k8s相关的服务都关闭吧
!!确定相关业务已经关闭,然后一个个执行
umount /dev/sdb1
xfs_repair /dev/sdb1
mount /dev/sdb1
lsblk -f
17:39
parted -l 可以查看未挂载的文件系统类型,以及那些分区尚未格式化

会不会还有程序占用着相关文件?
lsof +d /opt/local-path-xxxxxprovoider
后边的路径就是挂载路径
刚还试了
没有lsof命令
ps -elf 看看是否有可疑进程,如果关闭k8s,应该没有几个进程在了
pstree命令执行一下,我看看继承顺序
另一个经常出的日志占用内存问题:删除文件后,进程依然持有文件描述符,内容将输出到内存
以后现场会发生的问题:经常出现断网——造成终端停止、里边的长时间命令就会失败
建议方法:启动一个tmux,启动命令后,脱离终端,等过一段时间再attach上去
https://bbs.qunyingkeji.com/2052/