标题：kvdb
简介
KVDB是新浪SAE开发的分布式key-value数据存储服务，用来支持公有云计算平台上的海量key-value存储。KV DB支持的存储容量很大，对每个用户支持100G的存储空间，可支持1,000,000,000条记录，用户可以用KV DB存放简单数据，如好友关系等[1]。
因为传统关系型数据库在分布式环境下表现的扩展性不足等缺点，近年来NoSQL的概念渐渐成为业界关注的焦点，越来越多的技术人员也习惯于使用NoSQL数据库进行日常开发，SAE为了应对这种新需求，也进行了NoSQL方向的研发。
KVDB是高性能高可靠存储，根据我们内部测试，读写都可以达到10w qps。KV DB采用一主多从的分布式架构，SAE提供热备和定期冷备，发生宕机时，会自动切换到健康的DB上。
KVDB的使用非常方便，用户在使用时，只需要先调用init()函数，就可以调用KV的各种读写函数，值得一提的是，因为KV DB的实际存储选择用B+树实现，所以KV DB还支持前缀查找。
计费说明
数据存储：5云豆/GB·天，即0.05元/GB·天
请求数：0.5云豆/万次，及0.005元/万次
服务限制
key的最大长度：200字节
value的最大长度：4M （默认启用压缩）
mget获取的最大KEY个数：32
pkrget获取的最大KEY个数：100
PHP调用方式
开启开发者在登录SAE后，在右上角我的应用中选中指定应用后，点击开启服务即可关闭开发者在登录SAE后，选中应用后，点击禁用服务即可，特别注意，禁用后会清除所有数据，请谨慎操作使用KV DB的使用和MemcacheX的使用方式几乎一样，先init()后即可操作KV函数，示例：
$kv = new SaeKV();
// 初始化KV对象
$ret = $kv->init();
if($ret==true)
{
for($i=0;$i<100;$i++)
{
$ret = $kv->set($i, 'aaaaaa');
var_dump($ret);
}
}
KV DB现支持以下操作：
get 按key读取
mget 按key批量读取
pkrget 按key前缀查找
set 更新
delete 删除注意事项目前默认使用urlencode来编码key,之前采用其他编码方式以中文作为key的用户，可以通过SaeKV::get_options/SaeKV::set_options来获取和设置是否编码key，以禁用key编码的方式来解决无法get中文key的问题。
代码示例：
$flags = $kv->get_options();
$kv->set_options($flags & ~SaeKV::OPT_ENCODEKEY);
Java调用方式
如何启用服务应用使用KVDB服务需要在应用的KVDB管理界面中开启服务，之后再代码中参照API接口文档调用即可。如果你需要关闭KVDB服务,在面板中点击禁用服务即可，你需要特别注意的是禁用后会清空KVDB中的所有数据，请谨慎操作。本地环境使用本地开发环境的KVDB服务采用JavaDB进行模拟，你仅需将derby.jar(在下载中心可下载)放入工程的classpath中即可使用。另外由于本地环境只是模拟环境，所以效率达不到线上环境真实服务速度。支持数据类型KVDB支持boolean，long，double，byte[]四种基本类型直接存取操作，当然你也可以存取其他数据类型（short、float、int）或是对象（String和自定义对象等），但是你需要将数据类型做适当的转换。API中提供了SaeKVUtil工具类，可以帮你简化数据类型转换的操作,详情请看下文的使用范例。使用范例对KVDB所有操作都封装在SaeKV类中，当然存储对象等类型时你可以使用SaeKVUtil进行类型转换。在调用KVDB操作前你需要先初始化服务，即需先调用SaeKV的init()方法，需要注意的是你必须基于请求来执行初始化操作。
SaeKV kv=new SaeKV();
//初始化服务
kv.init();
基本数据类型存存取
//存取long类型
kv.set("longValue", 65535L);
kv.get("longValue");
//存取boolean类型
kv.set("boolean", true);
kv.get("boolean");
//存取double类型
kv.set("doubleValue",1.24);
kv.get("doubleValue");
//存取byte[]类型
kv.set("bytes",new byte[]{1,2});
byte [] b = kv.get("bytes");
//存取int类型(需转换成long)
kv.set("intValue", SaeKVUtil.intToLong(123));
SaeKVUtil.longToInt(kv.get("intValue"));
//存取float类型
kv.set("floatValue",1.24f);
kv.get("floatValue");
//存取short类型
kv.set("shortValue",(short)1);
SaeKVUtil.longToShort(kv.get("shortValue"))String类型存取存取String有两种方法，一种是使用SaeKVUtil的StringToByte方法将String转换成byte[]进行存储，再用SaeKVUtil的byteToString方法取出byte[]进行转换。第二种方法是将String看做是可序列化的对象，和普通对象一样存取。
//存取String类型 注意这里StringToByte返回的是String的getBytes()值，并非序列化后的byte[]
kv.set("string", SaeKVUtil.StringToByte("abc"));
SaeKVUtil.byteToString((byte[])kv.get("string"));
//第二种存储方式 把String当做可序列化对象来存储区
kv.set("string1", SaeKVUtil.serializable("abc"));
SaeKVUtil.deserializable((byte[])kv.get("string1"));对象类型存取这里需要特别注意的是，只有可序列化的对象(实现Serializable接口)才能存储到kvdb中
//存取对象类型 Person实现Serializable接口
kv.set("person", SaeKVUtil.serializable(new Person(1,"ward")));
SaeKVUtil.deserializable(kv.get("person"));
范围查找
范围查找是根据key的范围来查找对应的值，返回值类型为Map
/*
* startKey - 范围查找起始的key
* endKey - 范围查找结束的key
* isContainStartVlaue - 是否包含第一个查到的key
* isContainEndValue - 是否包含最后一个查到的key
* queryCount 查询的数量
*/
kv.rget("a","d",true,true,5)
//当然你也可以用简化的方法
kv.rget("a","d");
前缀查找
前缀查找可根据key值的前缀来过滤查找数据，返回值类型为Map
/**
* key前缀
* 查询数量，最多支持100个，如果超过100个只按100个查询
* 是否包含查找的值，如果设置此值为false，则返回的map中所有的value都为null
* 需要比较的key，如果存储的key为test1，test2，test3，test4，输入test2，则返回的test3和test4
*/
kv.pkrget("test",100,true,"test1");
//简化方法
kv.pkrget("test","test1");
查找多个key的值
可获取多个key值(String数组)的Value对应关系，返回值类型为Map
//key值数量必须小于32
kv.getMulti(new String[]{"test1","test2"});
范围删除
根据key值范围范围删除，和范围查找相视
/**
* startKey 起始的key
* endKey 结束的key
* isContainStartVlaue 是否包含第一个查到的key
* isContainEndValue 是否包含最后一个查到的key
* deleteCount 删除的数量
* @return 删除操作是否成功
*/
kv.rdel("a","d",true,true,3);
//同样也可以使用简便的方法
kv.rdel("a","d");
Python调用方式
KVDB服务使用前需要在 管理面板 中启用，不再使用时可以在面板中禁用，禁用会删除所有数据。
class sae.kvdb.Error
通用错误
class sae.kvdb.RouterError
路由meta信息错误
class sae.kvdb.StatusError
kvdb状态不为OK
class sae.kvdb.KVClient(debug=0)
KVDB客户端基于python-memcached，大多数method使用方法相同。 如果不能成功创建KVClient，则抛出 sae.kvdb.Error 异常。
debug 是否输出详细调试、错误信息到日志，默认关闭
set(key, val, time=0, min_compress_len=0)
设置key的值为val，成功则返回True
time 该key的超时时间，请参阅memcached协议Storage 。
min_compress_len 启用zlib.compress压缩val的最小长度，如果val的长度大于此值 则启用压缩，0表示不压缩。
add(key, val, time=0, min_compress_len=0)
同set，但只在key不存在时起作用
replace(key, val, time=0, min_compress_len=0)
同set，但只在key存在时起作用
delete(key, time=0)
删除key，成功返回1，失败返回0。
time 为后续多少秒内set/update操作会失败。
get(key)
从kvdb中获取一个key的值。成功返回key的值，失败则返回None
get_multi(keys, key_prefix='')
从kvdb中一次获取多个key的值。返回一个key/value的dict。
keys: key的列表，类型必须为list。
key_prefix: 所有key的前缀。请求时会在所有的key前面加上该前缀，返回值里所有的key都会去掉该前缀。
get_by_prefix(prefix, max_count=100, start_key=None)
从kvdb中查找指定前缀的 key/value pair。返回一个list，该list中每个item为一个(key, value)的tuple。
prefix: 需要查找的key的前缀。
max_count: 最多返回的item个数，默认为100。
start_key: 指定返回的第一个item的key，该key不包含在返回中。
getkeys_by_prefix(prefix, max_count=100, start_key=None)
从kvdb中查找指定前缀的key。返回符合条件的key的list。
prefix: 需要查找的key的前缀。
max_count: 最多返回的key的个数，默认为100。
start_key: 指定返回的第一个key，该key不包含在返回中。
get_info()
获取本应用kvdb统计数据，返回一个字典:
{
'outbytes': 126,
'total_size': 3,
'inbytes': 180,
'set_count': 60,
'delete_count': 21,
'total_count': 1,
'get_count': 42
}
disconnect_all()关闭kvdb连接示例代码:
import sae.kvdb
kv = sae.kvdb.KVClient()
k = 'foo'
kv.set(k, 2)
kv.delete(k)
kv.add(k, 3)
kv.get(k)
kv.replace(k, 4)
kv.get(k)
print kv.get_info()服务限制:存储空间：100G
最大记录条数：1,000,000,000
key的最大长度：200 Bytes
value的最大长度：4M
get_multi获取的最大KEY个数：32