medis

优质
小牛编辑
128浏览
2023-12-01

medis_server 是一个使用RESP协议进行交互的混合型NOSQL服务器。

它像redis一样,提供多种复杂数据结构——字符串、哈希、列表、集合、队列和堆栈——但是它提供两种保存选择:内存或者硬盘(通过leveldb)。如果这些数据结构还不能满足需要,它还提供sqlite,用户可以自由通过SQL定义数据结构。

medis_server 内嵌lua(5.4)脚本引擎,对于某些需要在服务器端完成的计算,应该是有所帮助的。

所有这些功能,都能通过RESP协议进行访问。也就是说,可以用redis-cli实现与medis_server的交互。

来看例子:

#include <mongols/medis_server.hpp>

int main(int, char**) {
    int port = 9090;
    const char* host = "127.0.0.1";
    mongols::medis_server
    server(host, port, 5000, 8096, 0);
    server.set_lua_package_path("html/lua/package/?.lua;","html/lua/package/?.so;");
    server.run("html/leveldb", "html/sqlite/test.db");
}

redis 是一朵浮云。

  • 高热数据应该保存放在内存,低热数据应该保存在硬盘,中热数据按读多还是写多相机选择内存或硬盘。

  • 对于非字符串的高级数据结构,首选在内存。

  • 特殊情况下,可以用jsoncons将高级数据结构转换为字符串类型进行存储。

  • 保存在内存中的数据按LRU算法更新。

  • 服务器退出时,只有内存数据会消失。

所有命令均为大写,前缀为_下划线的表示保存在内存中。所有保存在内存中的数据均可以通过_FLUSHALL命令全部清除。

所有内存命令支持过期时间机制,默认过期时间为300秒。

常规

  • ECHO value

  • PING [value]

  • FLUSHALL or _FLUSHALL

字符串

  • SET key value or _SET key value

  • GET key or _GET key

  • DEL key or _DEL key

  • EXISTS key or _EXISTS key

  • MSET key value [key value ...] or _MSET key value [key value ...]

  • MGET key [key ...] or _MGET key [key ...]

  • GETSET key value or _GETSET key value

  • STRLEN key or _STRLEN key

  • APPEND key value or _APPEND key value

  • INCR key or _INCR key

  • INCRBY key increment or _INCRBY key increment

  • DECR key or _DECR key

  • DECRBY key decrement or _DECRBY key decrement

  • SETRANGE key start value or _SETRANGE key start value

  • GETRANGE key start count or _GETRANGE key start count

  • _EXPIRE key seconds

  • _TTL key

哈希

  • HSET key field value or _HSET key field value

  • HGET key field or _HGET key field

  • HDEL key field [field ...] or _HDEL key field [field ...]

  • HEXISTS key field or _HEXISTS key field

  • _HERASE key

  • HLEN key or _HLEN key

  • HGETALL key or _HGETALL key

  • HMSET key field value [field value ...] or _HMSET key field value [field value ...]

  • HMGET key field [field ...] or _HMGET key field [field ...]

  • _HEXPIRE key seconds

  • _HTTL key

列表

  • LFRONT key or _LFRONT key

  • LBACK key or _LBACK key

  • LPUSH_FRONT key [value ...] or _LPUSH_FRONT key [value ...]

  • LPUSH_BACK key [value ...] or _LPUSH_BACK key [value ...]

  • LPOP_FRONT key or _LPOP_FRONT key

  • LPOP_BACK key or _LPOP_BACK key

  • LLEN key or _LLEN key

  • LRANGE key start count or _LRANGE key start count

  • _LEXISTS key value

  • _LERASE key

  • _LEXPIRE key seconds

  • _LTTL key

集合(有序)

  • SADD SADD key member [member ...] or _SADD key member [member ...]

  • SDEL key member [member ...] or _SDEL key member [member ...]

  • SMEMBERS key or _SMEMBERS key

  • SEXISTS key or _SEXISTS key

  • SLEN key or _SLEN key

  • SDIFF key1 key2 or _SDIFF key1 key2

  • SINTER key1 key2 or _SINTER key1 key2

  • SUNION key1 key2 or _SUNION key1 key2

  • SSYDIFF key1 key2 or _SSYDIFF key1 key2

  • _SERASE key

  • _SEXPIRE key seconds

  • _STTL key

队列

  • _QPUSH key member [member ...]

  • _QPOP key

  • _QEMPTY key

  • _QFRONT key

  • _QBACK key

  • _QERASE key

  • _QLEN key

  • _QEXPIRE key seconds

  • _QTTL key

堆栈

  • _ZPUSH key member [member ...]

  • _ZPOP key

  • _ZTOP key

  • _ZEMPTY key

  • _ZERASE key

  • _ZLEN key

  • _ZEXPIRE key seconds

  • _ZTTL key

SQLite

  • SQLCMD statement

    SQLCMD 'update a set name="test" where id=4 or id=5'

  • SQLBINDCMD statement

    SQLBINDCMD "INSERT INTO A(ID,NAME)VALUES(:ID,:NAME);" ":ID" 4 ":NAME" "CPP"

  • SQLTRANSACTION statement

    SQLTRANSACTION 'INSERT INTO A(ID,NAME)VALUES(14,"14");UPDATE A SET NAME="TEST" WHERE ID=14;'

  • SQLQUERY statement

    SQLQUERY 'SELECT * FROM A ORDER BY ID desc limit 3'

lua 脚本引擎

该引擎为lua5.4,内置一个名为medis的表变量,它包含一个CMD函数,它可以调用所有上述操作方法。 如果调用以下两个命令时,包含额外参数,那么可以通过medis表中ARGS表域访问到它们。它们的值从第三个值开始计算。

如果需要返回值,可使用medis表变量中的RESULT变量,该变量可返回布尔值、整数、字符串和无嵌套的表。

为了方便,我还在lua引擎中嵌入了一个可用于正则计算的表:mongols_regex,内含三个函数:

  • full_match
  • partial_match
  • match

以及一个用于md5和sha1计算的表:mongols_hash,内含两个函数:

  • md5
  • sha1

使用方法可参考:regex.lua

把一组相关计算放在lua脚本中,并在服务器端运行它,可以省去网络交互的麻烦。当然,也会消耗一些服务器时间。所以,该引擎主要针对轻量级计算。

  • LUACONTENT statement [arg ...]

    LUACONTENT "local JSON = require('JSON') local t =JSON:encode({a=medis.ARGS[4],b=2,{c=4}}) medis.CMD('SET',medis.ARGS[3],t)" lua 100

  • LUASCRIPT path [arg ...]

    LUASCRIPT 'html/lua/medis.lua' lua Tom


local echo=require('echo')
medis.CMD('SET',medis.ARGS[3],echo.concat('hello,',medis.ARGS[4]))
medis.RESULT={a='hello',b='world',1,3.5,'test'}