马上就要放假了,因为临过年了,也没啥事干… … 公司有个数据抽取的模块,是需要一个临时的又高性能的本地KV数据库, leveldb算是个好选择。 以前在人人的时候,我的好多项目都用了leveldb,只是后期改用ssdb的多点。 leveldb在百万数据后,速度明显不行… … 对于现在抽取来说来说,还是够用的了。
关于leveldb的安装和介绍我就不多说了,没啥意思… … 我这边主要是介绍python leveldb库的使用。。。 。。。
import leveldb
db = leveldb.LevelDB('./db')
db.Put('hello', 'world')
print db.Get('hello')
db.Delete('hello')
db.Get('hello')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError
for i in xrange(10):
db.Put(str(i), 'string_%s' % i)
print list(db.RangeIter(key_from = '2', key_to = '5'))
[('2', 'string_2'), ('3', 'string_3'), ('4', 'string_4'), ('5', 'string_5')]
batch = leveldb.WriteBatch()
for i in xrange(1000):
db.Put(str(i), 'string_%s' % i)
db.Write(batch, sync = True)
然后我们可以用FLask封装下leveldb api,做个rest api 。 Flask 默认是单进程单线程的,很容易造成io堵塞的,所以这里用gevent协程来做wsgi
import argparse
import leveldb
import ujson as json
from flask import request, g
from flatdb import flatdb_app
JSON = {'Content-Type': 'application/json'}
def ensure_db():
if 'db' not in g:
g.db = leveldb.LevelDB(flatdb_app.config['DB'])
def put():
ensure_db()
keys = request.args.items(multi=True)
batch = leveldb.WriteBatch()
for k, v in keys:
batch.Put(k, v)
g.db.Write(batch)
return '', 201, JSON
def get():
ensure_db()
keys = request.args.getlist('key')
if not keys:
return '', 204, JSON
response = {}
for k in keys:
try:
response[k] = g.db.Get(k)
except KeyError:
pass
if not response:
return '', 404, JSON
return json.dumps(response), 200, JSON
def getrange():
ensure_db()
from_key = request.args.get('from')
response = {}
vals = g.db.RangeIter(key_from=from_key)
for k, v in vals:
response[k] = v
if not response:
return '', 404, JSON
return json.dumps(response), 200, JSON
def delete():
ensure_db()
keys = request.args.getlist('key')
batch = leveldb.WriteBatch()
for k in keys:
batch.Delete(k)
g.db.Write(batch)
return '', 200, JSON
def define_urls(app):
app.add_url_rule('/put', view_func=put, methods=['GET'])
app.add_url_rule('/get', view_func=get, methods=['GET'])
app.add_url_rule('/getrange', view_func=getrange, methods=['GET'])
app.add_url_rule('/delete', view_func=delete, methods=['GET'])
def get_options():
parser = argparse.ArgumentParser()
parser.add_argument('-d', '--debug', action='store_true', default=False)
parser.add_argument('-p', '--port', type=int, default=7532)
parser.add_argument('-b', '--database')
parser.add_argument('-H', '--host', default='127.0.0.1')
return parser.parse_args()
def configure_app(app, options):
app.config['DB'] = options.database
define_urls(app)
def dev_server():
options = get_options()
configure_app(flatdb_app, options)
flatdb_app.run(debug=options.debug, port=options.port, host=options.host)
def run_server():
options = get_options()
configure_app(flatdb_app, options)
from gevent.wsgi import WSGIServer
server = WSGIServer((options.host, options.port), flatdb_app)
server.serve_forever()
if __name__ == '__main__':
run_server()
祝大家新年快乐…. 原本是打算这两天写个2015的计划书,结果….. 累了,就这么招吧。

levelDB是嵌入式的,使用的是本地IO, gevent只能处理网络io为异步,本地io一样会引起阻塞。
恩,对的 还是会堵塞的. 用gevent做http api,是为了解决flask性能的。 leveldb本身是很快,但是flask在一个量级下会堵塞的。