V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
tctc4869
V2EX  ›  Java

在本地用内存数据库,除了 hashMap,还有哪些内存数据库方案?

  •  
  •   tctc4869 · 2019-11-20 09:25:18 +08:00 · 8177 次点击
    这是一个创建于 1609 天前的主题,其中的信息可能已经有所发展或是发生改变。

    目前主要是在单个服务器上使用,暂不考虑 redis 这种比较复杂面向分布式集群的内存数据库,首先是性能优先。我听说 HashMap,如果用字符串做 key,似乎会有 Hash 值重复的可能?

    在 Spring 容器启动时会读取数据库的一些数据,并会永久地驻留在服务端的内存中。而另一些数据类型会有过期处理等,如果要用 kV 类型的内存数据库的话,有些数据类型,可能会用整型做 key,也可能会用字符串做 key,这两种方式不可避免

    第 1 条附言  ·  2019-11-20 11:17:35 +08:00
    有怎么多人推荐 redis,但是我想要的是能在 java 中,直接能通过 new 的方式进行配置的缓存库框架,例如使用静态的 HashMap 作为缓存库,但 HashMap 功能太单一了,我也知道 redis,但在 redis 配置的方式相对于 new 配置方式有点麻烦,已经有人推荐了 guava,caffeine,这两种我稍微查了一下资料,可以直接在 java 中以 new 的方式创建,并进行配置。
    44 条回复    2020-01-25 17:07:15 +08:00
    phantomzz
        1
    phantomzz  
       2019-11-20 09:32:32 +08:00   ❤️ 2
    knightdf
        2
    knightdf  
       2019-11-20 09:42:19 +08:00
    为啥 redis 不考虑?明明 redis 就是就是最适合你的,redis 单机集群都可以用
    hyl24
        3
    hyl24  
       2019-11-20 09:43:17 +08:00
    hash 冲突是必然存在的。建议好好学习一下 hashmap 原理。redis 也可以很简单呀单机使用没啥麻烦的。当然也可以选择 ehcache 或者 guava 的缓存 都是 java 进程内的缓存。。。。其次好像没有什么东西是可以永久存在内存中的吧。系统重启都需要从持久化到磁盘的数据恢复到内存的,不然也是内存预热重新加载进去的。
    tusik
        4
    tusik  
       2019-11-20 09:43:57 +08:00
    h2 也行,redis 单机也能跑得很好啊
    xmh51
        5
    xmh51  
       2019-11-20 09:45:06 +08:00
    hash 重复 不代表不能识别不同的 key 呀。hash map 保证 key 的唯一性
    changdy
        6
    changdy  
       2019-11-20 09:49:17 +08:00   ❤️ 1
    感觉楼主思路有点不清晰
    一方面追求性能 但是另外一方面对 内存 以及 hashmap 的模型并不清楚.
    其实读取数据+序列化反序列化的耗时在一套业务逻辑里面耗时是比较低的

    如果自己实现的话 一定要注意线程安全
    passerbytiny
        7
    passerbytiny  
       2019-11-20 09:55:55 +08:00   ❤️ 2
    你是不是对 数据库 这三个字的量级有误解?不管是 HashMap 还是 Key-Value,最多只能叫做(内存)数据,而不是(内存)数据库。
    Oracle (公司)有一款内存数据库,其他大型数据库厂商一般也都会有内存数据库,它们在操作方式上属于仅提供有限功能的标准关系型数据库,掏钱就能用。除此之外,Redis 是最入门的 NoSQL 型内存数据库了,入门到功能都不完全,需要搭配 Spring Data Redis 配套使用。
    woshiaha
        8
    woshiaha  
       2019-11-20 09:55:57 +08:00
    我听说 HashMap,如果用字符串做 key,似乎会有 Hash 值重复的可能?

    ------如果你 HashMap 都没整明白的话,还是直接用 redis 算了。。。。
    nnnToTnnn
        10
    nnnToTnnn  
       2019-11-20 09:59:17 +08:00
    ```
    static final int hash(Object key) {
    int h;
    return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }
    ```

    如果这还存在 hash 冲突,建议你去买张彩票,说真的。
    wysnylc
        11
    wysnylc  
       2019-11-20 10:00:27 +08:00
    apache 有 lru
    但是建议使用 redis
    zunceng
        12
    zunceng  
       2019-11-20 10:19:26 +08:00
    blotdb rocksdb 这种? 或者直接 sqlite
    crossoverJie
        13
    crossoverJie  
       2019-11-20 10:19:38 +08:00
    本地缓存配合 Redis 使用也很常见,推荐使用 Google 的 Guava 库,各种缓存特性都有。
    tctc4869
        14
    tctc4869  
    OP
       2019-11-20 10:30:23 +08:00
    @passerbytiny 内存数据库不就是缓存库的一种称呼吗?
    你就这么纠结“数据库”这个三个字的文字概念吗,“不管是 HashMap 还是 Key-Value,最多只能叫做(内存)数据,而不是(内存)数据库。”,HashMap 在你眼里只能叫数据,key-value 只能叫数据?那 leveldb 这种持久化的 kv 数据库在你眼里就不是数据库了,叫数据文件是吧,你的意思是瞧不起持久化的 kv 数据库吗,那 sqlite 这种也不是数据库,是数据文件对吧。文字游戏好玩吗。

    redis 数据库有缓存库功能,也有持久化功能,那它就不是内存数据库?或者不是磁盘数据库了?你纠结文字概念干嘛,分的清楚就可以。我是来问怎么选缓存库方案的,不是来玩文字概念游戏的。内存数据库的合适称呼是叫缓存库,谁不知道?与之不同的是磁盘数据库,网上叫来叫去都说成约定俗成了,我用"内存数据库"这个词不行吗。
    newtype0092
        15
    newtype0092  
       2019-11-20 10:30:32 +08:00
    要达到你的要求我一时还真想不到比 redis 更简单更高效的东西了。。。
    打开 redis 官网第一段话的介绍,只有最后一句提到了通过集群方式可以提供一些高可用特性,“面向分布式集群”是你自己给自己加戏~
    haoz1w0w
        16
    haoz1w0w  
       2019-11-20 10:31:35 +08:00   ❤️ 1
    @nnnToTnnn #10 肯定会存在 hash 冲突的 否则 hashmap 为什么要挂个链表呢?
    yuikns
        17
    yuikns  
       2019-11-20 10:38:59 +08:00   ❤️ 1
    我寻思楼主就是想要一个基于 Java 的 embedded cache solution

    guava 有个 CacheBuilder 似乎就是你想要的? https://github.com/google//wiki/CachesExplained
    yuikns
        18
    yuikns  
       2019-11-20 10:44:33 +08:00
    passerbytiny
        19
    passerbytiny  
       2019-11-20 10:46:28 +08:00
    @tctc4869 #13 拜拜
    tctc4869
        20
    tctc4869  
    OP
       2019-11-20 11:07:44 +08:00
    @newtype0092 我目前其实并不想要具备的持久化功能的缓存库,而且不是 xml 中配置,是直接在 java 通过静态字段的 new 的方式,直接以 new 或创建为配置的那种,然后用封装一下,例如用静态的 hashMap 作为一个缓存库,但静态的 hashmap 功能有点少。redis 配置有点麻烦,而且关乎于端口和 ip,楼上有人推荐 guava,caffeine 这两种的话比较符合,可以直接在 java 中通过静态字段的进行 new 创建的方式进行配置。毕竟不同的缓存功能要对应不用的数据类型,简单可以直接有 hashmap,有些还得具备的简单的关系数据功能。
    boyhailong
        21
    boyhailong  
       2019-11-20 11:08:26 +08:00
    单机使用的内存数据库还是本地缓存?
    单机 redis 的确是最优解,具体的过期需求可以设置,占用总内存也可以设置,单机还是集群可配置,是否存储落地也可配置,搜“AOF 和 RDB 禁止持久化”。你能想到的关于内存数据库的使用场景,redis 开发者都想到了,蟹蟹
    skypyb
        22
    skypyb  
       2019-11-20 11:52:59 +08:00 via Android
    redis 还配置麻烦?你在这发帖的几十分钟里够配置十来个集成 redis 的 spring 项目了。
    sunjiayao
        23
    sunjiayao  
       2019-11-20 12:12:40 +08:00
    楼上 guava 正解
    fengpan567
        24
    fengpan567  
       2019-11-20 12:26:29 +08:00
    ehcache
    kayv
        25
    kayv  
       2019-11-20 12:39:06 +08:00
    ehcache 或者 google guava 都可以。如果缓存不需要失效,直接上 Map
    zhuangzhuang1988
        26
    zhuangzhuang1988  
       2019-11-20 13:17:38 +08:00
    nnnToTnnn
        27
    nnnToTnnn  
       2019-11-20 13:28:10 +08:00
    @haoz1w0w 是存在理论上的 hash 碰撞,这个 hash 碰撞还不如 md5 的 hash 碰撞明显,如果真的存在 hash 碰撞了,你的机器内存也并不足够支撑你的数据存储。 如果你觉得这样不保险。还可以继续加盐值,但是我觉得没有必要了。

    你可以参考下 md5 的 hash 碰撞需要多大的数据量
    nnnToTnnn
        28
    nnnToTnnn  
       2019-11-20 13:38:42 +08:00
    准确的说,这个 hash 碰撞,不如 md5 16 的明显,在 md5 32 中加大的盐值,减少了碰撞几率。

    理论 hashmap 的 key 字节大小相差特别大,才能可能遇到 hash 碰撞。

    我实在是不明白,什么样的情况下你的 key 会大到产生 hash 冲突? 这让我很懵啊。
    Bromine0x23
        29
    Bromine0x23  
       2019-11-20 13:50:00 +08:00
    用 Redis 和 new 对象又不矛盾,spring-data-redis 就有对 redis 包装的容器类实现
    MyShoW
        30
    MyShoW  
       2019-11-20 14:08:48 +08:00
    redis+redisson 也可以考虑一下,直接操作对象,不用关心 redis 的存取
    haosamax
        31
    haosamax  
       2019-11-20 18:01:00 +08:00
    冲突的概率也太小了吧,就算冲突了又有什么关系呢
    sagaxu
        32
    sagaxu  
       2019-11-20 18:32:02 +08:00 via Android   ❤️ 1
    连 map 是啥都不知道的人,也来看不起内存 map 之王了?
    CoderGeek
        33
    CoderGeek  
       2019-11-20 20:38:56 +08:00
    guava Caffeine
    ErrorMan
        34
    ErrorMan  
       2019-11-20 20:43:50 +08:00
    内存型数据库 h2,可以嵌入 java
    hantsy
        35
    hantsy  
       2019-11-20 20:46:22 +08:00
    @tctc4869 Hazelcast , infinispan
    hzgit
        36
    hzgit  
       2019-11-20 21:21:43 +08:00
    比较主流的就是 guava cache 和 encache 了 ( ps. HashMap 并不是内存数据库哦)
    Raymon111111
        37
    Raymon111111  
       2019-11-20 21:28:36 +08:00
    ?

    如果你是为了解决 hash 冲突

    那应该是没有现成方案的
    zhady009
        38
    zhady009  
       2019-11-20 21:59:27 +08:00 via iPhone
    @MyShoW 这个最近在用 真的香
    areless
        39
    areless  
       2019-11-20 22:15:56 +08:00 via Android
    key md5 值建文件夹,把 val 写 key 的 md5 文件夹内的文件内,假若是 obj 序列化,json 分多文件,存到 linux 的 shm 里,这就是最简单的内存 kv 数据库了,以前称之为文本数据库。而且速度不会太慢。mysql 的慢是因为 sql~~~假设 sql 查询通过 gpu 去操作显存就没有像 cpu 去操作机械硬盘这种低速记录体的瓶颈。所以未来会回归 sql,淘汰掉 nosql 做前置缓存的。所以别研究怎么搞一个速度比舒马赫还快的 kv 或者 hashmap,研究一下怎么让正规的 sql 比拟 nosql 吧
    areless
        40
    areless  
       2019-11-20 22:26:29 +08:00 via Android
    sql 快了,那么构架就回归原始。现在像巫师一样的构架师~~~全文本外部索引用 es,kv 用 redis,存储用 mysql 或 pg 或等等等。http 请求负载,构架的重要胜于传统,胜于标准化。这是不合理的。用 sql like 快于 es,sql 内存表快于 redis,apache 常驻模式快于 nginx 才是标准化。
    wangyzj
        41
    wangyzj  
       2019-11-21 00:36:11 +08:00
    redis 已经很简单了把
    而且你能保证你自己做 hashmap 会比 redis 性能好么?
    你还得考虑种种问题情况
    johnnyho
        42
    johnnyho  
       2019-11-21 08:49:05 +08:00 via iPhone   ❤️ 1
    楼主感觉就是懂得比较少,又要嘴硬那种存在…虚心接受指导不好吗
    betajun
        43
    betajun  
       2019-12-23 16:43:18 +08:00
    现在线上使用的 guava 做 jvm 内缓存来兜底,没有出现过什么问题。但是你需要预估一下你的数据量,数据量太大造成频繁 gc。
    Jacky23333
        44
    Jacky23333  
       2020-01-25 17:07:15 +08:00 via Android
    楼主不是科班出身吗,没学过数据结构😓,不管你用什么类型做 key 也肯定会出现 Hash 冲突的呀
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   992 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 35ms · UTC 20:14 · PVG 04:14 · LAX 13:14 · JFK 16:14
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.