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

数据库

共 1099 篇文章

IT 2014-12-04 13:29:25 / 累计浏览 8,094

Redis和Memcached的区别

这篇讲的是Redis和Memcached这两种内存数据库的核心区别。文章从Redis作者的一个经典比较出发,清晰梳理了三者关键差异:首先,Redis支持String、Hash、List等更丰富的数据结构,可以在服务器端直接进行复杂操作,避免了Memcached需要将数据取回客户端修改的额外开销。其次,在内存效率上,若采用hash结构存储,Redis的组合压缩机制可能比Memcached更具优势。最后,性能表现各有特点:处理小数据时Redis的单核性能更优,而在100k以上的大数据场景中,Memcached的多核处理能力则略占上风。 文章随后深入剖析了Redis五种数据类型的实现原理,例如Hash内部如何根据成员数量自动转换存储结构,以及Set如何通过HashMap实现快速去重。这些细节不仅解释了差异背后的技术原因,也揭示了各自的设计考量。 总的来说,如果你的应用需要丰富的数据结构和复杂操作,Redis是更强大的选择;而如果是纯粹的、简单的大规模键值缓存,Memcached在内存利用和特定数据量级下的性能或许更合适。文章为技术选型提供了扎实的对比依据。

本机暂存
IT 2014-12-03 23:58:46 / 累计浏览 2,221

Pora2应用中HBase高并发读写性能优化

这篇讲的是淘宝搜索的Pora2实时分析系统在大量使用HBase进行高并发读写时,所遇到的一系列性能“坑”及优化实践。系统上线后出现处理延迟、集群压力大的问题,排查发现根源主要在于HBase的使用方式。 文章拆解了几个典型案例:一是HBase默认的Periodic Flusher机制引发了过于频繁的flush与compact,通过调整其超时阈值得到了缓解;二是下游消费消息队列时未控制Scan频率,对Region Server造成了无谓压力;三是在超大并发下,过多的客户端连接耗尽了服务端Handler,作者的解决方案是减少进程数、增加线程数以复用连接。 此外,还涉及了因rowkey生成代码bug导致的数据访问热点,以及Bulk Load数据未做Major Compaction引起的读取性能衰减。文章最后总结道,高并发场景下必须合理使用HBase,避免不当操作形成“越慢越压、越压越慢”的恶性循环。这些从实战中沉淀的细节,对同类系统的设计与调优很有参考价值。

本机暂存
IT 2014-12-01 23:38:03 / 累计浏览 2,830

redis超时问题分析

这篇讲的是Redis在实际运维中遇到超时问题的深度排查。作者从dump中心cm8集群的真实故障出发,发现内存充足的情况下依然出现超时,进而深入Redis源码寻找根因。 问题最终定位在三个方面:一是网络闪断,可通过监控带宽排查;二是内存使用,尤其是RDB持久化时fork子进程会触发Linux的写时复制机制,可能导致物理内存不足而发生swap,引发超时。解决方案包括调低swappiness参数、谨慎使用RDB持久化,或改用AOF及读写分离架构。 第三个原因在于Redis单进程串行处理命令的架构。基于epoll的事件驱动模型意味着任何慢命令(如sort、hgetall)都会阻塞后续请求,导致超时。因此,从应用层避免使用慢命令、增加实例分流是关键优化方向。文章结合源码片段,清晰剖析了从网络、内存到内部执行模型的完整故障链路。

本机暂存
IT 2014-11-30 23:48:52 / 累计浏览 2,117

深入剖析 redis 数据结构 redisObject

这篇讲的是Redis核心数据结构redisObject的设计。它只有32位,却极其高效地管理了所有类型的数据对象。 作者从结构体定义出发,揭示了它的精巧布局:type字段明确是字符串、列表还是哈希等类型;encoding字段则决定了底层是用普通字符串、压缩列表还是跳表来存储——同一个类型的数据可以有多种编码,Redis会根据数据规模自动选择最省内存的方案。比如一个小的集合可能用整数集合,变大了就切换为哈希表。 文章还详解了lru字段如何用于内存淘汰,以及refcount引用计数如何管理对象生命周期。最后那个void *ptr指针,才是真正指向数据的地方。 作者特别指出,得益于Redis单线程模型,引用计数的操作无需考虑线程安全,这是与Memcached等多线程系统的重要区别。整个设计将数据与元数据分离,各个字段职责清晰,正是Redis高效与灵活的重要基石。

本机暂存
IT 2014-11-30 23:48:02 / 累计浏览 4,377

深入剖析 redis replication 主从连接

这篇讲的是Redis主从复制机制的底层实现,特别是积压空间(repl_backlog)的设计与作用。 文章从主从架构的概述切入,指出其支持灵活的DAG拓扑以实现数据弱一致性。核心剖析聚焦于“积压空间”这一关键数据结构:它本质上是一个环形缓冲区,用于暂存数据变更记录。作者通过源码追踪,清晰展示了变更记录的写入路径:当命令执行修改了数据后,会经由 `call() -> propagate() -> replicationFeedSlaves()` 链路,最终被同时写入积压空间并分发给所有在线从机。 文章巧妙地解释了这种“双重写入”的设计意图:积压空间是为那些因故障断开连接的从机准备的。这些从机重连后,可以优先从这个环形缓冲区中获取断开期间错过的数据变更,进行高效的增量同步(部分同步),而非每次都进行全量同步。只有当断开时间过长,缓冲区无法覆盖时,才会退化为全同步。 通过对核心数据结构(如 `repl_backlog_size`, `repl_backlog_idx` 等)和关键函数的源码解读,文章深入浅出地揭示了Redis如何在保证实时同步的同时,优雅地处理节点故障恢复的场景,展现了其在工程实现上的细腻考量。

本机暂存
IT 2014-11-30 23:39:36 / 累计浏览 3,926

深入剖析 redis RDB 持久化策略

这篇讲的是 Redis RDB 持久化的底层实现。作者从 RDB 与 AOF 的基本概念切入,随后迅速深入核心,剖析了负责持久化 IO 操作的关键数据结构 `struct rio`。 文章的亮点在于对 `rio` 结构的拆解。它巧妙地通过函数指针(如 `read`、`write`)抽象了读写行为,并用一个 `union` 联合体统一了对内存缓冲区和文件的处理,使得一套代码能同时服务于内存缓存和磁盘文件两种场景,设计上颇具巧思。 接着,作者以 `rdbSave()` 函数为主线,通过代码注释的方式,清晰地勾勒出整个 RDB 写文件的流程:从创建临时文件、初始化 `rio` 结构,到遍历每个数据库、写入操作码和数据项。这个过程不仅解释了数据是如何被序列化到磁盘的,也揭示了 BGSAVE 等后台操作的基础——主进程 `fork` 出子进程来执行这个主逻辑,从而避免阻塞服务。 对于想了解 Redis 如何将内存数据“快照”到硬盘的开发者而言,这篇文章提供了一个从数据结构到执行流程的清晰视角。

本机暂存
IT 2014-11-30 23:22:09 / 累计浏览 7,580

存储基础知识之——硬盘接口简述

这篇文章梳理了从经典的IDE到现代FC、iSCSI等七种主要硬盘接口技术的演进与区别。文章指出,IDE(即并行ATA)因性能和速率的局限,已随SATA(串行ATA)的兴起而退役。SATA目前是消费级市场的主流选择,其接口速率已迭代至第三代。 在企业与高性能领域,文章则对比了SCSI体系及其继任者。SCSI-3虽能提供160MB/s带宽并支持多设备,但其并行架构已发展为串行的SAS接口,后者不仅提供更高的传输速率(如第二代SAS达6Gbps),还通过点对点连接简化了部署,并能兼容SATA设备。更为关键的是,文章详解了如何通过网络化突破本地存储的物理限制:iSCSI技术将SCSI命令封装于TCP/IP协议中,利用现有网络实现远距离、大规模的存储区域网络(SAN);而光纤通道(FC)则以其高速(可达16Gbps)、低延迟和长距离传输(最远10公里)的特性,成为构建高性能企业级SAN的核心选择。 整体来看,这篇文章从接口的物理形态、传输协议到应用场景,系统性地梳理了存储连接技术的关键差异,为理解存储系统架构和选型提供了清晰的脉络。

本机暂存
IT 2014-11-28 23:28:08 / 累计浏览 1,701

HBase在单Column和多Column情况下批量Put的性能对比分析

这篇讲的是HBase在不同数据模型下批量写入的性能差异。作者从一个实际现象出发:将数据存储在单个列(单列模式)与拆分成多个列(多列模式)时,批量Put的吞吐量存在巨大差距。测试数据显示,单列模式的TPS是多列模式的7倍以上,RPC调用次数也相差9倍。 文章核心是从HBase的KeyValue内存模型入手,解释了这种差距的根本原因。在多列模式下,每一列都会携带大约50-60字节的元数据开销(如行键、列族、时间戳等),导致一行数据在客户端缓冲区中占用的内存远大于单列模式,进而触发更频繁的RPC提交,拉低了整体吞吐。 作者通过代码计算put.heapSize()和KeyValue对象大小,验证了这一理论估算与测试结果高度吻合。文章最终给出实用建议:如果业务模型必须使用多列存储,在批量写入场景下,可以考虑适当调大客户端的write buffer,以缓解性能下降。

本机暂存
IT 2014-11-28 22:13:57 / 累计浏览 2,960

分布式全文检索系统SolrCloud简介

这篇文章讲解的是面向大规模搜索场景的分布式方案——SolrCloud。作者从Solr的部署演进讲起,指出单机和传统Master-Slaver方式的局限性,而SolrCloud基于Zookeeper实现了真正的分布式协同。 摘要重点突出了它的核心特性:集中式配置管理,让集群配置变更全局生效;自动容错与分片,单个节点故障不影响服务,并能自动重建副本;近实时搜索支持秒级数据可检索;查询时自动负载均衡,可通过横向扩展缓解压力。文章也提到了索引存储于HDFS、通过MapReduce批量建索引等高阶能力,以及强大的RESTful API和管理界面。 最后,文章对Collection、Shard、Replica等核心概念进行了阐释,帮助读者建立清晰模型。整体来看,这是一篇对SolrCloud分布式架构、关键技术点和适用场景的扎实入门介绍。

本机暂存
IT 2014-11-27 12:58:20 / 累计浏览 1,637

使用HBase EndPoint(coprocessor)进行计算

当面对千万、亿级数据量时,对HBase表进行全表扫描来统计行数或分组聚合,会带来巨大的网络与RPC开销。这篇技术分享给出了一个优雅的解法:使用HBase的Endpoint协处理器。 作者的核心思路是,将计算逻辑直接部署到数据所在的RegionServer上执行,只将聚合后的结果返回客户端。这就好比把计算任务“下发”到每个数据分区,避免了海量原始数据的网络传输。文章将这个过程比作一个精简高效的、运行在RegionServer上的MapReduce。 具体实现分为三步:首先定义一个继承自CoprocessorProtocol的计数接口;然后在服务端实现该接口,在Region内完成数据扫描与计数;最后在客户端通过HBase API发起远程调用,并汇总各个Region的统计结果。文章不仅给出了清晰的代码示例,还详细说明了如何通过配置文件或Shell命令来部署这个协处理器。 通过行数统计这个简单例子,文章展示了Endpoint协处理器如何为HBase添加灵活的计算能力,使其成为高效应对大规模数据聚合挑战的利器。

本机暂存
IT 2014-11-27 12:56:39 / 累计浏览 3,190

构建高可用和弹性伸缩的KV存储系统

KV存储系统在现代高并发应用中扮演着关键角色,但经典的Memcached和Redis在运维中常面临容灾困难、数据复制效率低以及在线扩容复杂等挑战。这篇内容从这些实际痛点出发,深入分析了Redis在持久化、主从复制和集群扩展方面的局限,比如主机宕机可能导致数据丢失、全量复制影响性能,以及扩容需要人工干预等。 针对这些问题,文章提出了一套新的分布式架构设计。该系统由路由、存储、管理和搬迁四类节点组成,通过一致性哈希与虚拟节点实现数据均匀分布,并利用心跳检测和自动切换机制来保障高可用。新方案不仅兼容现有协议,还实现了自动容错恢复、负载均衡和弹性伸缩,试图在保证内存级性能的同时,让运维变得更加智能和可靠。 整体来看,这不仅是对现有技术的梳理,更提供了一个从架构层面系统化解决KV存储可用性与扩展性难题的思路,对从事基础架构或缓存设计的工程师有直接的参考价值。

本机暂存
IT 2014-11-26 23:08:43 / 累计浏览 2,665

Windows主机的性能监控

在运维实践中,清晰了解承载业务的Windows主机状态,是保障上层应用(如SQL Server)稳定运行的基础。这篇文章系统性地梳理了如何利用PowerShell和perfmon两大工具,对Windows主机进行全面的性能监控。 作者从“工欲善其事,必先利其器”出发,详细介绍了如何使用PowerShell的`Get-Counter`和`Get-WmiObject`命令,来获取和计算各类性能计数器数据。文章的核心价值在于,它没有停留在列举指标,而是深入剖析了CPU、存储、内存、网络这四个关键维度的核心Metrics。 对于每个指标,例如CPU使用率、磁盘响应时间、内存页交换等,都提供了具体的PowerShell获取命令、含义解释以及计算逻辑。更进一步,文章还探讨了监控实践中可能遇到的陷阱,比如采集粒度不足导致问题被掩盖,并讨论了在大规模集群下,采用Push(Agent主动上报)或Pull(中心节点拉取)模式对监控数据精确度和系统开销的影响。 整体而言,这不仅是一份监控指标速查手册,更是一份从工具使用到指标解读,再到采集策略思考的实践指南。

本机暂存
IT 2014-11-26 22:51:51 / 累计浏览 2,772

深入剖析 redis 数据结构 ziplist

这篇讲的是 Redis 中为了极致节省内存而设计的压缩链表 ziplist 的实现细节。作者从 Redis 的 list 结构有两种底层实现(普通双链表和 ziplist)切入,重点剖析了后者。 ziplist 的核心巧妙之处在于,它用一段连续的内存空间模拟了双向链表的功能,从而省去了每个节点额外的前驱和后驱指针开销(每个指针8字节)。文章详细拆解了 ziplist 的整体格式以及每个 entry 的 TLV(类型-长度-值)结构,特别是通过 `prelen` 字段记录前一项的长度来实现反向遍历,通过精心设计的 `encoding` 字段对不同长度的字符串和整数进行紧凑编码。 通过分析 `ziplistFind()` 函数的源码,文章展示了 ziplist 如何进行数据查找与比较。最后,文章点明了 ziplist 在 Redis 中的实际应用场景(如 Hash 结构在数据量小时的底层存储),并解释了它的性能优势:紧凑的线性内存布局不仅节省空间,还可能更好地利用 CPU 缓存,使得在数据量较小时,其查找性能甚至可以媲美哈希表。

本机暂存
IT 2014-11-25 23:00:40 / 累计浏览 2,221

Oracle数据库升级迁移、SPA及统计信息

作者从一次真实的升级迁移讲起:某省级电信运营商将核心CRM系统的Oracle数据库,从IBM小型机上的10g RAC迁移至x86+VMware平台的11g RAC,成本降至十分之一。这引出了一个关键的后续问题:新系统上线后,应采用何种统计信息收集策略? 文章对比了两种方案:迁移旧库统计信息或在新库自动收集。作者团队最终选择了后者,原因是11gR2的自动收集机制已相对完善,且能为后续运维降低风险。但如何确保这一策略在上线时就安全可用?答案在于利用SPA(SQL性能分析器)。 团队使用了生产库三个时段及一个月AWR中的全部SQL,在新库上跑SPA测试。在测试前,先用`dbms_stats.gather_database_stats(options=>'gather auto')`执行一次增量收集。然而,直接这样做会导致新库的直方图信息严重缺失,因为自动收集依赖`col_usage$`表,而新库此表为空。解决方法是在SPA测试过程中,通过执行足够多的SQL来“喂饱”`col_usage$`,让系统“记住”哪些列需要被关注。最终,基于SPA的测试结果,用数十个SQL Profile固化了风险计划,保障了系统平稳上线。 这篇分享的价值在于,它清晰地展示了在大型跨版本迁移中,如何通过组合使用SPA和自动统计信息收集策略,来系统性规避性能风险,而不仅仅是凭经验手工调优。

本机暂存
IT 2014-11-24 23:36:20 / 累计浏览 7,242

给 Kibana 实现百分比统计图表

这篇讲的是作者如何在一个下班前的冲动下,给 Kibana 3.1 手动添加 percentile 图表类型,以支持 Elasticsearch 的百分比统计功能,结果却挖出了一连串坑。 作者的初衷很直接:利用 Elasticsearch 1.1 新增的 percentile aggregation 来做更细致的日志区间分布分析,并认为这能作为学习 AngularJS 的练手项目。但实际动手后发现,计划中的“简单更新 JS 库”完全行不通。最大的坑在于 Kibana 3.1 内置的 elasticjs 库版本号标注混乱(写着 v1.1.1 实则是旧版),而新版的 elasticsearch.js 代码结构又彻底重构,不再适配 Kibana 使用的 requirejs 模块化方案。 在探索了替换整个库的复杂路径后,作者找到了一个更直接的解决方案:既然 Elasticsearch 是 RESTful 接口,那就绕过这些客户端库,直接用 AngularJS 的 $http 服务手动构建请求。不过,这个过程也撞上了 Elasticsearch 本身的限制——aggregation_name 字段不支持中文字符,迫使作者需要调整 Kibana 原有的别名生成逻辑。 最终,作者用这个看似“不太优雅”但确实有效的方法实现了功能。文章记录的这些具体踩坑细节,比如库版本号陷阱、模块加载冲突以及数据字段命名限制,对同样想在 Kibana 上做定制开发的人来说,都是很实际的参考。

本机暂存
IT 2014-11-22 23:10:09 / 累计浏览 1,963

深入剖析 redis 数据结构 dict

这篇深度技术文章从源码层面拆解了 Redis 的核心数据结构——字典(dict)。作者首先指明,Redis 的每个数据库(db)本质上由两个哈希表(dictht)构成,真正存储键值对的是这两个表。文章重点剖析了 Redis 哈希表设计最精妙的部分:为何需要两个哈希表,以及如何利用它们实现 **渐进式 rehash(重哈希)**,从而在服务不中断的前提下完成表的扩容。 具体实现上,当触发扩展时,Redis 会为第二个哈希表分配新空间,并在后续的每次增删改查操作中,分批次地将数据从旧表迁移至新表。文章结合源码(`dictRehash` 函数)展示了这一“逐步搬家”的过程,并点明了其背后的设计考量:在服务器空闲时,定时任务会推进 rehash;在高负载时,操作本身的开销也会承担部分 rehash 工作,以此平衡性能。 此外,文章还分析了这种设计带来的“副作用”:由于查找操作需同时兼顾两个表,加上写操作本身包含多次查找,导致 Redis 在执行 SET 等写命令时效率并不高,这也从底层解释了其“重读轻写”的特性。最后,文章简要介绍了在涉及持久化(如 RDB/AOF)遍历哈希表时,也需要正确处理这两个表的过渡状态。全文逻辑清晰,从结构定义到核心算法,再到其对上层行为的影响,层层递进,非常适合想深入理解 Redis 高性能背后实现细节的开发者。

本机暂存
IT 2014-11-21 23:22:05 / 累计浏览 3,516

深入剖析 redis 数据结构 skiplist

这篇讲的是Redis有序集合ZSet背后的灵魂——跳表(skiplist)。作者从Redis源码出发,一层层拆解了这个经典数据结构。 文章首先点明跳表的核心价值:它用空间换时间,通过预先在有序链表上建立多级“索引”,实现了类似二分查找的高效查询。Redis正是利用它来支撑ZSet的排序和范围查询操作。 更精彩的部分在于对Redis具体实现的剖析。文章不仅给出了核心结构体`zskiplistNode`和`zskiplist`的定义,还深入到了插入和删除操作的算法细节。比如,插入时如何随机生成新节点的层数,以及如何通过`update`数组和`rank`数组来精确地调整每一层的前驱指针和`span`值。`span`这个设计很巧妙,它记录了两个节点之间跳过了多少元素,是实现按排名查询的关键。 作者没有停留在理论,而是结合代码注释,把查找、插入、删除的完整流程都梳理了一遍。从概念到实现,从宏观到微观,清晰地展现了Redis是如何用这套机制来保障其高性能的。对于想理解Redis内部原理的开发者来说,这篇源码分析对数据结构的剖析很到位。

本机暂存
IT 2014-11-20 23:53:27 / 累计浏览 1,645

深入剖析 redis 数据结构 intset

这篇讲的是 Redis 中整数集合 intset 的底层实现细节。当 set 中所有元素都是整数时,Redis 会优先使用 intset 这种紧凑的数据结构,只有遇到非整数时才升级为更通用的 dict。作者深入源码,拆解了 intset 如何做到高效存储与操作。 intset 本质是一个有序、不重复的整型数组。它的精巧之处在于通过 `encoding` 字段动态记录当前数组中整数的位宽(16、32或64位),从而在保证功能的前提下极致节省内存。查找操作直接利用数组的有序特性,采用经典的二分查找算法,效率很高。 文章的重点和亮点在于对插入过程的剖析。当插入的新整数超出了当前编码范围(例如向一个全是 16 位整数的集合插入一个 32 位整数),intset 不会简单拒绝,而是会触发一次“编码升级”(`intsetUpgradeAndAdd`)。升级过程非常巧妙:它会重新分配内存,将现有所有元素转换为新编码,并逆序移动元素以避免数据覆盖。由于新整数必然是最大或最小值,最终将其放置在数组头部或尾部即可。这种按需升级的设计,平衡了内存效率与灵活性。 整体来看,intset 是一个为特定场景高度优化的微型数据结构。它通过有序数组+二分查找+动态编码升级,为 Redis 提供了一个内存极其友好且高效的整数集合实现,是理解 Redis 空间优化哲学的一个绝佳范例。

本机暂存
IT 2014-11-20 23:34:32 / 累计浏览 2,243

TokuMX使用小计

作者面对一个实际痛点:MongoDB存储运行日志时,三个月数据就占用近100G磁盘,急需更高效的存储方案。他最终选择了TokuMX——一款声称能节省90%空间并大幅提升性能的MongoDB分支。 迁移过程非常直接,使用标准工具导出再导入即可。实际效果令人惊讶:原先102G的数据迁移到TokuMX后,仅占用2.2G,导入速度提升至少10倍,查询性能保持稳定。文章分析了TokuMX背后的关键技术:一是存储层的高效压缩,二是用分形树索引替代传统的B树,通过在节点内设置缓冲区并批量写入,来大幅提升写入效率。 除了分享这次迁移实践与技术原理,作者还附上了官方介绍文档、第三方性能评测等参考资料,为想深入了解或尝试的读者提供了入口。

本机暂存
IT 2014-11-20 23:33:34 / 累计浏览 1,835

翻译文档:TokuMX的分形索引是什么?

这篇讲的是TokuMX如何通过一种叫“分形树索引”的数据结构,颠覆了数据库性能优化的传统认知。 作者从数据库领域一条看似不可动摇的规则说起:要想写入快,索引必须能装进内存。因为传统B树索引在写数据时,几乎每次操作都需要访问磁盘上的叶子节点,一旦内存装不下,频繁的I/O就会让性能急剧下降。 而分形树索引的解法很巧妙:它在B树内部节点里加入了缓冲区。写操作先快速存入根节点的缓冲区,满了再像瀑布一样向下“刷”到子节点的缓冲区。这样一来,许多小写入就被合并成一次磁盘I/O,效率大幅提升。 文章通过对比清晰地指出:关键差异就在于这个缓冲设计,它让分形树索引在索引工作集远超内存时,依然能保持出色的写入性能。不过作者也补充,如果内存足够大,B树其实也很快,分形树的优势主要体现在应对重度I/O的场景。

本机暂存