自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

淺談網(wǎng)絡(luò)游戲內(nèi)存數(shù)據(jù)庫的設(shè)計(jì)(1)

運(yùn)維 數(shù)據(jù)庫運(yùn)維 其他數(shù)據(jù)庫
網(wǎng)絡(luò)游戲的數(shù)據(jù)變動(dòng)比較頻繁,如果每次數(shù)據(jù)變動(dòng)都刷往后端數(shù)據(jù)庫,會(huì)導(dǎo)致數(shù)據(jù)庫不負(fù)重荷。在游戲邏輯和數(shù)據(jù)庫間提供一層緩沖服務(wù),有利于減輕這重壓力.

首先,網(wǎng)絡(luò)游戲的數(shù)據(jù)在數(shù)據(jù)庫中是以表的形式保存的,每個(gè)玩家的數(shù)據(jù)占用其中的一行或幾行.以玩家基本屬性為例:

基本表: chainfo

表結(jié)構(gòu):chaid,chaname,hp,mp,maxhp,maxmp ...

為此,內(nèi)存數(shù)據(jù)庫將建立針對(duì)行集和行數(shù)據(jù)的抽象。為了提高查詢的效率,在內(nèi)存中建立一個(gè)大的hash-table,hash-table中只支持兩種數(shù)據(jù)結(jié)構(gòu):變長的list和定長

的array.list用以表示集,array表示數(shù)據(jù)行.根據(jù)建立的邏輯索引,數(shù)據(jù)庫中的一個(gè)表,在hash-table中可能會(huì)存放在多處.以玩家任務(wù)表為例:

chaid,missionid ...

chaid和missionid一起建立了一個(gè)唯一的數(shù)據(jù)庫索引,但可以為它建立兩個(gè)邏輯索引,chaid和chaid,missionid.

這樣,當(dāng)用戶上線時(shí)(假設(shè)用戶id為1001),將導(dǎo)入所有chaid==1001的行,在hash-table中建立一個(gè)list,這個(gè)list中的每個(gè)元素都是一個(gè)array,每個(gè)array表示一個(gè)任

務(wù)記錄行,list就是這個(gè)玩家所有任務(wù)的集合,如果游戲邏輯需要獲取這個(gè)玩家的任務(wù)列表,可以通過以下key獲取"mission,chaid,1001".當(dāng)然僅有一個(gè)行集是不夠的,

因?yàn)楫?dāng)用戶的某個(gè)任務(wù)數(shù)據(jù)變動(dòng)時(shí),必須遍歷list,找到正確的array再將變動(dòng)更新到正確的array中.而網(wǎng)絡(luò)游戲中最頻繁的就是更新操作了,為了提高效率,為每一個(gè)

任務(wù)行建立一個(gè)邏輯索引"chaid,missionid",將任務(wù)對(duì)應(yīng)的數(shù)據(jù)行也存放在hash-table中,這樣如果1001號(hào)玩家希望改變他的2號(hào)任務(wù)的數(shù)據(jù),則可以發(fā)key="mission,

chaid,missionid,1001,2"后跟變更數(shù)據(jù).來改變2號(hào)任務(wù)的數(shù)據(jù).

下面貼出代碼片段,介紹核心的存儲(chǔ)數(shù)據(jù)結(jié)構(gòu).

  1. enum 
  2.     INT8 = 0, 
  3.     INT16, 
  4.     INT32, 
  5.     INT64, 
  6.     DOUBLE, 
  7.     STRING, 
  8.     BINARY, 
  9. }; 
  10.  
  11. typedef struct basetype 
  12.     int8_t type;//the real type 
  13.     void  *data; 
  14. }*basetype_t; 
  15.  
  16. struct db_type_string 
  17.     struct basetype base
  18.     int32_t size; 
  19. }; 
  20.  
  21. struct db_type_binary 
  22.     struct basetype base
  23.     int32_t size; 
  24. }; 

首先是基本的數(shù)據(jù)元素,也就是array可以存放的元素類型,分別是4種整型,double,字符串和二進(jìn)制數(shù)據(jù).

  1. enum 
  2.     DB_LIST = 1, 
  3.     DB_ARRAY, 
  4. }; 
  5.  
  6. typedef struct db_element 
  7.     struct refbase ref
  8.     int32_t hash_index;//index in global_table 
  9.     int8_t type; 
  10. }*db_element_t; 
  11.  
  12. db_element_t db_element_acquire(db_element_t,db_element_t); 
  13. void db_element_release(db_element_t*); 
  14.  
  15.  
  16. //represent a db row 
  17. typedef struct db_array 
  18.     struct db_element base
  19.     int32_t     size; 
  20.     basetype_t* data;  
  21. }*db_array_t; 
  22.  
  23.  
  24. db_array_t db_array_create(int32_t size); 
  25. db_array_t db_array_acquire(db_array_t,db_array_t); 
  26. void       db_array_clear(db_array_t);//clear the data 
  27. void       db_array_release(db_array_t*); 
  28.  
  29.  
  30. //get/set one element of the db row 
  31. basetype_t db_array_get(db_array_t,int32_t index); 
  32. void       db_array_set(db_array_t,int32_t index,basetype_t); 
  33.  
  34. struct db_node 
  35.     list_node  next; 
  36.     db_array_t array; 
  37. }; 
  38.  
  39. //represent db row set 
  40. typedef struct db_list 
  41.     struct db_element base
  42.     struct link_list *l; 
  43.      
  44. }*db_list_t; 
  45.  
  46. db_list_t db_list_create(); 
  47. db_list_t db_list_acquire(db_list_t,db_list_t); 
  48. void      db_list_release(db_list_t*); 
  49. int32_t   db_list_append(db_list_t,db_array_t); 
  50. int32_t   db_list_size(db_list_t); 
  51. int32_t   db_list_shrink(db_list_t); 

然后是array和list的定義,他們都繼承自db_element_t,而hash_table中的元素正是db_element_t.array和list都實(shí)現(xiàn)了引用計(jì)數(shù),這樣當(dāng)所有引用都釋放時(shí),可以被正

確的銷毀。這里要注意的是,一個(gè)array可能被存放在多個(gè)list中,這樣,當(dāng)一個(gè)數(shù)據(jù)行被刪除時(shí),必須讓所有的list知道這個(gè)數(shù)據(jù)已經(jīng)無效。我的做法不是在array被刪

除時(shí)通知所有的list刪除對(duì)應(yīng)的array,而是通過db_array_clear,清除array中存放的有效數(shù)據(jù)。然后通過一個(gè)算法,定期對(duì)數(shù)據(jù)占用最多的list執(zhí)行shrink,以銷毀失效的

array.

  1. typedef struct global_table *global_table_t; 
  2.  
  3. global_table_t global_table_create(int32_t initsize); 
  4. void           global_table_destroy(global_table_t*); 
  5.  
  6.  
  7. db_element_t   global_table_find(global_table_t,const char *key); 
  8. int32_t        global_table_remove(global_table_t,const char *key); 
  9. int32_t        global_table_add(global_table_t,const char *key,db_element_t e); 
  10.  
  11. //collect unused db_element_t 
  12. void           global_table_shrink(global_table_t); 

然后是hash_table的定義,只向外提供三個(gè)操作接口,分別是查找,刪除和添加.對(duì)于添加操作,如果最開始往一個(gè)hash slot添加的是一個(gè)array,當(dāng)再次往這個(gè)slot添加

一個(gè)array時(shí),將會(huì)自動(dòng)將slot中的元素從array提升為list,并將兩個(gè)array都添加到這個(gè)list中.

下面是一些測(cè)試代碼:

  1. #include <stdio.h> 
  2. #include "global_table.h" 
  3.  
  4.  
  5. int main() 
  6.     global_table_t gtb = global_table_create(1024); 
  7.      
  8.     db_array_t a1 = db_array_create(3); 
  9.     db_array_t a2 = db_array_create(3); 
  10.     db_array_t a3 = db_array_create(3); 
  11.     db_array_t a4 = db_array_create(3); 
  12.      
  13.     db_array_set(a1,0,basetype_create_int32(10)); 
  14.     db_array_set(a1,1,basetype_create_int32(11)); 
  15.     db_array_set(a1,2,basetype_create_int32(12)); 
  16.      
  17.     db_array_set(a2,0,basetype_create_int32(20)); 
  18.     db_array_set(a2,1,basetype_create_int32(21)); 
  19.     db_array_set(a2,2,basetype_create_int32(22)); 
  20.      
  21.     db_array_set(a3,0,basetype_create_int32(30)); 
  22.     db_array_set(a3,1,basetype_create_int32(31)); 
  23.     db_array_set(a3,2,basetype_create_int32(32)); 
  24.      
  25.     db_array_set(a4,0,basetype_create_int32(40)); 
  26.     db_array_set(a4,1,basetype_create_int32(41)); 
  27.     db_array_set(a4,2,basetype_create_int32(42)); 
  28.      
  29.     global_table_add(gtb,"kenny",(db_element_t)a1); 
  30.     global_table_add(gtb,"kenny",(db_element_t)a2); 
  31.     global_table_add(gtb,"kenny",(db_element_t)a3); 
  32.     global_table_add(gtb,"kenny",(db_element_t)a4); 
  33.     global_table_add(gtb,"kenny1",(db_element_t)a1); 
  34.     global_table_add(gtb,"kenny2",(db_element_t)a2); 
  35.     global_table_add(gtb,"kenny3",(db_element_t)a3); 
  36.     global_table_add(gtb,"kenny4",(db_element_t)a4); 
  37.          
  38.          
  39.     //test search     
  40.     db_list_t l = (db_list_t)global_table_find(gtb,"kenny"); 
  41.      
  42.     printf("the row size of kenny(a db_list_t):%d\n",db_list_size(l)); 
  43.      
  44.     printf("element of a1:key(kenny1):"); 
  45.     db_array_t _a = (db_array_t)global_table_find(gtb,"kenny1"); 
  46.     int i = 0; 
  47.     for( ; i < 3; ++i) 
  48.     { 
  49.         basetype_t b = db_array_get(_a,i); 
  50.         printf("%d ",basetype_get_int32(b)); 
  51.     } 
  52.     printf("\n"); 
  53.      
  54.     printf("element of a2:key(kenny2):"); 
  55.     _a = (db_array_t)global_table_find(gtb,"kenny2"); 
  56.     i = 0; 
  57.     for( ; i < 3; ++i) 
  58.     { 
  59.         basetype_t b = db_array_get(_a,i); 
  60.         printf("%d ",basetype_get_int32(b)); 
  61.     } 
  62.      
  63.     printf("\n"); 
  64.      
  65.     printf("element of a3:key(kenny3):"); 
  66.     _a = (db_array_t)global_table_find(gtb,"kenny3"); 
  67.     i = 0; 
  68.     for( ; i < 3; ++i) 
  69.     { 
  70.         basetype_t b = db_array_get(_a,i); 
  71.         printf("%d ",basetype_get_int32(b)); 
  72.     } 
  73.      
  74.     printf("\n"); 
  75.      
  76.     printf("element of a4:key(kenny4):"); 
  77.     _a = (db_array_t)global_table_find(gtb,"kenny4"); 
  78.     i = 0; 
  79.     for( ; i < 3; ++i) 
  80.     { 
  81.         basetype_t b = db_array_get(_a,i); 
  82.         printf("%d ",basetype_get_int32(b)); 
  83.     } 
  84.      
  85.     printf("\n"); 
  86.      
  87.     db_array_release(&a4); 
  88.     global_table_remove(gtb,"kenny4"); 
  89.     /* shrink will cause the refcount of a4 reduce to zero, 
  90.      * then a4 will be destroyed 
  91.     */ 
  92.     db_list_shrink(l); 
  93.      
  94.     printf("the row size of kenny(a db_list_t),after remove and shrink: %d\n",db_list_size(l));         
  95.      
  96.     db_array_release(&a1); 
  97.     db_array_release(&a2); 
  98.     db_array_release(&a3); 
  99.      
  100.      
  101.      
  102.     printf("destroy global table,this will cause all element destroyed\n"); 
  103.     global_table_destroy(&gtb); 
  104.      
  105.     return 0; 

本篇僅僅介紹了核心的數(shù)據(jù)結(jié)構(gòu),后端的數(shù)據(jù)庫交互策略,網(wǎng)絡(luò)前端,備份處理和分布式多緩存將在后面慢慢介紹.

 代碼地址:https://github.com/sniperHW/kendylib dbcahce目錄

原文鏈接:http://www.cnblogs.com/sniperHW/archive/2012/08/11/2634052.html

【編輯推薦】

  1. 利用Java進(jìn)行MySql數(shù)據(jù)庫的導(dǎo)入和導(dǎo)出
  2. MySQL集群CGE電信運(yùn)營商級(jí)版本
  3. MySQL 5.5.21 GA發(fā)布(附下載)
  4. MySQL體系結(jié)構(gòu)詳解
  5. 超越MySQL 對(duì)流行數(shù)據(jù)庫進(jìn)行分支

責(zé)任編輯:彭凡 來源: 博客園
相關(guān)推薦

2009-02-03 08:58:13

SQL*Net配置網(wǎng)絡(luò)應(yīng)用

2011-04-08 09:24:24

2012-01-10 15:17:49

2020-08-31 07:00:00

數(shù)據(jù)庫數(shù)據(jù)庫同步

2021-12-22 14:27:02

網(wǎng)絡(luò)游戲網(wǎng)絡(luò)攻擊惡意軟件

2021-11-26 22:07:57

數(shù)據(jù)庫管理Mongodb

2010-09-08 11:06:29

2009-03-23 14:26:42

程序員網(wǎng)絡(luò)游戲經(jīng)驗(yàn)

2009-12-15 08:46:05

Windows 7游戲延遲

2019-08-13 15:52:34

數(shù)據(jù)庫同步遷移

2021-04-02 11:23:01

云計(jì)算數(shù)據(jù)庫云應(yīng)用

2011-04-14 09:38:55

內(nèi)存數(shù)據(jù)庫

2009-05-07 09:07:17

文化產(chǎn)業(yè)網(wǎng)絡(luò)游戲調(diào)查

2009-04-16 09:08:21

Oracle開發(fā)經(jīng)驗(yàn)

2023-09-01 07:30:59

2009-07-17 15:34:37

Java Swing連接數(shù)據(jù)庫

2013-09-24 09:38:03

SQL Server

2009-09-22 08:14:23

2018-09-06 14:53:39

數(shù)據(jù)庫事務(wù)隔離隔離級(jí)別

2014-07-18 17:28:08

Panabit
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)