开源项目ets_cache分析

时间:2023-11-12 12:20:50

1 背景

  当在程序中,有大量的数据需要读写,数据库的响应会延迟,甚至阻塞。缓存可以缓解对数据库访问的压力,而且在内存中数据的读写要比读写硬盘上的数据快。

2 目的

  ets_cache是用erlang实现的简单的缓存应用,它的结构简单,但功能强大支持百万级的数据量。其主要是用来存储一些公共访问的数据,这些数据存放在ets表中,借助ets表的高性能对数据进行操作。

3 结构

  3.1 源码目录

下图是ets_cache的源码目录截图:

开源项目ets_cache分析

  include:主要是一些宏定义和引入的一些包。其中定义了默认缓存ets表(ets_cache_data)

  test:主要是测试代码

  src:是源代码文件

  ets_cache_app.erl        
          应用程序启动文件

  ets_cache_sup.erl     
             ets_cache的supervisor行为

  ets_cache.erl     
              
     ets_cache的对外接口

  ets_cache_manager_sup.erl 
  ets_cache_manager的supervisor行为

  ets_cache_manager.erl     
     ets_cache的管理进程,是gen_server行为,维护着每个ets缓存表

  3.2
监控树结构

下图是ets_cache的监控结构:

      开源项目ets_cache分析

从图中我们当我们启动ets_cache应用并创建缓存表,创建的缓存表都被ets_cache_manager_sup的子节点,并对其进行维护。

4 核心

  ets_cache虽然简单,但是有两点值得借鉴:

1.每个ets表专属一个进程。当我们存储新的一类数据时,就可以创建新的进程,创建ets表,单进程维护ets表,保证了ets表的独立性。

2.ets表会定时清理冷数据。ets表的数据应该是访问频率较高的数据,每次访问玩数据都会更新数据的过期时间,而且每个一段时间进程就会对ets表进行一次清理,清理过时的数据,避免ets表的数据过于臃肿。

源码如下:

  handle_info(cleanup, #state{

                          table = Table,

                          clean_interval = CleanInterval

                         } = State) ->

      Now = ets_cache:unixtime(),

      %% error_logger:info_msg("cleanup now ~p~n", [Now]),

      MS = ets:fun2ms(

             fun({_, _, Timeout}) when is_integer(Timeout)->

                     Timeout =< Now

             end),

      ets:select_delete(Table, MS),

      erlang:send_after(CleanInterval, self(), cleanup),

      {noreply, State};

5 总结

  ets_cache虽然设计简单,但是实用。能支持不同类型的数据,创建不同的ets表,而且读写效率高,实用与大量数据的缓存。并可以稍加改动就可以作为数据库和程序之间的缓存。但是,对于数据一致性要求较高的数据要慎用。当所有数据访问频率不高时,清除掉冷数据会产生ets空表。

ets_cache源码地址:https://github.com/roowe/ets_cache

优秀的代码是艺术品,它需要精雕细琢!