前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >DBDB: 一个简单的key/value数据库(二)

DBDB: 一个简单的key/value数据库(二)

作者头像
哒呵呵
发布2018-08-06 14:13:45
5230
发布2018-08-06 14:13:45
举报
文章被收录于专栏:鸿的学习笔记鸿的学习笔记

编译自:http://www.aosabook.org/en/500L/dbdb-dog-bed-database.html 作者:Taavi Burns 翻译:鸿 如有翻译问题或建议,请公众号留言

前文点击链接:DBDB: 一个简单的key/value数据库(一)

读取数据 从example.db读取key值:foo

$ python -m dbdb.tool example.db get foo

这里是运行dbdb.tool的main()方法:

# dbdb/tool.py
def main(argv):
    if not (4 <= len(argv) <= 5):
        usage()
        return BAD_ARGS
    dbname, verb, key, value = (argv[1:] + [None])[:4]
    if verb not in {'get', 'set', 'delete'}:
        usage()
        return BAD_VERB
    db = dbdb.connect(dbname)          # CONNECT
    try:
        if verb == 'get':
            sys.stdout.write(db[key])  # GET VALUE
        elif verb == 'set':
            db[key] = value
            db.commit()
        else:
            del db[key]
            db.commit()
    except KeyError:
        print("Key not found", file=sys.stderr)
        return BAD_KEY
    return OK

connect()函数打开一个数据库文件,并且返回一个DBDB实例:

# dbdb/__init__.py
def connect(dbname):
    try:
        f = open(dbname, 'r+b')
    except IOError:
        fd = os.open(dbname, os.O_RDWR | os.O_CREAT)
        f = os.fdopen(fd, 'r+b')
    return DBDB(f)
# dbdb/interface.py
class DBDB(object):

    def __init__(self, f):
        self._storage = Storage(f)
        self._tree = BinaryTree(self._storage)

DBDB引用了一个Storage实例,self._tree也引用了此实例。DBDB实例可以通过字典查找(db [key])来获取键值。同时Python也会调用DBDB.__getitem__()。BinaryNodeRef是一个特殊的ValueRef,它知道如何对BinaryNode进行序列化和反序列化。

# dbdb/logical.py
class LogicalBase(object):
# ...
    def get(self, key):
        if not self._storage.locked:
            self._refresh_tree_ref()
        return self._get(self._follow(self._tree_ref), key)

get()会首先判断数据是否锁住了。(原子性的核心)

# dbdb/logical.py
class LogicalBase(object):
# ...
def _refresh_tree_ref(self):
        self._tree_ref = self.node_ref_class(
            address=self._storage.get_root_address())

_refresh_tree_ref使用磁盘上的数据来重置树的“视图”从而读取最新的数据。如果在读取数据时,数据被锁了会怎么样? 这意味着其他一些进程可能正在改变现在正在读取数据,此时读取的数据有可能不会与当前的数据内容保持一致,这就是“脏读”。 DBDB允许多进程访问数据,而不用担心阻塞,牺牲的代价则是数据稍微过时。

# dbdb/binary_tree.py
class BinaryTree(LogicalBase):
# ...
    def _get(self, node, key):
        while node is not None:
            if key < node.key:
                node = self._follow(node.left_ref)
            elif node.key < key:
                node = self._follow(node.right_ref)
            else:
                return self._follow(node.value_ref)
        raise KeyError

这是标准的二叉树搜索遍历所有节点。 Nodes和NodeRefs是value objects:它们是不可变的并且内容永远不会改变。 节点由关联的key/value和左右侧的子节点创建,它们同样的也永远不会改变。 整个二叉树的内容只有在根节点修改时才会发生改变。 这意味着搜索数据时,不需要担心二叉树树的内容发生改变。一旦找到相关的值,它会被main()方法写入stdout而不添加任何额外的换行符,以精确的保留用户的数据。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-04-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 鸿的学习笔记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档