-
当时需要使用SSDB的原因有几个,首先是对于contest模块设计的时候,由于点击查询当前比赛的Rank的时候,需要多次查询,而每次查 询的数据量比较大,为了能够高效的获取数据而使用SSDB数据库;第二方面是对于用户AC状态的记录,在用户登录进之后,网页需要显示用户AC了哪些题 目,哪些题目尝试了但没有通过。为了必须遍历当前系统存储的所有的submit,这样的话数据量也是很大,依照前面的原则,继续采用SSDB解决。
1:那SSDB到底是什么呢?
百度了一下,没有找到百度百科,找到的一个定义是SSDB是一个开源的高性能数据库服务器, 使用Google LevelDB作为存储引擎, 支持T级别的数据。从字面意思来讲,就是这个数据库有很高的性能((/ □ \))。然后的话,我们需要用到的就是查询速度高的特点。
2:SSDB 的主要特点(条目性的统计((/ □ \)),我们主要用到的模式就是k-v模式,即键值-值):
支持 zset, map/hash, list, kv 数据结构, 可替代 Redis
特别适合存储大量集合数据, 支持丰富的数据结构: key-value, key-map, key-zset, key-list.
使用 Google LevelDB 作为存储引擎
支持主从同步, 多主同步
客户端支持 PHP, C++, Python, Lua, Java, Ruby, nodejs, Go 等
内存占用极少3:安装及启动停止
SSDB 的建议安装?方式是源码编译安装, 建议运?行环境是主流 Linux 发?行版. 远程 SSH 登录你的服务器, 然后?用下?面的命令下载, 编译, 安装和运?行:
# 安装
$ sudo wget --no-check-certificate https://github.com/ideawu/ssdb/archive/master.zip
$ sudo unzip master
$ cd ssdb-master
$ sudo make
$ #optional, install ssdb in /usr/local/ssdb
$ sudo make install
# 启动
$ sudo ./ssdb-server ssdb.conf
# 启动作为守护进程
$ sudo ./ssdb-server -d ssdb.conf
# 停止
$ sudo kill `cat ./var/ssdb.pid`
SSDB 默认安装在 /usr/local/ssdb ?目录下. ssdb-server 是服务器的程序, ssdb-cli 是命令?行客户端.
4:配置
SSDB 附带的 ssdb.conf是配置文件,一般不用修改便可以使用.。标准配置文件如下:
# ssdb-server config
# MUST indent by TAB!# relative to path of this file, directory must exists
work_dir = ./var
pidfile = ./var/ssdb.pidserver:
ip: 127.0.0.1
port: 8888
# bind to public ip
#ip: 0.0.0.0
# format: allow|deny: all|ip_prefix
# multiple allows or denys is supported
#deny: all
#allow: 127.0.0.1
#allow: 192.168replication:
slaveof:
# to identify a master even if it moved(ip, port changed)
# if set to empty or not defined, ip:port will be used.
#id: svc_2
# sync|mirror, default is sync
#type: sync
#ip: 127.0.0.1
#port: 8889logger:
level: info
output: log.txt
rotate:
size: 1000000000leveldb:
# in MB
cache_size: 500
# in KB
block_size: 32
# in MB
write_buffer_size: 64
# in MB
compaction_speed: 1000
# yes|no
compression: nowork_dir: ssdb-server 的工作目录, 启动后, 会在这个目录下生成 data 和 meta 两个目录, 用来保存 LevelDB 的数据库文件. 这个目录是相对于 ssdb.conf 的相对路径, 也可以指定绝对路径.
server: ip 和 port 指定了服务器要监听的 IP 和端口号. 如果 ip 是 0.0.0.0, 则表示绑定所有的 IP. 基于安全考虑, 可以将 ip 设置为 127.0.0.1, 这样, 只有本机可以访问了. 如果要做更严格的更多的网络安全限制, 就需要依赖操作系统的 iptables.
replication: 用于指定主从同步复制. slaveof.ip, slaveof.port 表示, 本台 SSDB 服务器将从这个目标机上同步数据(也即这个配置文件对应的服务器是 slave). 你可以参考 ssdb_slave.conf 的配制.
logger: 配置日志记录. level 是日志的级别, 可以是 trace|debug|info|error. output 是日志文件的名字, SSDB 支持日志轮转, 在日志文件达到一定大小后, 将 log.txt 改名, 然后创建一个新的 log.txt.
leveldb: 配置 LevelDB 的参数. 你一般想要修改的是 cache_size 参数, 用于指定缓存大小. 适当的缓存可以提高读性能, 但是过大的缓存会影响写性能.
在使?用?自带的 ssdb.conf 配置?文件时, SSDB ?生成的?日志?文件按体积进?行分割, 仅此?而已. 所以, 你需要编写?自?己的 crontab 进?行?日志压缩和定期清理.
如果出现服务器掉电, kernel panic 等系统故障, 在系统重新启动之后, 你需要?手动删除 ssdb的 PID ?文件 ssdb.pid, 然后才能启动。5使用流程:
安装完成之后,在ssdb目录下执行 sudo ./ssdb-server -d ssdb.conf启动SSDB即可,这时,数据库已经在运行。
当需要存储数据时:
首先:整理需要存储的信息,比如(contestID , rank_list_proto_str)其中前者为键,后者为值。
再者:决定操作,目前我们主要涉及的操作就是对于数据的存储和查询,即insert和get操作:
在插入数据时,使用的模式是ssdb.set(key,value),如果key是一个组合的话,那么中间用\'\t\'相连,例如ssdb.set(userID + \'\t\' + problemID, value)。
查询的时候,主要模式是一样的,即使用ssdb.get(key)就可以得到对应的value了。如果没有对应的值,则返回空字符串。
插入:
1ssdb_api.SetContestRankListProto(contestID, contest_rank_list.SerializeToString())
1ssdb_api.InsertUserProblemStatus(
user
.userID, submit.problemID, submit.status)
查询:1contest_rank_list = ssdb_api.GetContestRankListProto(contest_id)
1status_ = ssdb_api.GetUserProblem(
user
.userID, problem.problemID)
上述的操作都是已经写好了操作函数,即view/ssdb_api.py中的函数123456789101112131415161718192021222324252627282930from
ssdb import SSDB
import sys
import cugbacm.proto.rank_pb2
ssdb_ip =
"127.0.0.1"
ssdb_port = 6666
ssdb = SSDB(host=ssdb_ip, port=ssdb_port)
def GetContestRankListProto(contestID):
global
ssdb
proto_str = ssdb.get(contestID)
return
proto_str
def SetContestRankListProto(contestID, rank_list_proto_str):
global
ssdb
try:
ssdb.
set
(contestID, rank_list_proto_str)
except
:
pass
def InsertUserProblemStatus(userID, problemID, status):
#AC == 1 No_pass = 2 other = 0
global
ssdb
value = 2
if status ==
"Accepted"
:
value = 1
st = str(ssdb.get(userID +
\'\t\'
+ str(problemID)))
if st ==
"1"
:
return
;
else
:
ssdb.
set
(userID +
\'\t\'
+ str(problemID), value)
1234567<pre
name
=
"code"
class=
"html"
>def GetUserProblem(userID, problemID):
global
ssdb
st = ssdb.get(userID +
\'\t\'
+ str(problemID))
if str(st) !=
"1"
and
str(st) !=
"2"
:
return
"0"
else
:
return
str(st)
其余的后续补充吧(/ □ \)
相关文章
- SPSS主成分分析插件程序使用说明及下载 - 小象
- 【深入浅出Docker原理及实战】「原理实战体系」零基础+全方位带你学习探索Docker容器开发实战指南(Dockerfile使用手册)
- wiringPi库的pwm配置及使用说明
- Linux 系统下安装 rz/sz 命令及使用说明
- Redis(Windows安装方法与Java调用实例 & 配置文件参数说明 & Java使用Redis所用Jar包 & Redis与Memcached区别 & redis-cli.exe命令及示例)
- ios NSURLSession(iOS7后,取代NSURLConnection)使用说明及后台工作流程分析
- IntelliJ IDEA下SVN的配置及使用说明
- Objective-C(十七、KVC键值编码及实例说明)——iOS开发基础
- Ansible基础认识及安装使用详解(week5_day1_part1)--技术流ken
- android 基础控件(EditView、SeekBar等)的属性及使用方法