`
m635674608
  • 浏览: 5061869 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

深入redis内部--内存管理

 
阅读更多

1. Redis内存管理通过在zmalloc.h和zmalloc.c中重写c语言对内存的管理来完成的。

redis内存管理 c内存管理 原型 作用
zmalloc malloc void *malloc(unsigned int num_bytes); 分配一块指定大小的内存区域,并返回指向该区域头部的指针,分配失败则返回NULL
zcalloc calloc void *calloc(unsigned n, unsigned size); 在内存的动态存储区中分配n个长度为size的连续空间,函数返回一个指向分配起始地址的指针;如果分配不成功,返回NULL。
zrealloc realloc oid *realloc(void *mem_address, unsigned int newsize); 先判断当前的 指针是否有足够的连续空间,如果有,扩大mem_address指向的地址,并且将mem_address返回,如果空间不够,先按照newsize指定 的大小分配空间,将原有数据从头到尾拷贝到新分配的内存区域,而后释放原来mem_address所指内存区域(注意:原来指针是自动释放,不需要使用 free),同时返回新分配的内存区域的首地址。即重新分配存储器块的地址。
zfree free void free(void *ptr)  释放ptr指向的存储空间。被释放的空间通常被送入可用存储区池,以后可在调用malloc、realloc以及calloc函数来再分配。

 

封装就是为了屏蔽底层平台的差异,同时方便自己实现相关的统计函数。

定义平台之间的差异,主要是tcmalloc(google)、jemalloc(facebook)、苹果平台。

具体来说就是:

  • 若系统中存在Google的TC_MALLOC库,则使用tc_malloc一族函数代替原本的malloc一族函数。
  • 若系统中存在facebook的JE_MALLOC库,则使用je_malloc一族函数替换原来的malloc一族函数。
  • 若当前系统是Mac系统或者其它系统,则使用<malloc/malloc.h>中的内存分配函数。
复制代码
/* Double expansion needed for stringification of macro values. */
#define __xstr(s) __str(s)
#define __str(s) #s

#if defined(USE_TCMALLOC)
#define ZMALLOC_LIB ("tcmalloc-" __xstr(TC_VERSION_MAJOR) "." __xstr(TC_VERSION_MINOR))
#include <google/tcmalloc.h>
#if (TC_VERSION_MAJOR == 1 && TC_VERSION_MINOR >= 6) || (TC_VERSION_MAJOR > 1)
#define HAVE_MALLOC_SIZE 1
#define zmalloc_size(p) tc_malloc_size(p)
#else
#error "Newer version of tcmalloc required"
#endif

#elif defined(USE_JEMALLOC)
#define ZMALLOC_LIB ("jemalloc-" __xstr(JEMALLOC_VERSION_MAJOR) "." __xstr(JEMALLOC_VERSION_MINOR) "." __xstr(JEMALLOC_VERSION_BUGFIX))
#include <jemalloc/jemalloc.h>
#if (JEMALLOC_VERSION_MAJOR == 2 && JEMALLOC_VERSION_MINOR >= 1) || (JEMALLOC_VERSION_MAJOR > 2)
#define HAVE_MALLOC_SIZE 1
#define zmalloc_size(p) je_malloc_usable_size(p)
#else
#error "Newer version of jemalloc required"
#endif

#elif defined(__APPLE__)
#include <malloc/malloc.h>
#define HAVE_MALLOC_SIZE 1
#define zmalloc_size(p) malloc_size(p)
#endif
复制代码

 

具体如下:

复制代码
/* Explicitly override malloc/free etc when using tcmalloc. */
#if defined(USE_TCMALLOC)
#define malloc(size) tc_malloc(size)
#define calloc(count,size) tc_calloc(count,size)
#define realloc(ptr,size) tc_realloc(ptr,size)
#define free(ptr) tc_free(ptr)
#elif defined(USE_JEMALLOC)
#define malloc(size) je_malloc(size)
#define calloc(count,size) je_calloc(count,size)
#define realloc(ptr,size) je_realloc(ptr,size)
#define free(ptr) je_free(ptr)
#endif

#ifdef HAVE_ATOMIC
#define update_zmalloc_stat_add(__n) __sync_add_and_fetch(&used_memory, (__n))
#define update_zmalloc_stat_sub(__n) __sync_sub_and_fetch(&used_memory, (__n))
#else
#define update_zmalloc_stat_add(__n) do { \
    pthread_mutex_lock(&used_memory_mutex); \
    used_memory += (__n); \
    pthread_mutex_unlock(&used_memory_mutex); \
} while(0)

#define update_zmalloc_stat_sub(__n) do { \
    pthread_mutex_lock(&used_memory_mutex); \
    used_memory -= (__n); \
    pthread_mutex_unlock(&used_memory_mutex); \
} while(0)

#endif
复制代码

说明:

Both libraries try to de-contention memory acquire by having threads pick the memory from different caches, but they have different strategies:

  • jemalloc (used by Facebook) maintains a cache per thread
  • tcmalloc (from Google) maintains a pool of caches, and threads develop a "natural" affinity for a cache, but may change

This led, once again if I remember correctly, to an important difference in term of thread management.

  • jemalloc is faster if threads are static, for example using pools
  • tcmalloc is faster when threads are created/destructed

1.1 zmalloc实现      

复制代码
void *zmalloc(size_t size) {
    void *ptr = malloc(size+PREFIX_SIZE);

    if (!ptr) zmalloc_oom_handler(size); //如果没有发生内存溢出,则使用的分配方式static void (*zmalloc_oom_handler)(size_t) = zmalloc_default_oom;
#ifdef HAVE_MALLOC_SIZE                  //HAVE_MALLOC_SIZE用来确定系统是否有函数malloc_size,定义如上所示。
    update_zmalloc_stat_alloc(zmalloc_size(ptr)); //更新分配内存的状态。处理线程安全和线程不安全
    return ptr;
#else
    *((size_t*)ptr) = size;
    update_zmalloc_stat_alloc(size+PREFIX_SIZE);
    return (char*)ptr+PREFIX_SIZE;
#endif
}
复制代码

 

复制代码
#define update_zmalloc_stat_alloc(__n) do { \
    size_t _n = (__n); \
    if (_n&(sizeof(long)-1)) _n += sizeof(long)-(_n&(sizeof(long)-1)); \
    if (zmalloc_thread_safe) { \
        update_zmalloc_stat_add(_n); \
    } else { \
        used_memory += _n; \
    } \
} while(0)

#ifdef HAVE_ATOMIC
#define update_zmalloc_stat_add(__n) __sync_add_and_fetch(&used_memory, (__n))
#define update_zmalloc_stat_sub(__n) __sync_sub_and_fetch(&used_memory, (__n))
#else
#define update_zmalloc_stat_add(__n) do { \
    pthread_mutex_lock(&used_memory_mutex); \
    used_memory += (__n); \
    pthread_mutex_unlock(&used_memory_mutex); \
} while(0)

#define update_zmalloc_stat_sub(__n) do { \
    pthread_mutex_lock(&used_memory_mutex); \
    used_memory -= (__n); \
    pthread_mutex_unlock(&used_memory_mutex); \
} while(0)

#endif
复制代码

说明

int pthread_mutex_lock(pthread_mutex_t *mutex);

当pthread_mutex_lock()返回时,该互斥锁已被锁定。线程调用该函数让互斥锁上锁,如果该互斥锁已被另一个线程锁定和拥有,则调用该线程将阻塞,直到该互斥锁变为可用为止。

int pthread_mutex_unlock(pthread_mutex_t *mutex);和上面的函数为一对。

其它函数的实现类似。

 

http://www.cnblogs.com/davidwang456/p/3504563.html

分享到:
评论

相关推荐

    tomcat-redis-session-manager源码

    首先,我们来看`Tomcat-Redis-Session-Manager`的核心功能:它将Tomcat默认的内存会话管理替换为基于Redis的分布式会话管理。这主要涉及两个关键组件:`RedisSessionManager`和`RedisSessionHandlerWrapper`。 `...

    -redis-session-manager-master.zip

    通过阅读源码,我们可以深入理解其内部实现机制,比如如何序列化和反序列化session对象,以及如何处理并发和超时问题。而README通常会提供详细的安装和使用指南,包括环境需求、配置参数的解释以及可能出现的问题及...

    redis-3.0-vs2017.zip

    通过这个环境,开发者可以深入理解Redis的内部工作原理,对源码进行修改或扩展,以满足特定需求。 压缩包内的文件可能包括以下内容: 1. `src`目录:包含Redis服务器的源代码文件,如`redis-server.exe`用于启动...

    Redis--参考资料即总结

    Redis,全称Remote Dictionary Server,是一款...总的来说,"Redis--参考资料即总结"这个主题将带领读者深入Redis的世界,从基本概念到高级特性,从源码剖析到工具使用,全面掌握这个强大的键值存储系统的方方面面。

    Redis-x64-3.zip

    6. **内存管理优化**:Redis 3.x继续优化内存管理,包括更好的内存压缩和更智能的内存回收策略,以降低内存占用。 7. **性能提升**:通过对内部数据结构的调整和算法优化,3.x在处理大量请求时性能得到显著提升。 ...

    redis-3.0-annotated-unstable.zip

    8. **内存管理**:Redis 使用自己定制的内存管理机制,通过 LRU(Least Recently Used)策略进行内存淘汰,保证在内存限制下尽可能高效地使用内存。 9. **集群**:Redis 3.0 引入了 Redis Cluster,提供了一种分布式...

    redis-7.0.0-x64-windows.rar

    首先,从源码编译意味着你可以深入了解其内部工作原理,同时可以根据需求进行定制化修改。对于开发者来说,这是一个非常宝贵的学习和调试资源。其次,新版本可能包含性能提升,如更快的数据读写速度,更优化的内存...

    Redis-win-3.2.100

    5. **源代码**:包含的`redis-win-3.2.100.zip`文件提供了Redis的源代码,对于开发者而言,可以查看源码、学习内部实现或进行二次开发。如果需要编译源码,需要安装Visual Studio等开发环境,并遵循官方的编译指南。...

    redis-py-cluster-1.3.4.tar.gz

    Redis是世界上最受欢迎的内存数据存储系统之一,常用于构建高性能、低延迟的数据缓存和数据库。Redis Python 客户端,即redis-py,是Python社区广泛使用的与Redis服务器交互的库。`redis-py-cluster`是这个客户端的...

    redis-3.2.11.tar.gz 以及redis-3.3.5.gem

    Redis-3.2.11.tar.gz 文件是Redis 3.2.11版本的源代码包,通过这个文件,我们可以了解Redis的内部实现并进行自定义编译安装。 首先,安装Redis通常涉及以下步骤: 1. **解压源码**:使用`tar -zxvf redis-3.2.11....

    redis-7.0.2官方下载版本

    - Redis 7.0.2可能通过优化内部算法和数据结构,提升了读写速度,减少了内存占用,进一步增强了其作为高性能缓存系统的地位。 - 并行命令执行也可能得到了改善,允许在单个连接上并行处理多个命令,提高了吞吐量。...

    Redis3.2--64位

    本文将深入探讨 Redis 3.2 的关键特性,以及64位系统下运行 Redis 的优势。 首先,Redis 3.2 引入了多种新功能和改进,其中最为显著的是LUA脚本的原子执行。在之前版本中,虽然LUA脚本可以在服务器端运行,但执行...

    redis-desktop-manager-2020.1.0

    这个2020.1.0版本的特色在于它是通过源码打包,这意味着用户可以深入了解其内部工作原理,并且没有使用上的任何限制,为开发人员和运维人员提供了极大的便利。 这款软件的主要功能包括: 1. **连接管理**:用户...

    Redis 5.0.9 + Another-Redis-Desktop-Manager

    本文将深入探讨 Redis 5.0.9 和 Another-Redis-Desktop-Manager 1.3.6 的相关知识。 首先,我们关注的是 Redis-x64-5.0.9.msi,这是一个针对Windows操作系统的64位版本的Redis安装包。Redis 5.0.9 是 Redis 的一个...

    redis3.2+jedis2.8.jar+common-pool2.jar+common-pool2-source.rar

    Common-Pool2-source.rar则包含了Common-Pool2的源代码,开发者可以通过阅读源码来了解其内部工作原理,进行更深入的定制或优化。 在使用Redis3.2+jedis2.8.jar进行Java开发时,首先需要在项目中引入Jedis库,配置...

    redis-6.2.3-win64.zip

    在本文中,我们将深入探讨Redis的基础概念、主要功能、6.2.3版本的新特性以及在Windows上的安装和使用方法。 1. Redis基础: Redis是一个开源的、基于内存的数据结构存储系统,支持多种数据类型,如字符串、哈希、...

    redis-4.0.11已编译压缩包

    4. **性能优化**:Redis 4.0对内部结构进行了优化,提高了读写速度和内存效率。此外,还改进了命令执行的并发性,尤其是在高并发场景下。 5. **AOF重写策略**:追加式日志(Append Only File,AOF)的重写策略也...

    redis-2.8.3.tar.gz

    Redis是世界上最受欢迎的开源内存数据结构存储系统,它作为一个键值数据库被广泛应用于缓存、消息中间件、计数器等...通过编译和安装,开发者可以深入了解其内部工作原理,同时享受到Redis提供的高效内存数据处理能力。

    redis7.0的tar.gz压缩包

    9. **性能提升**:通过内部算法优化和内存管理改进,Redis 7.0在读写速度、内存效率等方面都有所提升。 安装Redis 7.0通常涉及以下步骤: 1. 下载源码包,例如`redis-7.0.4.tar.gz`。 2. 解压压缩包:`tar -zxvf ...

    redis-4.0.11安装包

    Redis是世界上最受欢迎的内存数据存储系统之一,尤其在高性能、低延迟的数据访问需求场景中表现卓越。这个"redis-4.0.11"安装包是Redis的一个特定版本,适用于那些需要稳定性和兼容性的项目。在本文中,我们将深入...

Global site tag (gtag.js) - Google Analytics