IT技术博客大学习 共学习 共进步
首页 / 博学无忧
IT 2020-02-05 15:09:47 / 累计浏览 2,660

位运算技巧整理

这篇讲的是位运算(&、|、^、~)的基础规则与实用技巧的整理。作者从最基本的四种操作讲起,但真正的亮点在于后续展示的几招“组合技”:比如,利用“一个数和自己异或结果为0”的特性,可以高效找出数组中唯一一个出现奇数次数的数字;再如,当除数是2的幂次方时,用 `num & (len-1)` 来取余数,比直接用取模运算符 `%` 的效率更高。 文章还系统梳理了十进制与二进制之间的手工转换方法,补全了从原理到实践的理解链条。这些技巧并非炫技,在底层优化、嵌入式开发或算法面试中都有实实在在的应用。文章将零散的位运算知识串联成了可直接使用的“工具包”,对于想深入理解计算机底层运算的开发者来说,是一份清晰的备忘录。

IT 2020-02-05 15:06:55 / 累计浏览 1,800

如何获取 MySQL innodb 的 B+tree 的高度

这篇文章深入讲解了如何获取MySQL InnoDB存储引擎中B+树索引的实际高度。作者从树高直接影响查询性能这一核心点出发,指出通常3到4层较为理想,并通过一个包含百万条数据的具体示例,演示了两种实用的获取方法。 首先,文章详细说明了如何通过查询`INNODB_SYS_INDEXES`等系统表获取索引根页的页号,然后结合`innodb_page_size`和`hexdump`工具直接读取`.ibd`数据文件,从中解析出表示树高的`PAGE_LEVEL`字段。这种方法能让你直观地看到主键、`name`、`age`等索引分别处于第几层。 其次,文章还提供了一个不依赖数据库权限的估算思路:基于B+树结构,计算非叶子节点和叶子节点单页可容纳的索引项数量,从而推算出特定数据量下树的大致高度。例如,通过计算得出百万级数据下,`age`索引的高度就达到了3层。 整个过程既有动手操作的命令,也有原理性的估算,让读者不仅能“知其然”,还能“知其所以然”,非常适合希望深入理解InnoDB底层存储机制的开发者参考。

IT 2016-04-05 13:55:49 / 累计浏览 4,120

JVM内存结构

这篇讲的是JVM内存结构的核心组成与关键细节。文章清晰地梳理了Java虚拟机运行时所管理的五大内存区域:堆、方法区、PC寄存器、方法栈和本地方法栈。它不仅解释了每个区域的职责——比如堆用于存放对象实例并分代管理,方法区存储类信息与常量——还深入对比了它们在线程共享与私有、垃圾回收策略以及异常抛出方面的差异。 文章特别指出了Java 8中方法区的重大变迁,即Metaspace替代了永久代,这是一个重要的版本演进知识点。同时,为每个区域都列出了常用的JVM调优参数(如-Xms, -Xmx, -Xss)和对应的OutOfMemoryError或StackOverflowError场景,使得理论立刻能与实践中的故障排查相结合。 对于需要理解内存分配原理、或正面临OOM问题的开发者而言,这篇文章提供了一份结构化的全景图和实用的参数指南,能有效帮助建立起从代码到虚拟机内部运行的直观认知。

IT 2016-04-05 13:52:36 / 累计浏览 3,600

PHP返回内容过长时被nginx截断的解决办法

这篇讲的是作者升级博客环境后,发现后台编辑器界面莫名“消失”——页面内容被截断,功能完全无法使用。他没有急于胡乱配置,而是沉下心分析问题。 排查过程一度很曲折,从复杂的网络抓包入手绕了远路,但最终从 nginx 的错误日志中找到了关键线索:一行 `Permission denied` 错误。原来,当 PHP 返回的响应内容过大时,nginx 会先将其缓存到本地临时文件中,但由于该临时目录(`/var/lib/nginx/tmp/fastcgi/`)的权限不正确,nginx 无法写入文件,从而导致连接中断、内容截断。 解决方案其实很简单:将该目录的权限修改为 775。作者复盘时指出,这次本可快速解决的问题耗费了大量时间,核心教训是:面对异常,应当优先检查系统日志、基于线索推理,而非凭借假设盲目测试。一次具体的踩坑经历,清晰地揭示了 PHP 与 nginx 协作时一个容易被忽略的权限配置细节。

IT 2016-02-20 16:44:17 / 累计浏览 3,220

使用varnish + nginx + lua搭建网站的降级系统

这篇文章讲的是如何用Varnish、Nginx和Lua脚本搭建一个网站降级系统,核心目标是在数据库等后端服务出现致命故障(如500错误)时,能自动切换到展示缓存的静态页面,从而维持最基本的浏览功能。 作者首先明确了降级方案的三个关键点:只提供基础浏览、数据为非登录状态、支持手动与自动触发。整个系统的存储层由Varnish承担,利用其内存缓存来平衡性能与资源。为了保持缓存数据的时效性,作者设计了一个异步更新机制:通过crond定时任务分析Nginx的access日志,提取出热门请求URL,再主动向Varnish发起请求以刷新对应缓存,从而减轻了主站的压力。 降级的触发与切换逻辑主要通过Nginx结合Lua脚本来实现。在Nginx中,通过Lua脚本检查一个共享内存字典中的降级状态标志。一旦进入降级模式,所有PHP动态请求会被重定向,直接从Varnish获取数据返回给用户。自动降级功能则通过监控后端健康状态来实现,例如,当后端监控脚本返回500错误时,Varnish和Nginx都能自动感知并进入降级状态;恢复正常后,系统也会自动切换回来。管理员还可以通过特定的接口进行手动降级操作。 文章详细给出了从Varnish安装、Lua脚本部署到Nginx配置修改的完整步骤,并提供了相关的配置文件和脚本下载。对于需要保障高可用性的Web服务,这套结合了缓存、负载与动态逻辑切换的降级方案,提供了一个清晰且可落地的实践参考。

IT 2016-02-20 16:42:46 / 累计浏览 1,620

linux下redis执行bgsave时,报overcommit_memory错误问题

这篇讲的是 Redis 在内存紧张时执行 bgsave 可能遭遇的 overcommit_memory 报错问题。作者从实际故障现象切入,详细说明了错误提示的含义:当系统内存耗尽,fork 子进程进行后台保存时,若恰有数据变更需要申请内存,就可能因分配失败而终止保存。根本原因在于 Linux 内核的内存分配策略参数 `vm.overcommit_memory` 默认为 0,较为保守。 文章进一步剖析了这个内核参数的三个取值含义,并明确给出解决方案:将该参数设置为 1,允许内存适度超量分配。具体操作提供了三种方法:修改 sysctl.conf 文件、直接运行 sysctl 命令或写入 proc 文件系统,并附上了验证命令。 此外,文章还延伸讨论了与内存管理密切相关的 OOM Killer 机制,解释了 Linux 如何选择进程终止来释放内存,并介绍了如何通过 /proc/meminfo 查看 CommitLimit 和 Committed_As 等关键内存指标。整篇文章逻辑清晰,从问题到原理再到解决和扩展,为处理此类内存配置问题提供了完整思路。

IT 2016-02-16 21:18:29 / 累计浏览 2,840

mysql索引合并:一条sql可以使用多个索引

很多开发者可能还固守着“一条SQL只能使用一个索引”的旧观念,其实MySQL的索引合并特性早已支持更灵活的索引使用。这篇技术文章就详细拆解了这个特性。 文章首先厘清了概念:索引合并并非新事物,它能让MySQL对**同一个表**的多个索引进行范围扫描,并将结果通过并集、交集等方式合并,最终返回数据。要判断查询是否利用了索引合并,只需在`EXPLAIN`结果中看`type`列是否为`index_merge`,以及`key`列是否列出了所有被使用的索引。 作者通过一组精心设计的数据和查询进行演示。例如,当执行`WHERE (key1_part1=4 AND key1_part2=4) OR key2_part1=4`时,`EXPLAIN`显示成功使用了索引合并(`Using sort_union(key1,key2)`)。但另一个结构相似的查询却导致全表扫描。文章指出,这揭示了一个核心事实:**优化器是否选择索引合并,根本上取决于对数据统计的分析和成本估算**,单纯讨论SQL写法是否“能用”索引并不全面。 此外,文章还提到了一个关键的版本差异细节:在MySQL 5.6.7之前的版本中,存在“range优先”原则,可能会抑制索引合并的使用,即使后者理论上更优。这提醒我们,在考虑索引策略时,数据库版本也是不可忽视的因素。

IT 2016-02-06 11:17:20 / 累计浏览 2,940

PHP扩展迁移为兼容PHP7记录

这篇讲的是PHP7扩展开发中,由于内核API的多项变更,在迁移旧版扩展代码时需要处理的兼容性问题。作者详细记录了多个具体函数签名的变化与修正方法。 核心问题在于PHP7对底层进行了重构。很多常用函数如`add_assoc_stringl`、`RETURN_STRINGL`的参数个数减少了;`zval`变量的内存分配方式从堆(使用`ALLOC_INIT_ZVAL`)改为栈(直接声明`zval sarray_l;`)。此外,类型系统也发生了变化,例如布尔类型`IS_BOOL`被拆分为`IS_TRUE`和`IS_FALSE`,相关的宏`Z_BVAL`和`Z_TYPE_PP`也不再存在。 文章还解决了一些编译错误,例如缺少`INT64_MAX`定义时需要手动添加`#include `和相关宏定义;对于字符串,需使用`ZSTR_VAL()`宏将新的`zend_string`类型转换为传统的`char*`;在创建对象时,需要自定义一个`fetch_object`函数来替代旧的`zend_object_store_get_object`。 对于正在迁移或维护PHP扩展的开发者来说,这些来自一线的“踩坑”记录,清晰地指出了代码调整的具体方向,提供了实用的排查和修改参考。

IT 2016-01-27 22:45:22 / 累计浏览 3,600

PHP7扩展开发之hello word

这篇讲的是如何从零开始构建一个PHP7扩展,并让PHP脚本调用其中的函数输出“hello word”。作者以最简功能为例,拆解了扩展开发的核心步骤:从使用 `ext_skel` 工具生成骨架代码,到修改 `config.m4` 配置文件启用扩展,再到编写 C 代码实现 `say` 函数并将其注册到PHP函数表中。 整个过程清晰展示了扩展从代码到加载的完整链条,尤其是 `config.m4` 中注释配置的选择,以及函数注册这一步骤,是理解PHP扩展工作原理的关键。文章最后给出了编译安装和测试验证的完整命令,并附上了源码下载,适合想动手实践PHP底层开发的读者按图索骥。

IT 2016-01-27 22:32:32 / 累计浏览 1,940

非侵入式监控PHP应用性能监控分析

这篇讲的是如何在不触碰业务代码的前提下,对PHP应用进行性能监控。作者从“非侵入”这个实际需求出发,给出了从易到难的两种可行路径。 对于基础的请求耗时监控,最简单的方式是分析Nginx日志。文章清晰解读了日志中两个关键字段的区别:`$request_time`是端到端的总耗时,而`$upstream_response_time`则精准反映后端PHP处理的耗时。只需关注后者,就能快速定位PHP服务本身的性能瓶颈。 如果要深入分析单个请求内部的性能热点,文章详细介绍了使用xhprof扩展的完整方案。它不仅提供了xhprof的安装与配置步骤,其亮点在于展示了一套“无侵入”的部署技巧:通过Nginx的`auto_prepend_file`或php.ini配置,让监控脚本自动加载,实现了对业务代码的零修改。同时,方案还内置了按URL和超时时间智能采样的逻辑,避免了全量监控带来的性能开销。 整篇文章从日志层面的快速概览,到代码执行层面的精准剖析,形成了一套层次分明的监控方法论,为PHP开发者提供了实用的性能分析工具箱。

IT 2015-12-26 20:25:31 / 累计浏览 2,900

白话PHP7扩展开发之创建对象

这篇讲的是在PHP7扩展开发中如何创建一个对象。作者很巧妙地将这个过程比喻为一个孩子从“出生”到“成长”的完整历程,让底层C语言的实现步骤变得直观易懂。 文章将创建对象拆解为几个清晰的阶段:首先定义`zend_class_entry`这个“原型”,相当于“办准生证”;接着用`INIT_CLASS_ENTRY`给对象“取名”并声明方法;然后通过`zend_register_internal_class`完成“上户口”登记。这之后,才是为对象“培养”能力——包括使用`zend_declare_property_*`系列方法定义属性(教授知识),以及通过`zend_function_entry`数组来注册具体的方法(培养行为能力)。 文章的亮点在于,它没有停留在概念阐述,而是紧贴每一个比喻阶段,给出了对应的、可运行的C代码片段。从声明内存属性到定义一个能接收参数的`learn`方法,最终汇聚成一份完整的扩展源代码。文末还附上了PHP端的调用示例和输出结果,让整个流程形成闭环。对于想动手实践的读者,作者直接提供了完整的源代码下载链接。

IT 2015-11-08 22:56:40 / 累计浏览 1,840

[坑]打rpm包时,注意%post和%postun的执行顺序

这篇讲的是RPM打包中一个容易被忽略的坑:升级软件包时,错误的脚本执行顺序会导致配置被意外修改。作者在打包PHP扩展时发现,每次执行`yum update`升级成功后,新扩展在php.ini中的配置项就会被自动注释掉。 问题出在spec文件的`%postun`段。升级时,系统会先执行新包的`%post`段(安装后),再执行旧包的`%postun`段(卸载后)。作者旧包的`%postun`脚本原本是为卸载准备的,会用sed注释掉扩展配置,这就在升级过程中被误触发了。 根本原因在于`%postun`段接收的参数:参数0代表卸载,1代表升级。解决方案很直接——在`%postun`脚本中增加判断,只有当参数为0时才执行注释操作。这样升级时配置就能完好保留。文章还清晰梳理了`%pre`、`%post`、`%preun`、`%postun`在不同场景(安装、升级、卸载)下接收的参数含义,对编写可靠的spec文件很有参考价值。

IT 2015-11-02 22:33:32 / 累计浏览 2,000

Gearmand异步处理就安全了吗?不!

这篇讲的是一个实际生产中遇到的Gearman异步处理陷阱。当团队使用Gearman作为中间件时,发现Gearmand进程会莫名卡住,将PHP请求长时间“Hold”住,即便设置了超时也无效,这对PHP的同步工作模式风险很高。 问题最终被定位到使用Gearman的 `addFunction` 注册任务时,如果指定了 `timeout` 参数,便可能随机复现。通过 `pstack` 工具观察发现,故障时Gearmand的工作线程数量会减少。文章通过分析版本变更与源码指出,从0.33版本起增加的Worker超时处理特性,在底层依赖的libevent 1.4.x(非线程安全)环境下,导致了 `event_base` 对象被跨线程错误操作,从而使得工作线程的事件循环意外退出。 解决方案是从源码层面修正这一问题,例如将发生跨线程调用的 `event_base_set` 方法中的操作对象进行调整。作者最终建议,通过将 `addFunction` 的 `timeout` 参数临时设为0,可以规避此问题。这篇分享对使用Gearman或类似基于libevent组件的团队有很高的参考价值,尤其是在排查无响应卡顿问题时。

IT 2015-09-04 21:29:29 / 累计浏览 3,260

线上PHP问题排查思路与实践

这篇文章来自一位资深工程师在技术大会上的分享,系统地梳理了线上PHP问题的排查方法论。作者从最让用户头疼的“裸奔错误页面”切入,指出工程师需要看到502错误背后PHP-FPM进程失效等深层原因。 其核心思路是一个清晰的四步闭环:先恢复服务(通过摘机、回滚、重启或降级等手段),再保留现场(像警察保护案发现场一样记录日志与系统状态),接着排查问题(结合PHP内核、网络协议等知识和工具分析数据),最后验证结果。作者强调,恢复与保留往往同步进行,例如用gcore保存进程core文件后立即重启。 文章还分享了三个来自不同层面的实战案例,包括用tcpdump排查MySQL TPS飙升、追查导致CPU100%的PHP进程,以及一个由echo引发的系统崩溃。文末附有PPT下载,可供深入研习这套从理论到实践的完整排查框架。

IT 2015-02-26 22:36:24 / 累计浏览 1,600

kvproxy配置文件之集群设置

这篇讲的是kvproxy配置文件中集群设置的具体方法和注意事项。作者开篇就点明了kvproxy集群分为三种:默认集群、读集群和备份集群,后两者都是可选的,各自承担读写分离与数据同步的职责。 文章重点解析了几个核心配置要点:集群名可自定义,但同一集群内的数字id必须唯一,它作为实例标识在更换节点时能确保数据路由的一致性;权重数值并非百分比,而是代表实例在一致性哈希环中的虚拟节点数,数值越大承载的数据通常越多。 为了让概念更具体,作者提供了一个memcached集群配置实例。其中清晰展示了如何通过设置`hosts`、`hosts_backup`和`hosts_read`来分别指定默认、备份和读集群,并详细列出了每个集群成员的IP、端口、ID和权重。通过这个配置,读请求会由`read`集群处理,所有写操作则会同步到`slave`备份集群,从而实现了基本的读写分离和数据备份。整个讲解从概念到实践,条理清晰。

IT 2015-02-26 22:35:56 / 累计浏览 1,520

kvproxy的数据主从复制简介

这篇讲的是如何为Memcached缺少的数据主从同步能力打上补丁。 作者从Memcached用户在多集群部署时面临的数据一致性痛点出发,介绍了kvproxy提供的一个核心功能:通过主从复制实现集群间的数据同步。文章没有停留在概念层面,而是直接拆解了典型场景,比如应对单点故障做热备份,以及跨机房部署时减少网络延迟。 核心方案是让kvproxy代理层支持同步与异步两种复制策略。同步复制保证强一致但增加延迟,异步复制响应快但数据有滞后。文章很细致地指出了如何通过配置文件设置主从集群、指定复制策略前缀,比如让以“+”开头的Key强制走同步通道。 这相当于在缓存层引入了一个可控的数据同步管道,对于既想用Memcached高性能、又需要一定可靠性的团队,提供了一个具体的参考实现路径。

IT 2015-02-06 22:05:02 / 累计浏览 3,520

nginx location在配置中的优先级

这篇讲的是Nginx中`location`指令的优先级规则,一个看似简单实则容易踩坑的配置细节。作者从常见的配置困惑出发,系统对比了四种`location`表达式类型:精确匹配(`=`)、前缀停止匹配(`^~`)、正则匹配(`~`和`~*`)以及普通前缀匹配,并清晰地给出了它们的优先级排序。 文章的核心价值在于明确了“配置顺序影响不大,表达式类型才是关键”这一原则,并用具体的请求路径示例,比如请求`/images/1.gif`为什么命中`^~`而非正则,来直观展示匹配逻辑。理解这套优先级体系,能帮你精准控制请求路由,避免因配置不当导致的意外行为或安全漏洞。 对于需要精细管理反向代理、静态资源或错误页面的Nginx用户来说,搞清楚这套规则能避免很多排查时的“想当然”。

IT 2015-01-20 23:24:52 / 累计浏览 19,680

网络数据包调试利器之wireshark

网络调试中,Wireshark 是不少工程师离不开的“瑞士军刀”。这篇文章没有停留在概念介绍,而是直接带你走进 Wireshark 的实际操作现场。从如何在不同系统上安装开始,重点讲解了软件的核心使用流程。 文章细致拆解了 Wireshark 的主界面,并逐步演示了捕获数据包的关键设置。比如,如何选择网卡接口、理解混杂模式的用途以捕获局域网全部流量,以及如何设置像“port 80”这样的捕获过滤条件来提前筛选 HTTP 流量。 更实用的部分在于捕获后的分析环节。作者详细说明了如何使用显示过滤器,通过构建表达式来精确定位目标数据包。同时,介绍了着色规则和 IO 图表等可视化功能,这些都能帮助用户快速识别网络中的异常流量或性能瓶颈,比如通过 IO 图表直观发现 TCP 重传的低谷点。整篇文章像一份简洁的操作手册,让复杂的工具使用变得清晰可循。

IT 2015-01-19 23:59:44 / 累计浏览 14,740

调试工具之GDB

这是一篇关于调试利器GDB的实用指南。不同于常见的C/C++调试教程,这篇文章特别展示了如何用GDB调试PHP脚本,视角相当独特。 文章从GDB的安装讲起,涵盖了yum、rpm包以及从源码编译这几种常见方式。核心部分围绕一个具体的PHP示例展开,详细演示了启动GDB、设置参数、执行脚本的完整流程。其中亮点是两种高级断点设置方法:可以通过“文件名:行号”精确定位,比如“basic_functions.c:4439”,直接跳到PHP内置函数`sleep`在内核C代码中的实现点;也可以仅用函数名“zif_sleep”来设置断点,这在没有源码行号时尤为方便。文章还介绍了通过`help`命令自助查询GDB的庞大指令集。 作者通过这个实例,清晰地展现了GDB强大的通用调试能力。它不仅是C程序的调试器,更是一个能深入任何用C语言编写(或内嵌C)的运行时环境的强大工具。对于需要调试PHP内核、扩展或性能问题的开发者来说,这篇文章提供了一个极具价值的实践起点。

IT 2015-01-19 23:47:13 / 累计浏览 4,340

几道无聊的php的比较运算题,有兴趣的玩一玩

这篇讲的是PHP中一组有趣的比较运算符测试题。作者通过六个看似简单实则容易猜错的代码片段,考察读者对PHP字符串与数字进行比较时类型转换规则的掌握程度。 文章的核心在于揭示那个关键的转换逻辑:当比较的一方是数字时,字符串会被强制转换为数字后再进行比较。这个转换规则并不直观——它会先过滤掉字符串开头的空格、制表符、换行符等空白字符,然后提取直到首个非数字字符为止的内容作为数值。正是由于这个规则,像 `" \t01ab"` 在与数字`1`比较时,会被视为`1`,结果为`true`;而与字符串`'1'`比较时,则进行纯粹的字符串比较,结果为`false`。 文章没有停留在给出答案,而是进一步引导思考:如果把`==`换成严格相等`===`结果会如何?并直接引用了PHP核心源码 `zend_operators.c` 中的 `compare_function` 函数,印证了这套规则的底层实现。这对于想彻底弄懂PHP类型比较“怪癖”的开发者来说,是一次清晰且深入的梳理。