V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
newghost
V2EX  ›  程序员

OnceDB 内存数据库引擎:像关系型数据库那样,查询、搜索、更新、全文索引海量 Redis 数据

  •  1
     
  •   newghost ·
    newghost · Feb 27, 2020 · 3307 views
    This topic created in 2254 days ago, the information mentioned may be changed or developed.

    OnceDB 是基于 Redis 二次开发的全文搜索内存数据库,支持像 SQL 关系数据库和 NoSQL 无模式数据库那样管理数据。

    OnceDB 并不改变 Redis 的数据存储结构,与 Redis 3.x 完全兼容,Redis 数据库文件可以直接在 OnceDB 中操作,并再返回 Redis 中使用。

    Redis 特点

    性能强劲

    我们一直在开发能够运行在 arm 和 x86 平台上的管理软件。很多 arm 开发板运行在 TF 存储卡止。TF 卡的读写速度其实非常有限,读取、写入速度在 10~30M/s 之间,只有 Redis 这样的内存数据库,才能够在 arm 设备持续向外传送文件时,依然保持非常优异的并发能力,而不会造成 Web 服务不可用。

    开发效率

    Redis 中存放的只是一些基本的数据结构,只能通过复杂的方法实现数据索引、查询,所以如果只使用 Redis 数据库的话,开发效率非常低。所以一般以其它数据库为主,Redis 作为高性能缓存层来使用。

    二次开发 Redis

    为了充分利用 Redis 优异的性能,并能像 MySQL 或 MongoDB 数据库那样适应更多应用场景并提高开发效率。我们基于 Redis 进行了二次开发,添加了全文搜索,多条件查询,分析计算等功能。并通过辅助索引,提高在海量数据下搜索和查询的性能。该项目命名为 OnceDB, 支持 Windows 和 Linux,

    快速安装 OnceDB

    在 Github 上选择相应操作系统和芯片架构的安装包,解压即可运行。

    https://github.com/OnceDoc/OnceDB/releases/

    在 Windows 平台下,运行 oncedb-server.exe 即可启动服务。

    OnceDB 辅助索引

    OnceDB 通过有序列表( zset )实现辅助索引,大幅提高在复杂查询条件下,搜索海量数据的性能。

    OnceDB 可使用 upsert 或 insert 命令添加数据,并通过操作符来自动创建这些索引。

    比如添加一条 user:dota 数据,并设置相应索引:

    @ username 为主键字段
    ? 为 title 创建分组索引
    * 为 skills 创建关键字索引
    

    命令如下

    upsert user username @ dota password = 123456 title ? SDEI skills * java,go,c
    > OK
    

    然后可使用 find 指令查询数据,如果是是索引字段,可通过操作符从索引中搜索,比如搜索包含 c 关键字的 user 数据,则使用 “*” 操作符。打印 username 和 password 字段,使用 "= *" 来表达:

    find user 0 -1 username = * password = * skills * c
    1) (integer) 1
    2) "user:dota"
    3) "dota"
    4) "123456"
    5) "java,go,c"
    

    搜索结果第 1 行 “(integer) 1” 为符合条件的数据总数。如果使用全文搜索,则会返回 -1。

    比如全文搜索包含 c 的数据, 可使用 "~" 操作符:

    find user 0 -1 username = * password = * skills ~ c
    1) (integer) -1
    2) "user:dota"
    3) "dota"
    4) "123456"
    5) "java,go,c"
    

    返回的 -1 表明使用了全文搜索,全文搜索支持 “<, >, <=, >=' 等数值比较搜索。

    更多指令帮助请参考: OnceDB 数据修改和查询帮助文档

    OnceDB 驱动客户端( node.js )

    OnceDB 并不在底层约束数据模式,而通过驱动层来动态定义数据表、字段、类型、索引等,改变 Schema 定义即可扩展现在有表和字段,从而实现模式的动态定义。

    OnceDB 客户端已经发布,可通过 npm 可安装:npm install oncedb

    安装完成后可,连接到本地 oncedb-server:

    var oncedb = require('oncedb')()
    

    在更新查询数据前,需要先定义 schema 数据模式,指定含有哪些字段,设置字段类型,索引等。比如上文的 user 数据,可定义成如下模式:

    oncedb.schema('user', {
        username  : 'id'
      , password  : ''
      , title     : 'index'
      , skills    : 'keywords'
    });
    

    然后可以通过 oncedb.upsert 更新数据。

    oncedb.upsert('user', { username: 'dota', password: '123456', title: 'SDEI', skills: 'java,go,c' }, function(err) {
      // done
    })
    

    然后查询数据,此时会自动根据 schema 中的定义,从相应索引查询数据。

    oncedb.select('user', { skills: 'c' }, function(err, rows) {
       console.log('rows.count', rows.count)
       console.log(rows)
    })
    

    async / await 同步语法

    可使用 util.promisify 格式化接口,将回调改造成 async/ await 同步语法:

    const util    = require('util')
    const oncedb  = require('oncedb')()
    
    const update  = util.promisify(oncedb.update).bind(oncedb)
    const select  = util.promisify(oncedb.select).bind(oncedb)
    

    然后上面的 callback 模式就可改写成顺序模式:

    // 更新数据
    await upsert('user', { username: 'dota', password: '123456', title: 'SDEI', skills: 'java,go,c' })
    // 查询数据
    let rows = await select('user', { skills: 'c' })
    
    console.log('rows.count', rows.count)
    console.log(rows)
    

    输出结果:

    rows.count 1
    [
      {
        _key: 'user:dota',
        skills: [ 'java', 'go', 'c' ],
        username: 'dota',
        password: '123456',
        title: 'SDEI'
      }
    ]
    

    此时可根据 rows.count 来判断是不是启用了索引搜索,如果是 -1,则代表使用了全文搜索。

    更多帮助请参考: OnceDB Node.JS 客户端使用帮助

    10 replies    2020-03-12 09:19:16 +08:00
    JG
        1
    JG  
       Feb 27, 2020
    源码只开源了个 README,楼主是做嵌入式设备的?如果要在 arm 上用 redis 做持久化目前自带的持久化功能存 TF 卡上性能能接受吗?还是用的什么其他数据库做的持久化?
    itskingname
        2
    itskingname  
       Feb 27, 2020
    NoSQL 的语法分明比 SQL 好用得多易读易写,楼主非要让 SQL 进来插一脚。
    newghost
        3
    newghost  
    OP
       Feb 27, 2020
    @JG

    性能可以,Web 使用的也是全缓存的架构, 持久化时没有感觉,对性能无影响。
    newghost
        4
    newghost  
    OP
       Feb 27, 2020
    @itskingname

    指令只是借鉴了一下 sql 的写法,并不是真的 SQL,底层指令 Redis 原来的命令协议一样。驱动层跟 NoSQL 差不多。
    dk7952638
        5
    dk7952638  
       Feb 27, 2020
    有点厉害,战略性 star 一下,期待以后能开源
    itskingname
        6
    itskingname  
       Feb 27, 2020
    @newghost 我的意思就是说,SQL 的这些语句写法,比 Redis 原来的命令可读性、易用性差。
    newghost
        7
    newghost  
    OP
       Feb 27, 2020
    @itskingname

    同意,我们也只是在命令名称上参考了一下,本质完全不同
    newghost
        8
    newghost  
    OP
       Feb 27, 2020
    @dk7952638

    以后可能会开源
    4IoNut698v3Xgc2p
        9
    4IoNut698v3Xgc2p  
       Mar 11, 2020
    强烈支持,大概看了下官网,准备过两天深度测试下企业这个,目前有一个疑问:打印出库的支持自定义尺寸么?毕竟有个公司可能用 A4,而也有很多打 3 联那种横版。
    newghost
        10
    newghost  
    OP
       Mar 12, 2020
    @praming

    你说提报表组件? 目前只支持自宝义尺寸,还不支持连打。
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   5120 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 91ms · UTC 05:59 · PVG 13:59 · LAX 22:59 · JFK 01:59
    ♥ Do have faith in what you're doing.