作者laechan (小太保)
看板mud
标题[闲聊] 分散式储存
时间Mon Jan 28 15:59:14 2013
做法不只一种,这里只是举例。
比较直觉的想法是,一个 .c 档,其内存的资料透过像是
save_object 函数的处理後,会产生一个 .o 档。
那假设以家族系统为例,经年累月下来,必定会产生很多
的家族,以及很多的家族成员资料,那如果这些资料都储
存在同一个 .o 档里头,就会使得 .o 档过於肥大。
.o 档肥大有时会产生两个问题
一、.o 档的载入 loading 过重
二、.o 档的意外损毁(比方早期大於 198K 时)
那麽,就「家族资料」来说,因为储存的资料主体多半是
玩家ID,则以玩家ID开头做分流就变成直觉的想法:
laechan 这个玩家的家族资料,储存在 group_l.o 里
=> 设计一个 group_l.c,使它在做 save_object 时会
产生 group_l.o
=> 即 laechan 的家族资料是 set 在 group_l.c 里的
则 group_l.c 的档案内容如下
group_l.c
==================================================
mapping group_data=([]);
void create()
{
::create();
seteuid(getuid(this_object()));
if(file_exists(base_name(this_object())+".o"))
restore_object(base_name(this_object()));
}
// 呼叫这个函数时会做储存
int save_room()
{
save_object(base_name(this_object()));
return 1;
}
mapping query_group_data(string names)
{
return group_data[names];
}
.
.
================================================
而其它的 group_X.c 其档案内容也一样(所以可以用继
承来省略)。
然後,设计一个 group.c,读取资料都透过它,底下是
程式片段
group.c
================================================
// 读取某一玩家资料的例子
mapping query_group_data(string names)
{
object group_ob;
// 去找跟该玩家ID字头有关的 group_X.c
if(!catch(group_ob=find_object(__DIR__+"group_"+names[0..0])))
return group_ob->query_group_data(names);
}
// 能读取自然就能 set, del, add, ..
================================================
上面的意思可用底下的图示来表示
query
────→ 判断字头 找到物件
set ┌─────┐ ┌─────┐
Request 方 ────→ │ group.c ├→┤ group_X.c├←存取对映.o档
modify └─────┘ └─────┘
────→
.
.
这样就可以把一个 group.o 档,分拆成 36 个 .o 档
,分别是 group_0.o、group_1.o、...、group_z.o。
底下是一个分拆後的实例:
> ls *.o
1 group_data_0.o 1 group_data_9.o 3 group_data_i.o 5 group_data_r.o
1 group_data_1.o 9 group_data_a.o 4 group_data_j.o 16 group_data_s.o
1 group_data_2.o 7 group_data_b.o 6 group_data_k.o 5 group_data_t.o
1 group_data_3.o 9 group_data_c.o 8 group_data_l.o 1 group_data_u.o
1 group_data_4.o 8 group_data_d.o 7 group_data_m.o 1 group_data_v.o
1 group_data_5.o 5 group_data_e.o 5 group_data_n.o 4 group_data_w.o
1 group_data_6.o 5 group_data_f.o 1 group_data_o.o 1 group_data_x.o
1 group_data_7.o 5 group_data_g.o 6 group_data_p.o 3 group_data_y.o
1 group_data_8.o 6 group_data_h.o 2 group_data_q.o 2 group_data_z.o
分拆的好处是..
一、每一分拆档如上所示,档案内容都很小,处理速度快。
资料不需集中储存於同一个地方。
二、所有的家族资料,会在不同的时间载入。通常是有玩家
去呼叫到时,比方刚 shutdown 完,某家族族长去list
了自己的家族,那 group_X.c的部份只会载入跟它家族
有关的成员ID字头的物件
三、当我们变动了一笔家族资料时,只需去动到跟该笔资料
有关的 group_X.o,其它的 group_X.o档不会动到。
四、分拆後可储存的家族资料可变多,底下是实例:
> list -easy
全部共 574 个族群、3714 个族员.
五、万一发生资料损毁的情况,可避免全面性的资料损坏。
至於家族(或帮派)资料为何不储存在玩家身上,而要另外储
存呢?这是因为这样一来即便家族里头有玩家离线,也不会
妨碍家族资料的存取及变更。当然实际上即便资料是存在玩
家身上,透过一些特殊做法同样能不妨碍家族资料的存取及
变更。只是我不想去实作那些方法。
以上一点心得。
Laechan@Sanc
--
※ 发信站: 批踢踢实业坊(ptt.cc)
※ 编辑: laechan 来自: 210.61.157.53 (01/28 16:07)
1F:推 cibs :如果以家族/帮派资料来看,我觉得直 219.87.142.18 01/28 17:54
2F:→ cibs :接用家族名来存会更方便存取? 219.87.142.18 01/28 20:54
有些是一对一关系,例如族长─族名,所以用族长ID为
keyname、或用族名为 keyname 来存家族是可行的,而
用族长ID的好处是绝不会重覆,族名则可能重覆、中文
、色码、空白等等。
※ 编辑: laechan 来自: 1.165.174.117 (01/29 07:50)