12
返回列表 发新帖
楼主: jieforest

Redis添加区间集

[复制链接]
论坛徽章:
277
马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14马上有车
日期:2014-02-18 16:41:112014年新春福章
日期:2014-02-18 16:41:11版主9段
日期:2012-11-25 02:21:03ITPUB年度最佳版主
日期:2014-02-19 10:05:27现任管理团队成员
日期:2011-05-07 01:45:08
11#
 楼主| 发表于 2013-8-18 11:06 | 只看该作者
Defining the Interval Set

With the majority of the supporting tie-in code written, we can turn our focus on the actual data structure and the functions that respond to the external commands. First, we should add our command functions to the command table at line 115 of src/redis.c.
  1. {"iadd",iaddCommand,-5,"wm",0,NULL,1,1,1,0,0},
  2. {"irem",iremCommand,-3,"w",0,NULL,1,1,1,0,0},
  3. {"irembystab",irembystabCommand,3,"w",0,NULL,1,1,1,0,0},
  4. {"istab",istabCommand,-3,"r",0,NULL,1,1,1,0,0},
复制代码
We’ll define that AVL management functions as well as the four above functions in src/t_iset.c, a new module we create to hold just our custom datatype.

使用道具 举报

回复
论坛徽章:
277
马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14马上有车
日期:2014-02-18 16:41:112014年新春福章
日期:2014-02-18 16:41:11版主9段
日期:2012-11-25 02:21:03ITPUB年度最佳版主
日期:2014-02-19 10:05:27现任管理团队成员
日期:2011-05-07 01:45:08
12#
 楼主| 发表于 2013-8-18 11:07 | 只看该作者
I won’t be going through every aspect of the datatype, as the implementation is almost 1,000 lines long (view the full source). However, I do want to touch on a couple of points.

1) The avlCreate() function creates a structure for holding an interval tree as well as an internal Redis dict using dictCreate(). We use this dict to maintain the set of values that have already been added to the interval sets, guaranteeing constant member lookup and deletion.

2) The avlFree() function calls decrRefCount() with the robj at the node being freed. This is required to ensure Redis properly removes the object when no longer referenced (it may still be referenced in the dict mentioned above).

3) The iaddCommand() function is variadic, and thus can be used to add multiple items to the set with a single call. This is a good example method to reference for implementing similar functionality.

使用道具 举报

回复
论坛徽章:
27
优秀写手
日期:2013-12-18 09:29:09ITPUB季度 技术新星
日期:2012-08-15 14:50:13嫦娥
日期:2013-03-04 09:47:05数据库板块每日发贴之星
日期:2011-09-08 01:01:01数据库板块每日发贴之星
日期:2011-09-11 01:01:01数据库板块每日发贴之星
日期:2011-09-10 01:01:02数据库板块每日发贴之星
日期:2011-09-09 01:01:01ITPUB十周年纪念徽章
日期:2011-11-01 16:26:59ITPUB 11周年纪念徽章
日期:2012-09-28 17:34:422013年新春福章
日期:2013-03-04 09:50:49
13#
发表于 2013-8-18 11:27 | 只看该作者
jieforest 发表于 2013-8-17 10:44
我工作十多年了,职位是架构师,熟悉并关注的领域很多。可能是职务的原因吧,我自我评价:博而不精。

那你是老前辈了,以后在mongodb上面多多指教吧!

使用道具 举报

回复
论坛徽章:
277
马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14马上有车
日期:2014-02-18 16:41:112014年新春福章
日期:2014-02-18 16:41:11版主9段
日期:2012-11-25 02:21:03ITPUB年度最佳版主
日期:2014-02-19 10:05:27现任管理团队成员
日期:2011-05-07 01:45:08
14#
 楼主| 发表于 2013-8-19 08:53 | 只看该作者
Persistence

Redis provides two forms of disk persistence: RDB and AOF. RDB is a binary storage format that represents snapshots of the entire Redis database at any point in time. AOF (append-only file) is an append-only log of all Redis commands that have been run to build the database in its current format.

For our custom datatype, we will build in support for both types of persistence. If you can be sure that you will only use one type of persistence, you can implement support for only that format. Be forewarned, however, that the Redis server will throw a panic if you attempt to use a persistence strategy that is not supported by your custom type.

使用道具 举报

回复
论坛徽章:
277
马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14马上有车
日期:2014-02-18 16:41:112014年新春福章
日期:2014-02-18 16:41:11版主9段
日期:2012-11-25 02:21:03ITPUB年度最佳版主
日期:2014-02-19 10:05:27现任管理团队成员
日期:2011-05-07 01:45:08
15#
 楼主| 发表于 2013-8-19 08:56 | 只看该作者
RDB

We’ll start off by adding RDB support for interval sets. First, we need to define a constant that represents our interval type for RDB at the datatype definitions starting at line 72 of src/rdb.h.
  1. #define REDIS_RDB_TYPE_ISET   5
复制代码
Next, we need to add the code responsible for saving the interval set. First we need to add the interval set case to the switch statement inrdbSaveObjectType() at line 430 of src/rdb.c.
  1. case REDIS_ISET:
  2.     return rdbSaveType(rdb,REDIS_RDB_TYPE_ISET);
复制代码

使用道具 举报

回复
论坛徽章:
277
马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14马上有车
日期:2014-02-18 16:41:112014年新春福章
日期:2014-02-18 16:41:11版主9段
日期:2012-11-25 02:21:03ITPUB年度最佳版主
日期:2014-02-19 10:05:27现任管理团队成员
日期:2011-05-07 01:45:08
16#
 楼主| 发表于 2013-8-19 08:56 | 只看该作者
Second, we will add the actual save logic to rdbSaveObject() at line 478 of src/rdb.c.
  1. else if (o->type == REDIS_ISET) {
  2.     avl * tree = o->ptr;
  3.     dictIterator *di = dictGetIterator(tree->dict);
  4.     dictEntry *de;

  5.     if ((n = rdbSaveLen(rdb,dictSize(tree->dict))) == -1) return -1;
  6.     nwritten += n;

  7.     while((de = dictNext(di)) != NULL) {
  8.         robj *eleobj = dictGetKey(de);
  9.         double *scores = dictGetVal(de);

  10.         if ((n = rdbSaveStringObject(rdb,eleobj)) == -1) return -1;
  11.         nwritten += n;
  12.         if ((n = rdbSaveDoubleValue(rdb,scores[0])) == -1) return -1;
  13.         nwritten += n;
  14.         if ((n = rdbSaveDoubleValue(rdb,scores[1])) == -1) return -1;
  15.         nwritten += n;
  16.     }
  17.     dictReleaseIterator(di);
  18. }
复制代码

使用道具 举报

回复
论坛徽章:
277
马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14马上有车
日期:2014-02-18 16:41:112014年新春福章
日期:2014-02-18 16:41:11版主9段
日期:2012-11-25 02:21:03ITPUB年度最佳版主
日期:2014-02-19 10:05:27现任管理团队成员
日期:2011-05-07 01:45:08
17#
 楼主| 发表于 2013-8-19 08:57 | 只看该作者
This code creates an iterator on the dict internal to the interval set and proceeds to walk the dict. For each element encountered, the element’s value is saved along with the minimum and maximum scores associated with the interval.

After finishing with the save logic, we need to implement load logic in the rdbLoadObject() function at line 771 of src/rdb.c.
  1. else if (rdbtype == REDIS_RDB_TYPE_ISET) {
  2.     size_t isetlen;
  3.     avl * tree;
  4.     size_t maxelelen = 0;

  5.     if ((isetlen = rdbLoadLen(rdb,NULL)) == REDIS_RDB_LENERR) return NULL;
  6.     o = createIsetObject();
  7.     tree = o->ptr;

  8.     while(isetlen--) {
  9.         robj *ele;
  10.         double score1;
  11.         double score2;

  12.         avlNode *inode;

  13.         if ((ele = rdbLoadEncodedStringObject(rdb)) == NULL) return NULL;
  14.         ele = tryObjectEncoding(ele);
  15.         if (rdbLoadDoubleValue(rdb,&score1) == -1) return NULL;
  16.         if (rdbLoadDoubleValue(rdb,&score2) == -1) return NULL;

  17.         /* Don't care about integer-encoded strings. */
  18.         if (ele->encoding == REDIS_ENCODING_RAW &&
  19.             sdslen(ele->ptr) > maxelelen)
  20.             maxelelen = sdslen(ele->ptr);

  21.         inode = avlInsert(tree, score1, score2, ele);
  22.         dictAdd(tree->dict,ele,&inode->scores);
  23.         incrRefCount(ele); /* Added to dictionary. */
  24.     }
  25. }
复制代码

使用道具 举报

回复
论坛徽章:
277
马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14马上有车
日期:2014-02-18 16:41:112014年新春福章
日期:2014-02-18 16:41:11版主9段
日期:2012-11-25 02:21:03ITPUB年度最佳版主
日期:2014-02-19 10:05:27现任管理团队成员
日期:2011-05-07 01:45:08
18#
 楼主| 发表于 2013-8-19 08:57 | 只看该作者
We start the load code by reading the number of elements to expect during the load; this was automatically written by rdbSaveObject(). We then simply create a new interval set with createIsetObject() and then read in each node one by one, adding each to the tree withavlInsert() and dictAdd.

With that, the RDB code is complete.

Append-Only File

AOF support is much simpler; by default, each command sent to the Redis server is appended to the log, and thus support is already baked in. However, Redis does intelligently rewrite the append-only file when the file gets too big to eliminate redundancy. For instance, if a specific element has been added and deleted 500 times, we shouldn’t have 500 copies of the same add and delete commands. Thus we need to add a method that will iterate the interval set and write out the IADD commands to regenerate the set.

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 未成年人举报专区 
京ICP备16024965号-8  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表