- 博客(71)
- 收藏
- 关注
原创 三张图解释清楚分布式系统的一致性模型
在分布式系统中,数据通常分布在多个服务器或数据库中,而这些服务器之间可能位于不同的地理位置,因此分布式系统具有可扩展性和容错性等优点。然而当系统需要处理写入操作(如更新、删除数据)时,如何确保所有服务器上的数据保持一致,成为一个重要的问题。这就是一致性模型要解决的。
2024-08-21 07:45:10
576
原创 全网最易懂 !用人话讲给初中生听的线性回归LinearRegression !
当我们学习一门新课程、接触一个新专业时,总会对该领域的专有名词感到困惑,甚至看完解释仍难以理解其含义。在我们一起学习machine learning的过程中,我会尽量对相关名词用“人话”做一遍解释,以减少学习的“痛苦感”。譬如今天要学的线性“回归”,这个**回归(regression)**和我们平时说的“回归祖国”的回归(return)是两个含义完全不同的词,它有“倒推”的含义在里面。我们学习的时候一定要抛开现有的认知,这样才能对新知识有更高的接受度。那么,这个回归究竟是什么意思呢?其实回归算法是相对。
2024-08-21 07:20:36
862
原创 2W字,100张图,100个例子吃透机器学习100个核心概念 !
训练集用于模型学习,验证集用于模型调优,测试集用于最终评估模型的表现。通用逼近定理(Universal Approximation Theorem)通用逼近定理(Universal Approximation Theorem)是机器学习和神经网络领域的一个重要理论,它的核心思想是:具有足够复杂度的神经网络可以逼近任何连续函数。换句话说,一个足够复杂的神经网络可以学到任何复杂的模式或关系。想象你有一个非常复杂的数学函数,它很难直接描述。
2024-08-20 20:31:56
1088
原创 如何向小白解释清楚机器学习的4W
2012年,AlexNet架构的出现(以其发明者Alex命名的神经网络架构)展示了巨大的潜力,自此机器学习开始备受关注。这个程序的独特之处在于,它能够通过奖励机制来学习改进自己的表现,他在1952年首次提出了“机器学习”这个术语。然而,通过绘制人工智能和机器学习的维恩图,我们可以清楚地看到,在几乎所有的软件公司中,无论是谷歌这样的科技巨头,还是新成立的小型初创公司,软件工程师都是非常高薪的职位。维基百科对机器学习的定义是:机器学习是计算机科学的一个领域,使计算机能够在没有明确编程的情况下进行学习。
2024-08-20 20:09:19
478
原创 并发编程 | Future是如何优化程序性能
可以看出,FutureTask实现了RunnableFuture接口,而RunnableFuture继承了Runnable和Future,也就是说FutureTask既是Runnable,也是Future。所以 FutureTask 既可以作为 Runnable 被线程执行,又可以作为 Future 得到 Callable 的返回值。@OverrideSystem.out.println("子线程返回值:" + futureTask.get());//输出。
2024-08-19 20:34:09
695
原创 并发编程 | CountDownLatch是如何控制线程执行流程
CountDownLatch主要是用于让一个或多个线程等待其他线程完成某些操作后再继续执行。例如,小组早上开会,组长(主线程)只有等所有人(每个人代表一个线程)到达会议室才能开;再如,游乐园里的过山车,一次可以坐10个人,为了节约成本,通常是等够10个人了才开。CountDownLatch的核心思想是“倒计时”:线程在执行之前,需要等到计数器倒数到零。
2024-08-19 20:33:11
691
原创 性能优化理论篇 | 如何保证数据安全落盘,5分钟彻底弄懂 一次write中的各种缓冲区 !
由于传输的数据量已经确定,并且考虑到网络通信的特点(数据可能是突发的),我们决定使用libc库的流函数(fwrite() 和 fflush(),对应上图中的“Library Buffers”)进一步缓冲数据。然后,在@6处,程序调用fsync()函数,将内核缓冲区中的数据强制刷新到物理存储设备(如磁盘)上,直到现在,数据才被保存到上图所示的“稳定存储”层。@1处是应用程序缓冲区的示例,这是我们自己在代码中显示创建的,对应上图中的Application Buffers,从套接字读取的数据放入此缓冲区。
2024-08-18 14:25:30
883
原创 性能优化理论篇 | Cache VS Buffer,傻傻分不清 ?
再切换到运行“ vmstat 2”命令的窗口,观察“ buff”列和“ cache”列的变化,您会注意到,在使用 dd 命令读取磁盘时,缓冲区buffer和缓存cache的大小都会增加,但缓冲区buffer的增长速度明显更快。现在,立即切换回之前运行“ vmstat 2”命令的终端窗口,观察“ buff”列和“ cache”列的变化,“ cache”列的值一直在增加,而“ buff”列的值基本不变。上图中,大家只需要关注“ buff”这个表示缓冲区的列,以及“ cache”这个表示缓存的列,单位都是KB。
2024-08-18 14:22:04
1172
原创 性能优化理论篇 | swap area是个什么东西
为了理解启用交换空间对 Linux 性能的影响,我们首先需要了解交换空间的概念。从物理层面(存储层面)看,交换空间只是辅助存储器(Secondary Memory)如硬盘上的一个特殊区域,用于在 RAM 不足时临时存储数据。当系统内存(RAM)不足时,操作系统会将一些不常使用的数据从 RAM 中移出,暂时存放在这个交换空间中,以腾出 RAM 空间给需要的程序。从虚拟内存的概念来看,交换空间是虚拟内存的一部分。虚拟内存是操作系统通过将物理内存(RAM)和硬盘上的交换空间结合起来使用的一种机制。
2024-08-17 10:57:54
1152
原创 性能优化理论篇 | 彻底弄懂系统平均负载
这是最常见的一个误解(由于对进程状态缺乏了解而导致的),正如我们上面多次强调的那样,平均负载包括处于 R 状态(正在运行和准备运行)和 D 状态(不可中断睡眠状态)的进程。而对于下图,系统中的“平均负载”一直在减少,该系统15 分钟的“平均负载”为“5.05”。5 分钟的“平均负载”为“3.53”,而最近 1 分钟的“平均负载”为“0。下图中系统中的“平均负载”一直在增加,该系统15 分钟的“平均负载”为“3.25”。5 分钟的“平均负载”为“5.48”,而最近 1 分钟的“平均负载”为“6.00”。
2024-08-17 10:55:31
933
原创 Java基础 | 一文搞懂浅拷贝与深拷贝
通过[3]和[4]的输出可知:源对象和拷贝的对象中的的引用类型变量address地址也一样,说明深拷贝将引用类型的成员变量对象也 拷贝了一份,这是不同于浅拷贝的地方。通过[3]和[4]的输出可知:school和otherSchool中的的引用类型变量address地址一样,说明浅拷贝只是将school中的成员address的引用值(内存地址)复制一份给otherSchool中的address,并不会为引用类型成员变量创建新的对象。引用拷贝不属于对象拷贝,因为它并不会拷贝新的对象,下面介绍的。
2024-08-16 16:14:17
1091
原创 并发编程 | 线程池的拒绝策略
自定义拒绝策略可以让你在线程池任务被拒绝时,定义自己的处理逻辑。这样你就可以根据具体的业务需求来决定当线程池无法处理新的任务时应该做什么。要自定义拒绝策略,你需要实现RejectedExecutionHandler接口。这个接口有一个方法rejectedExecution(Runnable r, ThreadPoolExecutor executor),当任务被拒绝时,这个方法会被调用。在rejectedExecution方法中,你可以定义自己的处理逻辑。
2024-08-16 16:13:13
1044
原创 并发编程 | 线程池的自动创建
通过程序的运行结果可以看出,调用scheduleWithFixedDelay执行周期任务,这个周期是以上次任务结束的时间为起点开始计时,因此定时的周期不但和设置的参数有关,还和任务的执行时间有关,如本例我设置的周期是3s,任务的执行时间是2s,那么第一次执行任务的时间是16:07:07, 任务执行了2s在16:07:09结束第一次任务,那么在16:07:09的基础上再过3s之后也就是16:07:12 时刻第二次执行任务,以此类推周期执行。注意这个方法只会执行一次任务,后续就不会再执行该任务了。
2024-08-15 18:51:36
994
原创 并发编程 | 线程池的手动创建
corePoolSize:核心线程数,线程池初始化时线程数默认为 0,当有新的任务提交后,会创建新线程执行任务(注意不是在初始化 ThreadPoolExecutor 时立即创建),如果不做特殊设置,此后在程序的运行过程中,线程数通常不会再小于 corePoolSize ,因为它们是核心线程,即便未来可能没有可执行的任务也不会被销毁。我们可以选择使用默认的线程工厂,创建的线程都会在同一个线程组,并拥有一样的优先级,且都不是守护线程,我们也可以选择自己定制线程工厂,为线程指定名字、优先级、守护线程等属性。
2024-08-15 17:50:34
664
原创 你和NumPy之间,只差这40张图
NumPy 是 Python 生态系统中用于数据分析、机器学习和科学计算的核心工具包。它极大地简化了向量和矩阵的操作。许多重要的开发工具包,如 scikit-learn、SciPy、pandas 和 tensorflow,都建立在 NumPy 的基础上。掌握 NumPy 不仅有助于对数值数据进行切片和交叉分析,还能在处理和调试这些库时为你带来优势。
2024-08-14 08:30:38
973
原创 大厂最佳实践 | Stripe 如何防止重复付款
如果不存在,说明这是一个新的请求,服务器处理请求,并将幂等key和响应结果一起缓存在数据库中(如Redis)。为了帮助您理解,我再举一个更具体的例子,假设你正在用Stripe支付一笔费用,但由于网络问题,没有响应回来,你以为付款失败了,于是你就重新点击了一次支付按钮。由于加入了抖动,不同用户的重试时间就会有所不同,这样可以防止服务器在同一时间受到大量重试请求的冲击,从而减轻服务器的压力,防止过载。虽然使用幂等key之后,重试变的安全了,不会造成重复付费问题了,但是过多的重试请求可能会导致服务器过载。
2024-08-14 08:28:53
674
原创 如何向10岁小孩解释清楚贝叶斯定理 !
贝叶斯定理在提出来后的很长一段时间,大家并没有觉得它有什么作用,并一直受到主流统计学派的排斥。直到计算机的诞生,贝叶斯定理的强大作用才逐渐显现出来。人们发现,贝叶斯定理可以广泛应用于数据分析、模式识别、统计决策,甚至是当前最热门的人工智能领域,可以说,掌握并应用贝叶斯定理,是每个人必备的技能。为了弄清楚贝叶斯定理到底要解决什么问题,我们先来看一个现实生活中的例子:假设有一种疾病,其发病率为0.1%。现在,如果一个人测试显示阳性,请问他患病的概率是多少?
2024-08-13 06:45:41
973
原创 feed流设计要点记录
读写混合模式下读写混合模式下,系统需要做两个判断:哪些用户属于大V,我们可以将粉丝量作为一个判断指标;哪些用户属于活跃粉丝,这个判断标准可以是最近一次登录时间等。数据库设计 帖子表+ 计数表 CREATE TABLE feeds ( post_id1 BIGINT AUTO_INCREMENT PRIMARY KEY, -- 动态 ID,唯一标识每条动态 author_id BIGINT NOT NULL, -- 发布动态的用户 ID
2024-08-12 11:55:20
736
原创 谷歌科学家:《改变你职业生涯的一篇文章,我如何运用人工智能完成工作》建议每个人都要读一遍
通常,我不是那种轻易相信任何事物的人。比如,尽管我经历了十年前信息安全界的加密货币热潮,我却从未参与撰写任何关于区块链的研究论文。我也从未拥有过任何比特币,因为在我看来,它们除了用于赌博和欺诈之外,没有任何实际价值。我一直持怀疑态度,每当有人向我宣称“某项新技术将改变世界”,我的反应总是冷漠。因此,当第一次有人告诉我人工智能将极大地提升我的工作效率并改变我的日常工作方式时,我同样持保留态度,我的回应是:“见到实际效果我才会信。”此外,我是一名安全研究员。
2024-08-12 08:53:42
283
原创 微软、Google、百度、腾讯等名企经典面试题
给大家整理了微软、Google、百度、腾讯这些企业比较常考察的面试题,大家可以尝试自己去解解,如果没有解出来再在网上搜索下,看看这些题的思路。
2024-08-11 13:32:20
496
原创 手绘图系列 04 | 使用频率最高的”树“
到目前为止,我们主要介绍了一些线性的数据结构,如链表、队列、栈。在这些结构中,数据是有序的,而且顺序很重要。今天我们要跳出这个框框,进入一个更加“有挑战性”的领域——非线性数据结构。我们将从使用频率最高的”树“开始!记住!树是一种非常重要的非线性数据结构。
2024-08-10 15:24:06
1039
原创 从小白到架构师 | 系统可用性建设,你系统可用性高于4个9了吗?
可用性是指系统正常运行时间占实际运行时间的比例。所以,可用性其实是一个百分比,如99.9%。Availability = Uptime /(Uptime + Downtime) Uptime:系统正常运行的时间。Downtime:由于故障、维护或其他问题,系统不可用的时间段。
2024-08-09 17:16:51
992
原创 从小白到架构师 | 数据库优化最后的杀手锏---数据库分片
简单来说,数据库分片是一种将数据分布到多台机器上的方法。当单台数据库实例无法处理预期的工作负载时,分片往往可以解决问题。我们可以通过几种方式对数据进行分片,并将特定的表移至对应的数据库实例上。一种方式称之为垂直分片(Vertical Sharding),它是根据表的列来分割数据。例如一个用户表,里面包含了很多列,比如 user_id、name、email、address、phone_number 等。当数据量很大时,这个表可能会变得很庞大,也难以管理。
2024-08-09 16:17:33
715
原创 高并发下的分布式缓存 | Write-Through缓存模式
[高并发下的分布式缓存 | 缓存系统稳定性设计](https://editor.csdn.net/md/?articleId=140971647)[高并发下的分布式缓存 | 设计和实现LRU缓存](https://editor.csdn.net/md/?articleId=140901891)[高并发下的分布式缓存 | 设计和实现LFU缓存](https://editor.csdn.net/md/?articleId=140901918)[高并发下的分布式缓存 | Cache-Aside缓存模式](h
2024-08-08 09:10:58
1545
原创 高并发下的分布式缓存 | Read-Through缓存模式
[高并发下的分布式缓存 | 缓存系统稳定性设计](https://editor.csdn.net/md/?articleId=140971647)[高并发下的分布式缓存 | 设计和实现LRU缓存](https://editor.csdn.net/md/?articleId=140901891)[高并发下的分布式缓存 | 设计和实现LFU缓存](https://editor.csdn.net/md/?articleId=140901918)[高并发下的分布式缓存 | Cache-Aside缓存模式](h
2024-08-08 09:09:12
1348
原创 高并发下的分布式缓存 | Cache-Aside缓存模式
在高并发的场景下,如果我们在更新数据时采用先使缓存失效,再更新数据库,如果某个时刻,同时有一个读请求和一个更新请求操作同一条数据,更新请求刚好让这条数据在缓存失效,然后读请求读取时缓存未命中(因为数据已被更新请求从缓存中删除),就会从数据库中获取旧数据并添加到缓存中。因此,代码需要实现重试机制。如果缓存中没有需要的数据,这叫做缓存未命中,这种情况下,应用程序需要从数据库中获取这个数据,从数据库中拿到数据后,应用程序还会将数据存入缓存,以便下次再需要这个数据时,可以直接从缓存里获取,而不需要再去查数据库。
2024-08-07 08:44:17
1226
原创 高并发下的分布式缓存 | 缓存系统稳定性设计
但如果在获取锁后再次检查 data,就能发现 A 线程已经从数据库获取了数据并将其放入缓存中,这样 B 线程就可以直接使用缓存中的数据,而无需再访问数据库。第一次判空:在代码的最开始,系统从缓存中尝试获取 data。缓存击穿是指一个热点数据在缓存中失效后,可能同一时刻会有很多对该热点数据的请求,这些请求都无法在缓存中找到该数据,因此都会访问数据库,导致数据库压力骤增。缓存雪崩是指在某个时间点,缓存中大量数据同时失效,或者缓存节点不可用,导致大量请求直接访问数据库,给数据库带来巨大压力,甚至导致数据库崩溃。
2024-08-07 08:43:28
1330
原创 在Linux上做了10年开发,Linux系统的文件权限竟然还没完全弄清楚 !
在 Linux 中,新创建文件或者目录都有一个 默认权限。文件:新建文件默认的权限是 666(即 rw-rw-rw-),表示所有者、组和其他用户都可以读取和写入文件,但不能执行。目录:新建目录的默认权限是 777(即 rwxrwxrwx),表示所有者、组和其他用户都可以读取、写入和执行目录。在 Linux 中,“权限掩码”(umask)是一个控制新建文件/目录的默认权限的机制。它通过设置一个“掩码”来限制文件和目录的初始权限。
2024-08-06 09:07:24
683
原创 从小白到架构师 | 六张图弄清楚数据库复制的各种架构
数据库复制是指将相同数据的多个副本保存在不同的数据库服务器(也叫副本或实例)中的过程。这样,如果某个数据库服务器出现问题,其他服务器仍然可以继续为用户提供数据服务。这种方式能够提高系统的性能、可用性和可靠性。想象一下,一个公司把重要的文件复印了好几份并放在不同的地方,这样即使其中一份丢失了,其他地方还有备份,工作也不会受到影响。数据库复制就像这种“复印”的过程,只不过过程复杂很多。假设有一家在线商店,它只有一个数据库服务器,存储了所有与产品、订单和客户相关的数据。
2024-08-06 09:03:16
913
原创 这其实是个概率问题,一个例子揭秘 HyperLogLog 的高效计数技巧 !
桶记录遇到的最大连续零的数量。每次分配给一个桶的数字,如果连续零的数量超过桶中存储的数量,桶会更新。当然,我们没有减少规模的选项,因为我们不能告诉用户不要访问网站,但如果我们在显示的数字精度上做一些妥协,我们还是可以接受的。我在谷歌上搜索了互联网大厂是如何解决这个问题的,令人惊讶的是,这个看起来很简单的问题竟然是计算机科学中最著名的问题之一,称为“计数独特问题”。在计算出哈希所属的存储桶之后,我们将获得该哈希的最大尾随零,如果哈希的最大尾随零大于存储桶中存储的零,则更新存储桶(第 19-23 行)。
2024-08-05 16:35:08
773
原创 图+代码 | Bloom Filter实现及应用
布隆过滤器是一种空间复杂度很低的概率型数据结构,用于判断一个元素是否在一个集合中。元素可能在集合中:这可能是一个真阳性(确实在集合中)或假阳性(实际上不在集合中)。元素肯定不在集合中:这是一个真阴性。简单来说,布隆过滤器能告诉你一个元素可能存在或肯定不存在。它非常节省内存,但有一定概率会给出错误的“存在”结果(即假阳性)。布隆过滤器是一种设计用来快速、节省内存地判断元素是否在集合中的数据结构。它的特点是有可能出现“假阳性”——即报告某个元素存在,而实际上不存在。
2024-08-05 16:15:09
517
原创 高并发下的分布式缓存 | 设计和实现LFU缓存
最少使用频率 (LFU) 是一种用于管理计算机内存的缓存算法。在这种算法中,系统会跟踪缓存中每个数据被引用的次数。当缓存已满时,系统会删除引用频率最低的数据。
2024-08-04 09:29:01
1009
原创 高并发下的分布式缓存 | 设计和实现LRU缓存
LRU缓存是一种缓存策略,当缓存满了,需要腾出空间存放新数据时,它会删除最近最少使用的数据。换句话说,它会优先淘汰那些最久没有被访问的元素,以确保缓存中的数据是最近使用的,这对提高缓存系统的命中率有帮助。
2024-08-04 09:27:27
1163
原创 服务扛不住了,你是加机器还是堆硬件了?
当您的系统面临用户量增多时,它需要更多的资源来处理更多的请求,两种常见的方法是垂直扩展和水平扩展。在本文中,我们将探讨这两种扩展策略的优缺点,并讨论如何选择。垂直扩展垂直扩展是通过增强系统内现有机器的硬件以应对流量的增加,这可能意味着升级CPU、RAM、存储或其他硬件以增强服务器的处理能力。垂直扩展的优点垂直扩展的缺点水平扩展(横向扩展)水平扩展意味着向系统添加更多机器,以将工作负载分散到多个服务器上。每台机器都运行应用程序的一个副本,并且通常使用负载平衡器将流量相对均衡的分发到每个实例上。
2024-08-03 15:25:33
635
原创 支撑英雄联盟750万同时在线用户的聊天系统底层的CRDT是什么?
CRDT 是什么意思?CRDT是Conflict-Free Replicated Data Types的缩写,直译的话即“无冲突可复制数据类型”。翻译过来还是一脸懵逼!用稍微通俗一点的话说:研究分布式系统,尤其是研究最终一致性分布式系统的过程中,一个最基本的问题就是,应该采用什么样的数据结构来保证最终一致性?CRDT即是理论界目前对于这个问题的答案!当然理论界的思路现在不是所有人能跟上的,需要更加简单的解释。
2024-08-03 12:03:50
804
原创 从小白到架构师 | 缓存预热
缓存预热指的是在系统启动或上线前,提前将经常访问的数据加载到缓存中,以避免在系统刚启动时,用户大量请求直接访问数据库,导致数据库压力过大或系统性能下降。通过缓存预热,可以确保系统一上线就能提供快速的响应时间和良好的用户体验。
2024-08-02 19:17:21
341
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人