面试题答案
一键面试1. Redis对象系统不同类型对象编码方式对内存占用及管理策略的影响
- 字符串对象
- 编码方式:有int、embstr和raw三种。当字符串值是整数值且在 -2^63 到 2^63 - 1 之间时,使用int编码,仅需8字节;embstr编码用于长度较短(小于等于39字节)的字符串,它将RedisObject和sds结构体紧凑存储在一块连续内存中,减少内存碎片;长度超过39字节则使用raw编码,此时RedisObject和sds结构体分开存储。
- 对内存占用影响:int编码内存占用最小;embstr编码在短字符串场景下内存利用高效;raw编码对于长字符串虽能存储,但相对embstr会多占用一些内存空间。
- 内存管理策略影响:int编码无需额外字符串管理;embstr编码因紧凑存储,释放内存时一次操作即可;raw编码因结构分离,释放时需要分别处理RedisObject和sds,增加内存管理复杂度。
- 列表对象
- 编码方式:ziplist(压缩列表)和linkedlist(双端链表)。当列表元素数量较少且每个元素长度较短时,使用ziplist编码,它将所有元素紧凑存储在一块连续内存中;元素数量较多或元素长度较长时,使用linkedlist编码。
- 对内存占用影响:ziplist在小列表场景下内存占用低;linkedlist由于每个节点都有前驱后继指针,在大列表时内存占用大。
- 内存管理策略影响:ziplist内存连续,内存管理相对简单,但插入删除元素可能导致内存重新分配;linkedlist内存分散,虽插入删除灵活,但容易产生内存碎片。
- 哈希对象
- 编码方式:ziplist和hashtable。当哈希对象的键值对数量较少且键值字符串长度较短时,使用ziplist编码;键值对数量较多或键值长度较长时,使用hashtable编码,即哈希表结构。
- 对内存占用影响:ziplist在小哈希场景下内存占用少;hashtable在大哈希场景下查找效率高但内存占用相对较大,因为它有哈希表结构的额外开销。
- 内存管理策略影响:ziplist内存连续,管理类似列表的ziplist;hashtable内存分配和释放涉及哈希表操作,当元素动态变化时,可能需要重新哈希,增加内存管理复杂性。
- 集合对象
- 编码方式:intset(整数集合)和hashtable。当集合中所有元素都是整数值且元素数量较少时,使用intset编码,它是紧凑存储整数的有序结构;元素类型多样或数量较多时,使用hashtable编码。
- 对内存占用影响:intset在整数小集合场景下内存占用低;hashtable在复杂集合场景下功能全面但内存占用大。
- 内存管理策略影响:intset内存连续,元素增加删除可能需内存重分配;hashtable内存管理类似哈希对象的hashtable编码。
- 有序集合对象
- 编码方式:ziplist和skiplist(跳跃表)。当有序集合元素数量较少且成员和分值长度较短时,使用ziplist编码;元素数量较多时,使用skiplist编码,它结合了链表和二分查找的优点。
- 对内存占用影响:ziplist在小有序集合场景下内存占用少;skiplist在大有序集合场景下能高效支持范围查询,但内存占用较大,因为每个节点有多个指针。
- 内存管理策略影响:ziplist内存连续,管理与其他ziplist编码对象类似;skiplist内存分散,插入删除操作可能产生内存碎片。
2. 不同业务场景下内存优化及避免内存碎片措施
- 小数据量且数据类型单一的场景
- 原理:优先使用ziplist、intset或embstr编码能减少内存占用。
- 优化措施:在设计数据结构时,尽量控制元素数量和长度,让Redis能自动采用高效编码。例如,对于只包含少量整数的集合,确保元素数量和范围符合intset编码要求。
- 大数据量且读多写少的场景
- 原理:采用hashtable、linkedlist或skiplist编码,虽然内存占用大,但查询效率高。
- 优化措施:提前预估数据量,合理分配内存,减少动态内存分配次数。例如,在创建大哈希表时,根据预估元素数量设置合适的初始容量,减少哈希表扩张时的内存重分配。
- 频繁插入删除数据的场景
- 原理:连续内存编码(如ziplist)在频繁插入删除时可能导致大量内存重分配,应尽量避免。
- 优化措施:可以考虑使用内存分配器特性,如jemalloc的内存池技术,减少内存碎片产生。同时,根据业务规律,批量处理插入删除操作,减少单个操作对内存的频繁影响。
- 内存碎片避免
- 原理:内存碎片主要由频繁的小内存分配释放造成。
- 优化措施:
- 调整数据结构:根据数据特点选择合适编码,减少内存碎片化可能。
- 使用内存分配器参数:如调整jemalloc的chunk大小等参数,优化内存分配策略。
- 定期重启:在业务低峰期重启Redis,让操作系统重新整理内存,消除内存碎片,但此方法需谨慎评估对业务的影响。