1 背景
当在程序中,有大量的数据需要读写,数据库的响应会延迟,甚至阻塞。缓存可以缓解对数据库访问的压力,而且在内存中数据的读写要比读写硬盘上的数据快。
2 目的
ets_cache是用erlang实现的简单的缓存应用,它的结构简单,但功能强大支持百万级的数据量。其主要是用来存储一些公共访问的数据,这些数据存放在ets表中,借助ets表的高性能对数据进行操作。
3 结构
3.1 源码目录
下图是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_manager_sup的子节点,并对其进行维护。
4 核心
ets_cache虽然简单,但是有两点值得借鉴:
1.每个ets表专属一个进程。当我们存储新的一类数据时,就可以创建新的进程,创建ets表,单进程维护ets表,保证了ets表的独立性。
2.ets表会定时清理冷数据。ets表的数据应该是访问频率较高的数据,每次访问玩数据都会更新数据的过期时间,而且每个一段时间进程就会对ets表进行一次清理,清理过时的数据,避免ets表的数据过于臃肿。
源码如下:
1 handle_info(cleanup, #state{ 2 3 table = Table, 4 5 clean_interval = CleanInterval 6 7 } = State) -> 8 9 Now = ets_cache:unixtime(), 10 11 %% error_logger:info_msg("cleanup now ~p~n", [Now]), 12 13 MS = ets:fun2ms( 14 15 fun({_, _, Timeout}) when is_integer(Timeout)-> 16 17 Timeout =< Now 18 19 end), 20 21 ets:select_delete(Table, MS), 22 23 erlang:send_after(CleanInterval, self(), cleanup), 24 25 {noreply, State};
5 总结
ets_cache虽然设计简单,但是实用。能支持不同类型的数据,创建不同的ets表,而且读写效率高,实用与大量数据的缓存。并可以稍加改动就可以作为数据库和程序之间的缓存。但是,对于数据一致性要求较高的数据要慎用。当所有数据访问频率不高时,清除掉冷数据会产生ets空表。
ets_cache源码地址:https://github.com/roowe/ets_cache
优秀的代码是艺术品,它需要精雕细琢!