Infinispan篇(一):一个被遗忘了的分布式集群缓存系统

简介: Infinispan 是一个开源内存数据网格,提供灵活的部署选项和强大的数据存储、管理和处理功能。

一、前言

这几天在学习Keycloak,而Keycloak使用的缓存是Infinispan,今天就来排一下它。

二、Infinispan概述

Infinispan 是一个开源内存数据网格,提供灵活的部署选项和强大的数据存储、管理和处理功能。Infinispan提供了一个键/值数据存储,可以保存所有类型的数据,从Java对象到纯文本。Infinispan 将数据分布在弹性可扩展的集群中,以保证高可用性和容错能力,无论您将 Infinispan 用作易失性缓存还是持久性数据存储。

官方文档https://infinispan.org/documentation/

2.1 特点

2.2 部署模型

Infinispan有两种缓存部署模型,远程和嵌入式。与传统数据库系统相比,这两种部署模型都允许应用程序以显著降低的读取操作延迟和更高的写入操作吞吐量访问数据。

远程缓存: Infinispan Server 节点在专用的 Java 虚拟机 (JVM) 中运行。客户端使用 Hot Rod、二进制 TCP 协议或通过 HTTP 访问远程缓存。(Keycloak采用远程部署,通俗点讲就是Infinispan是独立部署的。)

嵌入式缓存: Infinispan 与 Java 应用程序在同一个 JVM 中运行,这意味着数据存储在执行代码的内存空间中。

三、二进制部署

https://downloads.jboss.org/infinispan/14.0.4.Final/infinispan-server-14.0.4.Final.zip

本次测试infinispan的版本为最新稳定版14.0.4.Final。

3.1 准备工作

#将infinispan-server-14.0.4.Final.zip解压
unzip infinispan-server-14.0.4.Final.zip

infinispan 从14版本开始jdk需要11以上,也适用于JDK 17,18和19。

3.2 启动

$ cd /infinispan-server-14.0.4.Final/bin下
$ nohup ./server.sh -b 0.0.0.0 &

3.3 登录infinispan Server Management Console

浏览器中输入http://ip:11222/

必须输入凭据才能访问控制台。创建用户名和密码以继续。

使用以下命令创建用户名和密码,如下

bin/cli.sh user create admin -p admin -g admin

用户名是admin,密码也是admin

四、Infinispan单机部署(容器化单节点)

4.1 镜像拉取

docker pull quay.io/infinispan/server:14.0.4.Final

请拉取官方镜像,https://quay.io/repository/infinispan/server?tab=tags

4.2 准备工作

自定义docker网络

### 预先创建一个自定义的网络pk_net,此处的10.139可以自定义,不冲突即可
$ sudo docker network create --driver bridge --subnet 10.139.0.0/16 --gateway 10.139.0.1 pk_net

编写docker-compose-infinispan.yaml文件,内容如下:

version: '3.7'
services:
  infinispan:
    image: quay.io/infinispan/server:14.0.4.Final
    container_name: infinispan-server
    hostname: infinispan-server
    restart: always
    privileged: true
    environment:
      USER: admin
      PASS: admin
      TZ: Asia/Shanghai
    volumes:
      - /data/infinispan/server/conf/infinispan.xml:/opt/infinispan/server/conf/infinispan.xml
      - /data/infinispan/server/data:/opt/infinispan/server/data
      - /data/infinispan/server/lib:/opt/infinispan/server/lib
      - /data/infinispan/server/log:/opt/infinispan/server/log
    ports:
      - "11222:11222"
    networks:
      - pk_net
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:11222/rest/v2/cache-managers/default/health/status"]
      interval: 30s
      timeout: 20s
      retries: 3
networks:
  pk_net:
    external: true

参数说明:

  • healthcheck表示健康探测。
  • http://localhost:11222/rest/v2/cache-managers/default/health/status是获取缓存管理器健康状态接口。
  • 挂载/data和/log需要在宿主机上更改权限,如:chmod -R 777 /data/infinispan/server/data

infinispan.xml内容如下:

<infinispan
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="urn:infinispan:config:14.0 https://infinispan.org/schemas/infinispan-config-14.0.xsd
                            urn:infinispan:server:14.0 https://infinispan.org/schemas/infinispan-server-14.0.xsd"
      xmlns="urn:infinispan:config:14.0"
      xmlns:server="urn:infinispan:server:14.0">
   <cache-container name="default" statistics="true">
      <transport cluster="${infinispan.cluster.name:cluster}" stack="${infinispan.cluster.stack:tcp}" node-name="${infinispan.node.name:}"/>
      <security>
         <authorization/>
      </security>
   </cache-container>
   <server xmlns="urn:infinispan:server:14.0">
      <interfaces>
         <interface name="public">
            <inet-address value="${infinispan.bind.address:127.0.0.1}"/>
         </interface>
      </interfaces>
      <socket-bindings default-interface="public" port-offset="${infinispan.socket.binding.port-offset:0}">
         <socket-binding name="default" port="${infinispan.bind.port:11222}"/>
         <socket-binding name="memcached" port="11221"/>
      </socket-bindings>
      <security>
         <credential-stores>
            <credential-store name="credentials" path="credentials.pfx">
               <clear-text-credential clear-text="secret"/>
            </credential-store>
         </credential-stores>
         <security-realms>
            <security-realm name="default">
               <!-- Uncomment to enable TLS on the realm -->
               <!-- server-identities>
                  <ssl>
                     <keystore path="application.keystore"
                               password="password" alias="server"
                               generate-self-signed-certificate-host="localhost"/>
                  </ssl>
               </server-identities-->
               <properties-realm groups-attribute="Roles">
                  <user-properties path="users.properties"/>
                  <group-properties path="groups.properties"/>
               </properties-realm>
            </security-realm>
         </security-realms>
      </security>
      <endpoints socket-binding="default" security-realm="default" />
   </server>
</infinispan>

这是从容器中拷贝出来的。

或者采用docker run命令,如下:

docker run --name infinispan -d -p 11222:11222 -e USER="admin" -e PASS="password" quay.io/infinispan/server:14.0.4.Final

注意有些最小化镜像版本是没有管理界面,请选择合适的镜像版本。

五、infinispan集群部署(二进制部署)

infinispan的集群部署相对简单,在多个主机上部署Infinispan Server,Infinispan会自动发现(多播功能)整个网络上找到所有Infinispan Server实例加入到集群里面。

若是主机上存在多个网卡时,启动时需要通过-k指定集群ip,如下启动命令:

nohup ./bin/server.sh -b 192.168.0.201 -k 192.168.0.201 &
或者
nohup ./bin/server.sh -b 0.0.0.0 -k 192.168.0.201 &

如下:

通过7800来进行集群交互。

六、infinispan集群部署(容器化部署)

前面我们收到infinispan会自动发现(多播功能)整个网络上找到所有Infinispan Server实例加入到集群里面,但是容器化的方式,其默认的集群ip是容器ip,若是不改变集群ip,其它主机节点上的infinispan服务是无法加入集群。

编写docker-compose-infinispan.yaml文件,内容如下:

version: '3.7'
services:
  infinispan:
    image: quay.io/infinispan/server:14.0.4.Final
    container_name: infinispan-server
    hostname: infinispan-server
    restart: always
    privileged: true
    #改变集群ip
    command: ["-k 192.168.0.201"]
    environment:
      USER: admin
      PASS: admin
      TZ: Asia/Shanghai
    volumes:
      - /mnt/data/infinispan-docker/server/conf/infinispan.xml:/opt/infinispan/server/conf/infinispan.xml
      - /mnt/data/infinispan-docker/server/data:/opt/infinispan/server/data
      - /mnt/data/infinispan-docker/server/lib:/opt/infinispan/server/lib
      - /mnt/data/infinispan-docker/server/log:/opt/infinispan/server/log
    ports:
      - "11222:11222"
      - "7800:7800"
    #使用宿主机网络
    network_mode: host
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:11222/rest/v2/cache-managers/default/health/status"]
      interval: 30s
      timeout: 20s
      retries: 3

需要通过-k 192.168.0.201去改变集群ip,通过查看infinispan的源码发现其实-k 等同于--cluster-address,所以可以写command: ["--cluster-address=192.168.0.201"]。

源码Bootstrap中handleArgumentCommand方法:

@Override
   protected void handleArgumentCommand(String command, String parameter, Iterator<String> args) {
      switch (command) {
         case "-c":
            parameter = args.next();
            // Fall through
         case "--server-config":
            configurationFiles.add(Paths.get(parameter));
            break;
         case "-l":
            parameter = args.next();
            // Fall through
         case "--logging-config":
            loggingFile = Paths.get(parameter);
            break;
         case "-s":
            parameter = args.next();
            // Fall through
         case "--server-root":
            serverRoot = new File(parameter);
            break;
         case "-b":
            parameter = args.next();
            // Fall through
         case "--bind-address":
            properties.setProperty(Server.INFINISPAN_BIND_ADDRESS, parameter);
            break;
         case "-p":
            parameter = args.next();
            // Fall through
         case "--bind-port":
            properties.setProperty(Server.INFINISPAN_BIND_PORT, parameter);
            break;
         case "-n":
            parameter = args.next();
         case "--node-name":
            properties.setProperty(Server.INFINISPAN_NODE_NAME, parameter);
            break;
         case "-g":
            parameter = args.next();
         case "--cluster-name":
            properties.setProperty(Server.INFINISPAN_CLUSTER_NAME, parameter);
            break;
         case "-j":
            parameter = args.next();
         case "--cluster-stack":
            properties.setProperty(Server.INFINISPAN_CLUSTER_STACK, parameter);
            break;
         case "-k":
            parameter = args.next();
         case "--cluster-address":
            properties.setProperty(Server.JGROUPS_BIND_ADDRESS, parameter);
            break;
         case "-o":
            parameter = args.next();
            // Fall through
         case "--port-offset":
            properties.setProperty(Server.INFINISPAN_PORT_OFFSET, parameter);
            int offset = Integer.parseInt(parameter);
            if (!properties.containsKey(Server.JGROUPS_BIND_PORT)) {
               properties.setProperty(Server.JGROUPS_BIND_PORT, Integer.toString(Server.DEFAULT_JGROUPS_BIND_PORT + offset));
            }
            break;
         case "-P":
            parameter = args.next();
         case "--properties":
            try (Reader r = Files.newBufferedReader(Paths.get(parameter))) {
               Properties loaded = new Properties();
               loaded.load(r);
               loaded.forEach(properties::putIfAbsent);
            } catch (IOException e) {
               throw new IllegalArgumentException(e);
            }
            break;
         default:
            throw new IllegalArgumentException(command);
      }
   }

依次对应如下集群设置:

public static final String INFINISPAN_BIND_ADDRESS = "infinispan.bind.address";
   public static final String INFINISPAN_BIND_PORT = "infinispan.bind.port";
   public static final String INFINISPAN_CLUSTER_NAME = "infinispan.cluster.name";
   public static final String INFINISPAN_CLUSTER_STACK = "infinispan.cluster.stack";
   public static final String INFINISPAN_NODE_NAME = "infinispan.node.name";
   public static final String INFINISPAN_PORT_OFFSET = "infinispan.socket.binding.port-offset";
   public static final String JGROUPS_BIND_ADDRESS = "jgroups.bind.address";
   public static final String JGROUPS_BIND_PORT = "jgroups.bind.port";

或者采用docker run命令,如下:

docker run --name infinispan -d -p 11222:11222 -p 7800:7800 --net=host  -e USER="admin" -e PASS="admin" quay.io/infinispan/server:14.0.4.Final -k 192.168.0.201

-k 192.168.0.201 等同于--cluster-address=192.168.0.201

如下:

通过7800来进行集群交互,通过-k去指定集群ip,若是不指定,拿到的就是本地ip,即容器ip, 这样infinispan自动发现是没办法发现其他主机上的infinispan节点的。

相关文章
|
30天前
|
消息中间件 缓存 NoSQL
Redis 是一个高性能的键值对存储系统,常用于缓存、消息队列和会话管理等场景。
【10月更文挑战第4天】Redis 是一个高性能的键值对存储系统,常用于缓存、消息队列和会话管理等场景。随着数据增长,有时需要将 Redis 数据导出以进行分析、备份或迁移。本文详细介绍几种导出方法:1)使用 Redis 命令与重定向;2)利用 Redis 的 RDB 和 AOF 持久化功能;3)借助第三方工具如 `redis-dump`。每种方法均附有示例代码,帮助你轻松完成数据导出任务。无论数据量大小,总有一款适合你。
67 6
|
12天前
|
缓存 Java Shell
Android 系统缓存扫描与清理方法分析
Android 系统缓存从原理探索到实现。
38 15
Android 系统缓存扫描与清理方法分析
|
6天前
|
存储 运维 负载均衡
构建高可用性GraphRAG系统:分布式部署与容错机制
【10月更文挑战第28天】作为一名数据科学家和系统架构师,我在构建和维护大规模分布式系统方面有着丰富的经验。最近,我负责了一个基于GraphRAG(Graph Retrieval-Augmented Generation)模型的项目,该模型用于构建一个高可用性的问答系统。在这个过程中,我深刻体会到分布式部署和容错机制的重要性。本文将详细介绍如何在生产环境中构建一个高可用性的GraphRAG系统,包括分布式部署方案、负载均衡、故障检测与恢复机制等方面的内容。
48 4
构建高可用性GraphRAG系统:分布式部署与容错机制
|
11天前
|
存储 分布式计算 负载均衡
分布式计算模型和集群计算模型的区别
【10月更文挑战第18天】分布式计算模型和集群计算模型各有特点和优势,在实际应用中需要根据具体的需求和条件选择合适的计算架构模式,以达到最佳的计算效果和性能。
31 2
|
25天前
|
消息中间件 中间件 数据库
NServiceBus:打造企业级服务总线的利器——深度解析这一面向消息中间件如何革新分布式应用开发与提升系统可靠性
【10月更文挑战第9天】NServiceBus 是一个面向消息的中间件,专为构建分布式应用程序设计,特别适用于企业级服务总线(ESB)。它通过消息队列实现服务间的解耦,提高系统的可扩展性和容错性。在 .NET 生态中,NServiceBus 提供了强大的功能,支持多种传输方式如 RabbitMQ 和 Azure Service Bus。通过异步消息传递模式,各组件可以独立运作,即使某部分出现故障也不会影响整体系统。 示例代码展示了如何使用 NServiceBus 发送和接收消息,简化了系统的设计和维护。
41 3
|
29天前
|
存储 缓存 分布式计算
大数据-89 Spark 集群 RDD 编程-高阶 编写代码、RDD依赖关系、RDD持久化/缓存
大数据-89 Spark 集群 RDD 编程-高阶 编写代码、RDD依赖关系、RDD持久化/缓存
41 4
|
30天前
|
存储 缓存 NoSQL
大数据-38 Redis 高并发下的分布式缓存 Redis简介 缓存场景 读写模式 旁路模式 穿透模式 缓存模式 基本概念等
大数据-38 Redis 高并发下的分布式缓存 Redis简介 缓存场景 读写模式 旁路模式 穿透模式 缓存模式 基本概念等
53 4
|
7天前
|
存储 监控 大数据
构建高可用性ClickHouse集群:从单节点到分布式
【10月更文挑战第26天】随着业务的不断增长,单一的数据存储解决方案可能无法满足日益增加的数据处理需求。在大数据时代,数据库的性能、可扩展性和稳定性成为企业关注的重点。ClickHouse 是一个用于联机分析处理(OLAP)的列式数据库管理系统(DBMS),以其卓越的查询性能和高吞吐量而闻名。本文将从我的个人角度出发,分享如何将单节点 ClickHouse 扩展为高可用性的分布式集群,以提升系统的稳定性和可靠性。
19 0
|
30天前
|
分布式计算 Hadoop
Hadoop-27 ZooKeeper集群 集群配置启动 3台云服务器 myid集群 zoo.cfg多节点配置 分布式协调框架 Leader Follower Observer
Hadoop-27 ZooKeeper集群 集群配置启动 3台云服务器 myid集群 zoo.cfg多节点配置 分布式协调框架 Leader Follower Observer
42 1
|
1月前
|
分布式计算 Hadoop 网络安全
Hadoop-08-HDFS集群 基础知识 命令行上机实操 hadoop fs 分布式文件系统 读写原理 读流程与写流程 基本语法上传下载拷贝移动文件
Hadoop-08-HDFS集群 基础知识 命令行上机实操 hadoop fs 分布式文件系统 读写原理 读流程与写流程 基本语法上传下载拷贝移动文件
28 1