geode教程

1. geode简介

Apache Geode是一个数据管理平台,可在广泛分布的允架构提供对数据密集型应用程序的实时、一致的访问。Geode跨多个进程汇集内存、CPU、网络资源和可选的本地磁盘,以及管理应用程序对象和行为。

它使用动态复制和数据分区技术来实现高可用性、改进的性能、可伸缩性和容错性。除了作为分布式数据容器之外,Geode还是一个内存数据管理系统,可提供可靠的异步事件通知和有保证的消息传递。(gemfire是它的商业版本)

1.1 主要组件

  • locator:locator定位器,类似于ZK,进行选举协调,服务发现等功能,我们应用程序链接的是locator定位器
  • server:真正提供缓存服务的功能
  • region: 对数据进行区域划分,类似数据库中表的概念
  • gfsh: Geode的命令行控制台
  • client:链接Geode服务的客户端

1.2 Geode特性

  • 高读写吞吐量

  • 低且可预测的延迟

  • 高可扩展性

  • 持续可用性

  • 可靠的事件通知

  • 数据存储上的并行应用程序行为

  • 无共享磁盘持久性

  • 降低拥有成本

  • 客户/服务器的单跳能力

  • 多站定数据分布

  • 连续查询

  • 异构数据共享

1.3 Geode 与 Redis

总体来说个体的的功能包含Redis的功能,但还是有一些差异点:

  1. 定位不同:Geode定位数据管理平台,强调实时一致性,Redis高速缓存
  1. 集群:Geode天然支持集群,节点是对等的,Redis集群去中心化,主从复制
  1. 部署方式:Geode有点对点方式、C/S方式、WAN多数据中心方式, Redis是C/S主从方式、集群方式
  1. 查询: Geode支持OQL查询、函数计算, Rdis支持KV查询
  1. 发布订阅:Geode支持稳定额事件订阅和连续查询,Redis的发布订阅使用不多
  1. 事务支持:Geode支持的也是村内存的ACID事务,对落盘的事务支持也不行,Redis支持的也是内存型事务
  1. Geode支持Redis协议模型,有Redis Adapter

1.4 应用场景

目前12306就是用Geode作为高性能分布式缓存计算框架。Apache Geode适用于各种需要处理大规模分布式数据的场景,以下是几个典型的应用场景:

  1. 实时分析系统:Geode的高性能和实时一致性特性使得它成为实时分析体系统的理想选择。例如:金融领域的股票交易分析、电商领域的用户行为分析等
  1. 缓存系统:由于Geode具有高性能和可扩展性,它可以用作缓存系统,为应用程序提供快速的数据访问。例如:在web应用中缓存用户会话数据或热点数据
  1. 分布式计算:Geode可以作为分布式计算框架的一部分,提供数据处理和存储的支持。例如:Hadoop生态中集成Geode作为存储后端或消息中间件。
  1. 事务处理系统:由于Geode提供了高可用性和容错性,它可以构建需要强一致性和高可用性和的事务处理系统。例如:在线支付系统或银行交易系统

2. 环境搭建

  1. 下载安装包

    1
    wget https://github.com/apache/geode/archive/v1.10.0.tar.gz

    或者访问 Apache Geode官网

    1
    2
    官网下载太慢了,放网盘!!!
    链接: https://pan.baidu.com/s/1qdD6Urr0cAJRs7U_YqRUbA 提取码: hssz
  2. 上传到指定目录

    1
    2
    3
    cd /opt/
    tar -xvf ./apache-geode-1.15.1.tar
    mv apache-geode-1.15.1 geode
  3. 添加环境变量

    1
    sudo vim /etc/profile

    在配置最下面添加:

    1
    export PATH=$PATH:/opt/geode/bin

    配置生效

    1
    source /etc/profile
  4. 启动locator

    它告诉一个新连接的成员其他正在运行的成员位置,并未服务器提供负载均衡,用于检测和管理geode集群

    1
    2
    3
    gfsh
    #等进入gfsh命令界面,输入以下命令
    start locator --name=locator1
  5. 启动pulse监控工具

    1
    2
    #启动pulse并自动连接到locator的JMX管理器
    start pulse

  6. 访问pulse登陆界面

    request
    1
    2
    3
    http://localhost:7070/pulse

    默认账户:admin admin

  7. 启动服务器server

    1
    start server -name=server1 -server-port=40411

    如果没有指定member名字,gfsh会自动随机生成一个member名字, 在Pulse中观察变化,查实扩展分布式系统,以图形方式查看定位器和缓存服务器

  1. 启动缓存服务器

    1
    start server --name=server1 --server-port=40411
  2. 创建一个被复制的持久的region

    1
    create region --name=regionA --type=REPLICATE_PERSISTENT
  3. 运行put命令向region中添加数据

    1
    put --region=regionA --key="1" --value="one"
  4. 查询region中的数据

    1
    query --query="select * from /regionA"

3. 代码工程

实现springboot对geode插入和查询操作

  1. 引入pom

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
    <artifactId>springboot-demo</artifactId>
    <groupId>com.et</groupId>
    <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>gemfire</artifactId>

    <properties>
    <maven.compiler.source>8</maven.compiler.source>
    <maven.compiler.target>8</maven.compiler.target>
    </properties>
    <dependencies>
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-autoconfigure</artifactId>
    </dependency>
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
    </dependency>
    <dependency>
    <groupId>org.springframework.geode</groupId>
    <artifactId>spring-geode-starter-session</artifactId>
    <version>1.4.13</version>
    </dependency>
    <dependency>
    <groupId>org.springframework.geode</groupId>
    <artifactId>spring-geode-starter-test</artifactId>
    <version>1.4.13</version>
    <scope>test</scope>
    </dependency>
    <dependency>
    <groupId>org.springframework.geode</groupId>
    <artifactId>spring-geode-starter</artifactId>
    <version>1.4.13</version>
    </dependency>
    </dependencies>

    </project>
  2. controller

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    import com.et.gemfire.entity.People;
    import com.et.gemfire.repository.PersonRepository;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.*;

    import java.util.HashMap;
    import java.util.Map;

    @RestController
    public class HelloWorldController {
    @RequestMapping("/hello")
    public Map<String, Object> showHelloWorld(){
    Map<String, Object> map = new HashMap<>();
    map.put("msg", "HelloWorld");
    return map;
    }
    @Autowired
    PersonRepository personRepository;

    @RequestMapping(value = "/findById", method = RequestMethod.GET)
    public Object findById(String id) {
    return personRepository.findById(id);
    }

    @RequestMapping(value = "/findAll", method = RequestMethod.GET)
    public Object findAll() {
    return personRepository.findAll();
    }

    @RequestMapping(value = "/insert", method = RequestMethod.POST)
    public Object insert(@RequestBody People bean) {
    personRepository.save(bean);
    return "add OK";
    }
    }
  1. respository
    1
    2
    3
    4
    5
    6
    import com.et.gemfire.entity.People;
    import org.springframework.data.repository.CrudRepository;
    import org.springframework.stereotype.Repository;

    @Repository
    public interface PersonRepository extends CrudRepository<People, String> {}
  1. entity

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    import org.springframework.data.annotation.Id;
    import org.springframework.data.gemfire.mapping.annotation.Region;

    import java.io.Serializable;

    @Region(value = "People")
    public class People implements Serializable {
    @Id
    private String name;
    private int age;

    public String getName() {
    return name;
    }

    public void setName(String name) {
    this.name = name;
    }

    public int getAge() {
    return age;
    }

    public void setAge(int age) {
    this.age = age;
    }
    }
  2. DemoApplication

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    import com.et.gemfire.entity.People;
    import org.apache.geode.cache.client.ClientRegionShortcut;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.data.gemfire.cache.config.EnableGemfireCaching;
    import org.springframework.data.gemfire.config.annotation.EnableCachingDefinedRegions;
    import org.springframework.data.gemfire.config.annotation.EnableEntityDefinedRegions;
    import org.springframework.data.gemfire.config.annotation.EnablePdx;

    @SpringBootApplication
    @EnableEntityDefinedRegions(basePackageClasses = People.class, clientRegionShortcut = ClientRegionShortcut.PROXY ) // 只是当代理转发的操作
    @EnablePdx
    @EnableCachingDefinedRegions
    @EnableGemfireCaching
    public class DemoApplication {

    public static void main(String[] args) {
    SpringApplication.run(DemoApplication.class, args);
    }
    }

4. 测试

  1. 启动springboot应用

  2. 测试插入

  3. 测试查询

5. Geode扩展

  1. 用gfsh命令来查看集群中的区域

    1
    list regions
  2. 列出集群上的成员

    1
    list memebers
  3. 查看区域说明

    1
    describe region --name=regionA