IT技术博客大学习 共学习 共进步
全部 移动开发 后端 数据库 AI 算法 安全 DevOps 前端 设计 开发者

最新文章

采集自各技术站点的近期文章。

IT 后端/ 2016-03-18 17:09:16 / 累计浏览 1,963

图解微服务架构演进

这篇讲的是随着业务规模扩大,传统单体应用架构如何一步步演进到微服务架构的完整路径。 作者从 Dubbo 用户手册的一句话切入,点明了架构升级的背景:常规垂直应用架构已无法应对互联网发展,服务化改造势在必行。文章核心是梳理了服务化架构的演进阶梯:最初是功能内聚但扩展性差的 **ORM 单体架构**;随后为提升性能,演化出便于前后端分离、加速开发的 **MVC 垂直应用架构**;当应用间交互增多,便抽离核心业务,通过 **RPC 分布式服务框架** 实现复用与整合;随着服务数量激增,需要调度中心进行统一管控,形成了 **SOA 流动计算架构**。 最终,演进到了微服务架构。它的核心思想是将功能进一步拆解为更原子、自治的服务单元进行高密度部署,以实现彻底的解耦。文章也结合敏捷开发、持续交付和容器化(Docker)等趋势,指出微服务是应对复杂度的必然演进方向。整个梳理逻辑清晰,从历史演进的角度为理解微服务提供了一个扎实的上下文。

本机暂存
IT 后端/ 2016-03-18 17:07:19 / 累计浏览 1,607

缓存系列文章–无底洞问题

这篇讲的是分布式缓存系统中一个经典陷阱——“无底洞”问题。作者从Facebook大规模Memcached集群的实践切入,指出盲目增加节点不仅无法提升性能,反而会导致批量操作(如mget)因网络次数暴增而变慢。 问题的根源在于哈希分布下,大量key被打散到不同节点。一次批量获取需要跨多次网络IO,机器越多,耗时越长。文章对比了哈希分布与顺序分布的特点,并给出了四种应对方案:最简单的串行mget(O(n)网络时间),优化后的按节点分组串行IO(O(节点数)网络时间),以及多线程并行IO和利用Redis的hash-tag强制key到同一节点。 通过对比可以看出,从“串行mget”到“hash-tag”,核心思路都是尽可能减少网络往返次数。文章最后用清晰的表格总结了各方案的优劣与适用场景,为开发者在数据分散与访问效率之间做出权衡提供了明确参考。

本机暂存
IT 后端/ 2016-03-18 17:04:16 / 累计浏览 2,863

Java注解全面解析

这篇讲的是Java注解的核心机制与演进。作者从注解的基本语法切入,解释了它看起来像接口但本质不同的特点,并重点拆解了`@Target`和`@Retention`这两个元注解如何控制注解的“作用目标”与“生命周期”。 文章不仅梳理了四大元注解的功能,还深入探讨了注解元素的类型限制(比如不能用包装类型,不能用`null`作为默认值)以及“快捷方式”语法的实现条件——即只有名为`value`的唯一元素时方可省略键名。 对于开发者更关心的JDK 1.8增强,文章详细对比了新增的`TYPE_PARAMETER`和`TYPE_USE`枚举成员的使用场景差异,并通过`@Repeatable`注解的案例,展示了如何实现同一位置的重复声明及其底层的容器收集机制。这使得全文不仅是一份语法手册,更像一份从基础到实战特性的清晰路线图。

本机暂存
IT 算法/ 2016-03-18 17:03:31 / 累计浏览 2,313

大数据过滤及判断算法 -- Bitmap / Bloomfilter

这篇讲的是如何用极低的空间成本,高效判断一个元素是否存在于海量数据集合中。作者从一道常见的面试题出发,引出了两个核心数据结构:Bitmap与Bloomfilter。 文章首先剖析了Bitmap,它本质上就是一块连续的内存位图,每个bit(0/1)直接对应一个元素的“无/有”。作者展示了如何通过简单的位运算(`/8`和`%8`)定位到具体的bit位,并给出了一个完整的C++代码示例,用于在一个10万规模的集合中精确查找缺失的数字。Bitmap的优点是100%准确,但缺点是所需内存与元素值的范围直接相关。 接着,文章重点介绍了Bloomfilter。它通过多个哈希函数对同一个值进行多次哈希,将结果映射到不同的bit位上。这种设计能用远小于Bitmap的内存处理更海量的数据,但代价是存在理论上的误判——可能将不在集合的元素误判为“存在”。作者解释了误判率与哈希函数数量、内存大小的关系,并提供了包含三种经典哈希函数(BKDR、FNV、DEK)的实现代码。 文末,作者还留下了一个思考题:对于“从1到100万无序数中找出被随机取走的N个数”这个问题,除了这两种方法,还可以如何利用数学性质(如求和、求积)来间接求解?这展示了不同场景下算法选择的灵活性。

本机暂存
IT 后端/ 2016-03-18 17:01:41 / 累计浏览 3,008

操作系统基础知识

这篇讲的是操作系统面试中几个核心概念的对比与辨析。文章没有泛泛而谈,而是聚焦于死锁、链接库、进程与线程、进程间通信这几个经典问题,通过问答的形式拆解要点。 关于死锁,它清晰地列出了四个必要条件(互斥、请求与保持、非剥夺、循环等待),并介绍了从忽略问题到破除条件的四种处理策略,其中“鸵鸟算法”的比喻让策略选择显得更生动。 在链接库部分,文章对比了静态库(.lib)与动态库(.dll)的核心区别:前者在编译时代码被强制装入程序,增大体积但运行稳定;后者在运行时按需加载,能有效节省内存空间,更适合大型项目。 对于进程与线程,文章从概念、执行过程和逻辑关系三个层面展开。关键在于,进程是资源分配的基本单位,拥有独立内存空间;而线程是CPU调度的基本单位,共享进程资源,是程序中可并行执行的路径。 最后,文章梳理了用户进程间通信的几种主要方式,如管道、消息队列等,并以管道为例说明了其单向、阻塞的特性。整体而言,文章将抽象的理论知识梳理成了清晰的对比条目,有助于读者快速建立起对这些基础概念的理解框架。

本机暂存
IT 算法/ 2016-03-18 16:59:03 / 累计浏览 2,679

Trie树(字典树) 最热门的前N个搜索关键词

这篇讲的是Trie树,也叫字典树,一种专门用来高效处理字符串的树形数据结构。它的核心思想很巧妙,通过“空间换时间”,利用字符串的公共前缀来共享存储路径,从而最大化地减少不必要的比较,让查询和插入操作的时间复杂度直接与单词长度挂钩,而不是单词数量。 文章里用了一组清晰的图示和例子,一步步展示了Trie树是如何从零构建起来的。比如,当你有 `inn, int, at, age` 这些单词时,像 `inn` 和 `int` 就可以共享 “in” 这个前缀的分支。这种结构让查找操作变得非常直接:只需顺着字符路径走到底,再检查终点节点是否被标记为“存在”即可。 更实用的是,文章没有停留在原理,而是直接给出了两个经典的应用场景。一个是统计海量文本中出现频率最高的词,另一个是在千万级的搜索日志中,用有限内存找出最热门的查询串。在这两个问题里,Trie树都扮演了高效的计数和索引角色,再结合堆进行排序,就能得出最终结果。对于想理解如何将数据结构用于解决实际工程问题的人来说,这篇文章的路径很清晰。

本机暂存
IT 移动开发/ 2016-03-18 16:50:56 / 累计浏览 3,488

React-Native学习指南

这份指南旨在为React-Native开发者提供一站式资源导航。它从最基础的入门指南、视频教程开始,帮助新手快速上手,同时也收录了官方API文档及其高质量的中文翻译版本。 更深入的部分,文章整理了关于通信机制、布局实践、模块桥接以及如何在原生应用中集成React-Native等进阶主题的技术解析。除了React-Native核心内容,它还贴心地附上了React.js的入门资料链接,因为掌握前端基础对于理解框架至关重要。 这份资源合集还在持续更新,并关联了知名的Awesome React-Native社区仓库。它更像是一个由社区驱动、不断生长的知识索引,为不同阶段的开发者都提供了直接可用的学习路径。

本机暂存
IT DevOps/ 2016-03-18 14:14:23 / 累计浏览 2,522

Docker基础技术:Linux CGroup

这篇讲的是Docker背后的核心资源隔离技术——Linux CGroup。作者从Namespace只解决“环境隔离”但无法限制“资源使用”这一痛点切入,引出了CGroup的必要性。 CGroup(控制组)是Linux内核的功能,最初由Google工程师在2006年发起,旨在为进程组分配和隔离CPU、内存、磁盘I/O等计算资源。文章清晰地归纳了它的四大核心能力:资源限制、优先级控制、审计统计以及进程挂起/恢复。这些能力让系统管理员能像为虚拟机分配资源一样,精细地管控容器或一组进程。 文中通过一个生动的实例展示了CGroup的威力:一个耗尽CPU的“死循环”程序,在被加入一个CPU份额设为20%的CGroup后,其CPU占用立刻降至约20%。这种通过操作 `/sys/fs/cgroup` 下的文件(如 `cpu.cfs_quota_us` 和 `tasks`)来即时调控资源的方式,直观地体现了CGroup作为一种基于文件系统的接口的设计思路。对于想理解Docker如何实现资源限制的读者,这篇文章提供了扎实的原理和可动手实践的细节。

本机暂存
IT DevOps/ 2016-03-18 14:13:05 / 累计浏览 2,334

Docker基础技术:Linux Namespace(下)

这篇讲的是Docker底层Linux Namespace的后半部分,作者从上一篇的铺垫出发,聚焦在User Namespace和Network Namespace这两个关键能力上。对于User Namespace,文章不仅解释了容器内用户身份被重映射(默认为65534)的原理,还深入到了`/proc//uid_map`文件的三字段格式与写入规则,并附上一段完整的C代码示例,展示了如何通过父子进程协作与管道同步,在创建容器时完成从普通用户到容器内root的UID映射,以此提升安全性。在Network Namespace部分,文章通过一张经典的Docker宿主机网络示意图,说明了容器如何获得独立的网络栈,并提及了`docker0`网桥、`veth`虚拟网卡对以及容器默认使用的私有网段。整体内容硬核,将抽象的隔离机制与具体的文件操作、代码实现紧密结合,对于想深入理解容器安全与网络隔离根基的读者来说,是一篇扎实的进阶指南。

本机暂存
IT DevOps/ 2016-03-18 14:12:04 / 累计浏览 3,399

Docker基础技术:Linux Namespace(上)

这篇讲的是Docker“新瓶装旧酒”背后的关键内核技术——Linux Namespace。作者从Docker并非全新技术切入,指出其核心是巧妙运用了已有的Linux内核能力,旨在带读者“山寨”一个简易Docker。 文章重点解析了Namespace提供的六种隔离机制,包括UTS(主机名)、IPC(进程间通信)、PID(进程ID)等。作者并未停留在概念罗列,而是通过一组清晰的C语言代码示例,一步步演示了如何使用`clone()`系统调用配合不同的`CLONE_NEW*`参数,来实现具体的隔离效果。例如,子进程在独立的UTS命名空间中修改hostname,不会影响宿主机;在独立的PID空间里,其初始进程会成为PID 1。 这种“上代码、看结果”的讲解方式,将抽象的“环境隔离”概念变得直观可感。对于想理解容器技术(不仅仅是Docker)底层原理的开发者而言,文章提供了从理论到动手验证的完整路径,是理解Linux容器化技术基石的实用入门。

本机暂存
IT 数据库/ 2016-03-18 14:09:18 / 累计浏览 3,993

[MySQL优化案例] — slave延迟很大优化方法

这篇讲的是如何解决MySQL主从复制中常见的从库延迟问题。作者从根因出发,指出核心矛盾在于主库的并发事务提交与从库单线程复制之间的不匹配,以及MySQL传统的异步复制机制本身就会引入延迟。 针对这些痛点,文章梳理了几条切实可行的优化路径。其核心思路是提升从库的并行处理能力和IO效率。例如,推荐使用实现了真正并行复制的MariaDB版本作为从库;强调业务表必须显式定义主键以避免大表全表扫描;在应用层合并写请求以减少数据库压力。 在硬件和系统层面,文章也给出了从高到低的优化排序,包括升级为SSD/PCIe-SSD、增大内存以扩大Buffer Pool、将文件系统更换为XFS或ReiserFS、调整RAID级别为RAID 1+0并开启写缓存,以及将IO调度器改为deadline或noop。这些措施从不同层面缓解了从库的IO瓶颈,组合使用能有效改善复制延迟。

本机暂存
IT 后端/ 2016-03-18 14:03:25 / 累计浏览 3,702

PHP-FPM中backlog参数变更的一些思考

这篇讲的是PHP-FPM中`backlog`参数两次关键默认值变更背后的技术权衡。作者从2013年PHP 5.5.6将默认值从-1提升至65535说起——当时的初衷是避免因队列满而静默丢弃TCP连接,宁愿报错也不悄悄丢包。但到了2014年,这个值又被调整为511,理由是65535的队列过长,容易导致前端Nginx因等待超时而关闭连接,最终PHP-FPM处理完请求写回时遇到“Broken Pipe”,白白浪费资源。文章指出,调整后的511与Nginx、Redis等常见组件的默认值对齐,更符合实际生产中的连接超时节奏。作者还结合Linux手册中对`listen()`系统调用的说明,梳理了`backlog`队列在不同内核版本中的行为演变,并对比了各方修改补丁的论述,揭示了这个看似简单的参数在高并发场景下对系统吞吐与资源效率的深刻影响。

本机暂存
IT 后端/ 2016-03-18 14:01:19 / 累计浏览 2,941

Lua C API 的正确用法

这篇讲的是在C/C++宿主程序中嵌入Lua时,最容易被忽视的陷阱:如何正确处理Lua的异常(error)机制。文章指出,很多开发者会忽略C API调用可能抛出异常这一点,导致程序出现未定义行为甚至直接崩溃。 作者从基础讲起,强调所有可能出错的API调用(如lua_tostring)都应被lua_pcall或lua_resume保护起来。文章用一个创建虚拟机的简单代码示例,清晰地展示了即使luaL_openlibs也可能因未捕获异常而带来风险,并推荐将核心逻辑封装为lua_CFunction再通过lua_pcall调用。 进阶部分深入讨论了在C++或多语言环境(如Unity的mono)中,Lua的异常机制(基于longjmp/throw)与宿主语言异常系统(如C++ RAII、.NET CLR)的协同难题。文章警告,直接用宿主语言的异常处理(如C++的try-catch)去捕获Lua API异常会破坏虚拟机状态,因此必须精心设计接口,将Lua与宿主视为两个通过消息通信的独立运行时,而非共享异常上下文。 最后,文章提到了在C扩展中初始化对象字段、管理栈空间等实用技巧,并附上了作者为解决跨语言交互问题而编写的示范代码。全文聚焦于“正确性”而非性能,对于任何需要深度集成Lua的开发者来说,这是一份避开关键坑点的实用指南。

本机暂存
IT 开发者/ 2016-03-18 12:37:09 / 累计浏览 2,971

Mac实用技巧——在Finder中显示文件完整路径

这篇讲的是一个让Mac Finder显示文件完整路径的实用技巧。在默认设置下,Finder只会在标题栏显示当前文件夹的名字,而不会显示完整路径,这给需要频繁导航多层目录的用户带来了不便,尤其是在处理复杂项目文件时,常常需要反复点

本机暂存
IT DevOps/ 2016-03-17 00:07:26 / 累计浏览 1,545

Linux文件系统基础之inode和dentry

这篇讲的是Linux文件系统中两个最核心的元数据结构——inode和dentry,以及它们如何协同工作来构建我们熟悉的文件目录。 作者从虚拟文件系统VFS的抽象层入手,解释了为什么需要这些结构来统一管理底层不同的实体文件系统(如ext4)。文章指出,inode是内核中文件对象的唯一标识,它存储了权限、属组、数据块位置等所有静态元数据,但刻意不包含文件名。而文件名与inode的映射关系,则由目录项dentry在内存中动态建立和维护。 通过阅读文件路径时内核的解析过程,文章清晰地展示了dentry如何通过内存中的树状结构,高效地缓存和还原出文件系统的目录层次。这种设计将稳定的磁盘结构与灵活的内存缓存分离,是Linux文件系统高性能的关键。 理解了inode和dentry,文章最后点明,文件链接的奥秘也迎刃而解:软链接拥有独立的inode和内容,而硬链接仅仅是为同一个inode在目录项中新增了一条名字映射,并通过引用计数管理生命周期。整篇文章从底层原理出发,把看似复杂的文件系统机制拆解得条理分明。

本机暂存
IT DevOps/ 2016-03-17 00:05:02 / 累计浏览 2,545

securecrt linux与windows 互传文件

这篇讲的是如何用SecureCRT自带的sz/rz命令,来替代传统FTP/SFTP工具进行Windows与Linux间的文件互传。作者开篇就点出了常见方案的痛点:FTP/SFTP工具操作繁琐,尤其在目录层级较深时体验不佳。 文章的核心是介绍sz(下载)和rz(上传)这对命令。通过具体配置和代码示例,它展示了如何先在SecureCRT中设置默认的传输目录,然后直接使用`sz 文件名`将Linux文件下载到指定本地路径,或使用`rz`弹出窗口选择本地文件上传到Linux当前目录。整个过程不需要启动额外客户端,直接在终端里就能完成。 不过,文章也坦诚地指出了局限:sz/rz对于小文件传输非常便捷,但传输大文件时速度会比较慢。因此,这个方案特别适合那些需要频繁、快速交换中小型文件的运维或开发场景,能显著提升工作效率。

本机暂存
IT 前端/ 2016-03-17 00:02:35 / 累计浏览 5,816

给HTML初学者的30条最佳实践

这篇来自Nettuts+的文章专为刚踏入Web开发领域的HTML初学者准备,作者从实际编码中最易犯错的细节出发,系统梳理了30条旨在培养良好习惯的编码实践。 文章并非空谈理论,而是从“保持标签闭合”这类基础却至关重要的习惯讲起,直指新手常犯的省略标签、忽略包裹容器等错误。随后,它明确了声明正确DOCTYPE的必要性,并强烈建议将样式与结构分离——坚决使用外部CSS,杜绝内联样式。对于提升页面性能,文章给出了具体方案:将CSS链接置于``以加快渲染,而将JavaScript文件放在``标签前以避免阻塞页面呈现。作者甚至告诫“现在不是1996年了”,应摒弃内联JS的陈旧写法。贯穿全文的是“边开发,边验证”的理念,强调利用验证工具辅助编写标准、健壮的代码。 这些实践看似简单,却是构建可维护、高性能网页的基石。对于经验尚浅的开发者,遵循这些准则能有效规避早期养成的坏习惯,为后续学习更复杂的技术打下扎实、规范的基础。

本机暂存
IT 前端/ 2016-03-17 00:00:52 / 累计浏览 3,261

JavaScript 封装问题

这篇讲的是一个在 JavaScript 面向对象编程中,开发者容易踩到的具体“坑”。作者从百度知道的一个提问出发,发现不少开发者在使用构造函数和原型(prototype)封装类时,会习惯性地在函数内部给 prototype 赋值,从而导致实例化后调用原型方法时报错“XX is not a function”。 文章通过代码重现了这个问题,并深入分析了根因:JavaScript 引擎在执行 `new` 操作符时,会先基于构造函数内部的 `this` 创建一个新对象,然后才执行构造函数体内的代码。这意味着,当我们在函数内部书写 `Dialog.prototype = {...}` 这行代码时,其实是在函数执行期间动态替换了原型对象。然而,当前这个实例在创建时,其内部的 `[[Prototype]]` 指向的还是旧的、空的原型对象。因此,实例无法访问到新定义的原型方法。 正确的封装做法,是将原型的定义放在构造函数的外部、紧随其后的代码中。这样可以确保在创建任何实例之前,原型方法就已经稳定地定义好了。这个案例提醒我们,理解 JavaScript 原型链的绑定时机至关重要,一个简单的代码顺序差异,就会导致截然不同的运行结果。

本机暂存
IT 前端/ 2016-03-16 23:45:26 / 累计浏览 1,715

一些有用的HTML5 pattern

这篇讲的是手机端表单输入体验的一个具体痛点。作者从实际开发中遇到数字键盘显示多余的字母出发,对比了 HTML5 中 `type="tel"` 和 `type="number"` 的优劣:前者键盘统一但字母碍眼,后者在 Android 上是纯数字键盘,但在 iOS 上体验不佳,且旧版 Android 还有样式小尾巴。 为了解决这些不完美,作者深入探索了 `pattern` 属性。文章指出,虽然 `pattern` 的主要作用是通过正则表达式进行前端格式验证,但它的写法会影响移动端调起的键盘类型。例如,在 iOS 上,`pattern="[0-9]*"` 能成功调出九宫格数字键盘,而 `pattern="\d"` 则不行;到了 Android 高版本,系统则更认 `type` 属性本身。 文章还整理了一份实用的常用正则表达式清单,涵盖了信用卡、手机号、身份证、密码等多种常见表单场景。尽管 `pattern` 的整体浏览器支持情况不理想,但对于开头提到的优化数字输入键盘这一具体需求,它在 iOS 和 Android 主流设备上都能有效工作,为开发者提供了一个轻量级的解决方案。

本机暂存
IT 后端/ 2016-03-16 23:42:05 / 累计浏览 2,405

记一次内存泄露的debug过程

这篇讲的是作者在压测“代码在线运行”工具时,遭遇了高并发下内存飙升且无法回落的问题。从自身代码审查无果,他转向使用Go语言内置的pprof工具进行深度剖析。 通过分析堆内存分配的热点,问题指向了goroutine与ioPipe的交互。作者进一步验证,发现大量goroutine因ioPipe未被正确关闭而持续存在,无法回收,从而造成了内存的持续累积。根源在于异常退出前未主动关闭资源。 定位后,解决方案变得清晰:在程序逻辑中确保主动关闭ioPipe的Reader。修复后,作者使用wrk工具进行了长时间压测,并监控goroutine数量,确认内存占用稳定,问题得以解决。文章结尾点出,这个因粗心引起的小bug,修复却需借助专业工具链,提醒开发者熟悉语言提供的诊断工具至关重要。

本机暂存