优秀的编程知识分享平台

网站首页 > 技术文章 正文

Hazelcast vs Redis

nanyue 2024-11-27 18:17:05 技术文章 5 ℃


背景

由于其基础架构和多年的优化,Hazelcast非常快,并且显着优于Redis Labs(和Redis开源),特别是在规模上。虽然Radis有很令人难忘的特性,但是它也有一个严重的限制–它是为了单机模式设计的。如果用户需要超过单机的能力,就需要使用专用分区系统。不过3.0.0版本发布了一种集群系统产品,可以从根本上简化分布式Redis部署。所有人都认可Radis很快,我们来看看Hazelcast和Redis的比较


Hazelcast

介绍

Hazelcast 是由Hazelcast公司开发和维护的开源产品,可以为基于jvm环境运行的各种应用提供分布式集群和分布式缓存服务。Hazelcast可以嵌入到任何使用Java、C++、.NET开发的产品中(C++、.NET只提供客户端接入)。hazelcast支持分布式队列,集合,map,线程池,锁,支持事务处理,分布式的监听和事件,支持动态增加集群节点,动态备份 数据,动态failover,使用起来非常简单,速度非常快,每秒操作数可达到几千次。需要依赖的包非常小,不足1M,执行的效率非常高效,对CPU和内 存很友好。

特点

  • 支持多种数据结构:Hazelcast 支持使用多种数据结构以及 Map。
  • Fast R/W access :鉴于所有数据都在内存中,Hazelcast 提供非常高速的数据读/写访问。
  • 高可用性: Hazelcast 支持跨机器分发数据以及额外的备份支持。这意味着数据不是存储在一台机器上。因此,即使在分布式环境中频繁发生的机器宕机,数据也不会丢失。
  • 高性能: Hazelcast 提供了可用于在多个工作机器之间分配工作负载/计算/查询的构造。这意味着计算/查询使用来自多台机器的资源,这大大减少了执行时间。
  • 易于使用: Hazelcast 实现并扩展了许多 java.util.concurrent 结构,这使得它非常易于使用和与代码集成。在机器上开始使用 Hazelcast 的配置只需要将 Hazelcast jar 添加到我们的类路径中。
  • 发布订阅:Hazelcast支持通过主题进行消息的可靠分发


数据结构

Hazelcast提供了很多通用数据结构的分布式实现。针对每一种不同的客户端语言,Hazelcast都尽量模拟该语言原生接口,Hazelcast 提供了 Map、Queue、MultiMap、Set、List、Semaphore、Atomic 等常用接口的分布式实现。 所有这些结构都可以在Java、.NET,C ++,Node.js,Python,Go和Scala客户端中使用。基于分区策略,Hazelcast有两种类型的分布式数据结构:分区数据结构和非分区数据结构,分区数据结构一个分区只保存部分数据,非分区数据结构一个分区保存全部的数据。

类型

描述

分区

标准集合

Map

java.util.Map 的分布式实现。

支持

Queue

java.util.concurrent.BlockingQueue 的分布式实现。

不支持

Ringbuffer

Java中没有对应的数据结构,Ringbuffer通常用于可靠的事件系统。

不支持

Set

java.util.Set 的分布式并发实现

不支持

List

java.util.List 的分布式并发实现,支持存储重复元素,这是和Set的唯一区别。

不支持

Multimap

com.google.common.collect.Multimap 的分布式实现,支持存储重复键。

支持

Replicated Map

不支持分区的Map数据结构,集群所有成员都有全量数据

不支持

Cardinality Estimator

实现了lajolet’s HyperLogLog 算法的数据结构

不支持

并发工具

FencedLock

java 中 java.util.concurrent.locks.Lock的分布式实现,可以保证集群中只有一个线程可以获得锁

不支持

ISemaphore

java中 java.util.concurrent.Semaphore的分布式实现

不支持

IAtomicLong

java中 java.util.concurrent.atomic.AtomicLong的分布式实现

不支持

IAtomicReference

Java中java.util.concurrent.atomic.AtomicReference的分布式实现

不支持

FlakeIdGenerator

用于生产集群范围内的唯一标识符

不支持

ICountdownLatch

Java中 java.util.concurrent.CountDownLatch的分布式实现

不支持

PN counter

一个分布式数据结构,其中每个Hazelcast实例都可以递增和递减计数器值,并将这些更新传播到所有副本

不支持

Event Journal

是一种分布式数据结构,用于存储map或缓存上操作的历史记录

支持


持久化

由于Hazelcast 服务之间是端对端的,没有主从之分,集群中所有的节点都存储等量的数据以及进行等量的计算。Hazelcast 默认情况下把数据存储在 271 个区上,这个值可以通过系统属性 hazelcast.partition.count来配置对于一个给定的键,在经过序列化、哈希并对分区总数取模之后能得到此键对应的分区号,所有的分区等量的分布与集群中所有的节点中,每个分区对应的备份也同样分布在集群中。也就是说 Hazelcast 会使用哈希算法对数据进行分区,比如对于一个给定的map中的键,或者topic和list中的对象名称,分区存储的过程如下:

  • 先序列化此键或对象名称,得到一个byte数组;
  • 然后对上面得到的byte数组进行哈希运算;
  • 再进行取模后的值即为分区号;
  • 最后每个节点维护一个分区表,存储着分区号与节点之间的对应关系,这样每个节点都知道如何获取数据。



序列化与反序列化使用 hazelcast 提供的 DataSerializable 或者 IdentifiedDataSerializable 接口通常能获得较好的性能,不过他们在使用上需要实现特定接口和服务器端配置。也可以使用 thrift 等序列化框架在连接到 hazelcast 的序列化 I/O 流上。Map 支持三种内存存储格式:OBJECT, BINARY, NATIVE; map 的 key 和 value 类型必须支持序列化,已支持网络传输和内存压缩。

  • OBJECT: 直接 java 对象,get 操作无需反序列化,得到的是对象的直接引用。与应用程序共享 jvm heap
  • BINARY: java 对象的二进制格式,需要序列化与反序列化操作。与应用程序共享 jvm heap
  • NATIVE: 使用 key / value 实现的序列化接口将对象存储在堆外内存或者从堆外内存读取;不与应用程序共享内存;

在数据量大的场景中,通常会使用 NATIVE 格式的存储数据,以减少应用程序 jvm gc 压力。


使用方式

hazelcast使用有两种方式,嵌入式和客户端服务器

  • 嵌入式: Hazelcast 服务器的 jar 包被导入到宿主应用程序中,服务器启动后缓存数据会被存在于各个宿主应用中,优点是可以更低延迟的数据访问。
  • 客户端服务器: Hazelcast 客户端的 jar 包被导入宿主应用程序中,服务器 jar 包独立运行于 JVM 中。优点是更容易调试以及有更可靠的性能,最重要的是有更好的扩展性。客户端/服务器部署模式的优点包括:可预测性高、可靠的Hazelcast服务、问题定位定界简单,更重要的是具备高可扩展性。在客户端/服务器模式下,当集群需要扩展时,只需添加或减少Hazelcast服务器节点。客户端和服务器的伸缩可以独立进行。如果既想拥有低延迟数据访问(内嵌部署模式),又想充分利用客户端/服务器模式的灵活扩展性,需要考虑将客户端部署在更靠近缓存的地方,并将客户端的热点数据缓存到客户端本地缓存中。


Redis

介绍

Remote DIctionary Server(Redis) 是一个由Salvatore Sanfilippo写的key-value存储系统,它是一个开源(BSD许可)的内存型数据存储系统,支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的AP以及丰富的数据结构,它可以用作数据库、缓存和消息中间件。并支持事务、发布订阅、lua脚本、lru驱动事件、过期机制、自动故障转移等多种功能,由于Redis 是用ANSI C编写的,可在大多数 POSIX 系统(如 Linux、*BSD 和 OS X)中运行,无需外部依赖。

特点

  • 内存数据库,速度快,也支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。
  • Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
  • Redis支持数据的备份,即master-slave模式的数据备份。
  • Redis的所有数据存储在内存中,对数据的更新将异步地保存到磁盘上。
  • 功能丰富。除了支持五种数据结构之外,还支持事务、流水线、发布/订阅、消息队列等功能。
  • (服务架构)支持高可用和分布式


数据结构

Redis 是一个内存键值key-value 数据库,且键值对数据保存在内存中,因此Redis基于内存的数据操作,其效率高,速度快;其中,Key是String类型,Redis 支持的 value 类型包括了 String、List 、 Hash 、 Set 、 Sorted Set 、BitMap等。Redis 能够之所以能够广泛地适用众多的业务场景,基于其多样化类型的value

类型

描述

String

基于SDS实现,适用于简单key-value存储、setnx key value实现分布式锁、计数器(原子性)、分布式全局唯一ID

List

按照元素进入List 的顺序进行排序的,遵循FIFO(先进先出)规则,一般使用在 排序统计以及简单的消息队列

Hash

是字符串key和字符串value之间的映射,十分适合用来表示一个对象信息 ,特点添加和删除操作复杂度都是O(1)

Set

是String 类型元素的无序集合,集合成员是唯一的,这就意味着集合中不能出现重复的数据。 基于哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)

Sorted Set

是Set的类型的升级, 不同的是每个元素都会关联一个 double 类型的分数,通过分数排序,可以范围查询

Redis Geo

将地球看作为近似为球体,基于GeoHash 将二维的经纬度转换成字符串,来实现位置的划分跟指定距离的查询。特点一般使用在跟位置有关的应用

HyperLogLog

是一种概率数据结构,它使用概率算法来统计集合的近似基数 , 错误率大概在0.81%。 当集合元素数量非常多时,它计算基数所需的空间总是固定的,而且还很小,适合使用做 UV 统计

BitMap

用一个比特位来映射某个元素的状态, 只有 0 和 1 两种状态,非常典型的二值状态,且其本身是用 String 类型作为底层数据结构实现的一种统计二值状态的数据类型 ,优势大量节省内存空间,可是使用在二值统计场景




持久化

redis 提供了两种持久化的方式,分别是RDB(Redis DataBase)和AOF(Append Only File)。

  • RDB,简而言之,就是在不同的时间点,将 redis 存储的数据生成快照并存储到磁盘等介质上
  • AOF,则是换了一个角度来实现持久化,那就是将 redis 执行过的所有写指令记录下来,在下次 redis 重新启动时,只要把这些写指令从前到后再重复执行一遍,就可以实现数据恢复了

其实 RDB 和 AOF 两种方式也可以同时使用,在这种情况下,如果 redis 重启的话,则会优先采用 AOF 方式来进行数据恢复,这是因为 AOF 方式的数据恢复完整度更高。如果你没有数据持久化的需求,也完全可以关闭 RDB 和 AOF 方式,这样的话,redis 将变成一个纯内存数据库,就像 memcache 一样。


集群管理

Redis在3.0版本以后开始支持集群,经过中间几个版本的不断更新优化,最新的版本集群功能已经非常完善,Redis 集群是一个提供在多个Redis间节点间共享数据的程序集,集群节点共同构建了一个去中心化的网络,集群中的每个节点拥有平等的身份,节点各自保存各自的数据和集群状态。节点之间采用Gossip协议进行通信,保证了节点状态的信息同步。Redis 集群数据通过分区来进行管理,每个节点保存集群数据的一个子集。数据的分配采用一种叫做哈希槽(hash slot)的方式来分配,和传统的一致性哈希不太相同。Redis 集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽。为了使在部分节点失败或者大部分节点无法通信的情况下集群仍然可用,集群使用了主从复制模型。读取数据时,根据一致性哈希算法到对应的 master 节点获取数据,如果master 挂掉之后,会启动一个对应的 salve 节点来充当 master 。在redis3.0以前的版本要实现集群一般是借助哨兵sentinel工具来监控master节点的状态,如果master节点异常,则会做主从切换,将某一台slave作为master,哨兵的配置略微复杂,并且性能和高可用性等各方面表现一般,特别是在主从切换的瞬间存在访问瞬断的情况,而且哨兵模式只有一个主节点对外提供服务,没法支持很高的并发,且单个主节点内存也不宜设置得过大,否则会导致持久化文件过大,影响数据恢复或主从同步的效率。


总结

在功能方面,Redis 和 Hazelcast 都非常相似。以下是 Hazelcast 在 Redis 区别:

  • Hazelcast从头开始为分布式环境构建与作为单机缓存开始的 Redis 不同,Hazelcast 从一开始就是为分布式环境构建的。Hazelcast 架构是性能的关键。它的多线程架构(Redis 是单线程的)、near-cache、pipelining等能力为客户提供了最高的吞吐量和最低的延迟。
  • Hazelcast 维护添加或删除集群节点非常简单,例如,添加节点是启动具有所需配置的节点的问题。删除节点需要简单地关闭节点。Hazelcast 会自动处理数据的分区等。对 Redis 进行相同的设置并执行上述操作需要更多的预防措施和手动操作。
  • Hazelcast支持故障转移,所需的资源更少, Redis 遵循主从方法,对于故障转移,Redis 需要额外的资源来设置Redis Sentinel。如果原始主节点出现故障,这些 Sentinel 节点负责将一个从节点提升为主节点。在 Hazelcast 中,所有节点都被平等对待,一个节点的故障会被其他节点检测到。因此,节点关闭的情况非常透明地处理,而且无需任何额外的监控服务器集。
  • Hazelcast 提供了简单分布式计算,还减少了在线数据传输。Redis 也支持这一点,但是,要实现这一点,需要了解 Lua 脚本,这会增加额外的学习曲线。

Tags:

最近发表
标签列表