当前位置: 首页 > 科技观察

基于SpringCloud+ApacheIgnite的Redis备份方案实例教程

时间:2023-03-16 22:18:51 科技观察

1.ApacheIgnite1。ApacheIgnite是一个分布式数据库,支持以内存级速度进行高性能计算。Ignite支持的编程语言主要包括:Java、.NET、C#和C++,其中Java版本对应的API最为丰富。二、应用场景现在最主流的分布式数据库应该是Redis了。但是在某些情况下,我们的项目可能无法使用Redis进行开发。例如:由于Redis底层是用C语言实现的,而Ignite底层是用Java语言实现的,如果我们公司的云环境不支持C语言环境,就无法部署Redis。此时,我们可以考虑使用Ignite作为Redis的替代品。与Redis相比,Ignite还具有较高的计算效率,因为它也是一个内存数据库,并且还支持Redis的Key-Value存储形式。Ignite中缓存的Key和Value是Object类型的对象,比Redis更灵活,可以支持更多的用户自定义数据类型,而Redis受限于它提供的数据,如String、Hash、Set类型。Ignite除了具有类似的K-V缓存结构外,与Redis相比还有很多优势。例如:Ignite完全兼容JCache缓存规范,但Redis不支持。Ignite完全支持ACID事务,而Redis只能提供部分支持。Ignite支持完全缓存数据。Redis不支持复制。二、Ignite的简单部署本章以主流的JavaMaven项目为例,说明Ignite的简单部署和使用。1.引入到Maven项目中,Ignite的部署非常简单,不需要单独下载安装包然后通过终端命令行启动节点。你只需要在项目的pom.xml中添加Ignite的依赖坐标就可以成功引入它的实现。org.apache.igniteignite-core2.12.0org.apache.igniteignite-spring2.12.0/dependency>值得注意的是,如果项目或子项目的pom.xml文件引用了h2内存数据库相关依赖,那么它的版本一定要覆盖为2.14.197,否则Ignite会报启动错误,因为Ignite的jar包中引入的h2版本为2.14.197,如果不一致会造成版本冲突,导致Ignite节点无法启动。2、服务器端代码首先,在创建Ignite节点之前,我们需要创建一个IgniteConfiguration类型的Ignite配置对象。IgniteConfiguration可以在我们创建的Ignite节点上进行一些自定义配置。其中,最基本的配置就是设置当前Ignite服务器节点(self)连接的IP地址。Ignite节点之间的网络通信主要通过TCP协议实现,其默认端口为47500。Ignite的服务发现机制(SPI)主要通过TcpDiscoverySpi类的对象实现。我们通过调用其setIpFinder方法为TcpDiscoverySpi设置一个IP查找器。TcpDiscoveryVmIpFinder是一个静态IP发现器,它可以指定一组IP地址和端口,IP发现器将检查这些IP地址和端口以进行节点发现。一旦与提供的任何IP地址建立连接,Ignite将自动发现所有其他节点。Ignite节点的启动由Ignition.start方法触发,Ignite节点配置完成后可以调用该方法启动Ignite节点。在启动时,Ignite会将节点分配为服务器节点或客户端节点。如果未设置,Ignite节点将自动作为服务器节点启动。publicclassIgniteServerApplication{publicstaticvoidmain(String[]args){//1.创建Ignite配置IgniteConfigurationcfg=newIgniteConfiguration();//2.创建一个基于TCP的Spi对象,用于发现其他Ignite实例TcpDiscoverySpidiscoverySpi=newTcpDiscoverySpi();//3.创建IP发现器TcpDiscoveryVmIpFinderipFinder=newTcpDiscoveryVmIpFinder();ipFinder.setAddresses(Collections.singleton("127.0.0.1:47500"));//设置IP地址discoverySpi.setIpFinder(ipFinder);//设置IP发现cfg.setDiscoverySpi(discoverySpi);//设置Spi"表示Ignite节点启动成功,“servers=1,clients=0”表示当前有1个server节点,0个client节点3.客户端代码Ignite客户端节点的启动和server节点的代码几乎一样。由于Ignite节点默认以server模式启动,所以只需要手动将Ignite设置为client节点即可。上图中,IgniteConfiguration的setClientMode(true)方法可以显式的让Ignite节点以客户端模式启动。上图中“servers=1,clients=1”表示当前有1个server节点和1个client节点。3.Ignite集群通过简单的Java程序实例说明了Ignite服务器节点和客户端节点的部署和连接之后,简单介绍了Ignite的集群特性。1.Ignite节点Ignite节点可以分为两种类型:服务器节点和客户端节点。服务器节点是Ignite集群的主体,主要功能是存储数据和执行计算任务,而客户端节点只是作为普通节点加入集群,并不存储数据。Ignite节点可以通过其配置的SPI(ServiceProviderInterface,服务发现机制)自动发现彼此并形成集群。根据不同的应用场景,Ignite的SPI主要包括两种类型:TCP/IP发现和ZooKeeper发现。通常使用较多的是TCP/IP机制,节点之间通过DiscoverySpi相互发现。DiscoverySpi的默认实现是TcpDiscoverySpi,可以配置为基于组播的IP发现或基于静态的IP发现模式(2.2和2.3节中的TcpDiscoveryVmIpFinder)。2.基于组播和静态IP发现与TcpDiscoveryVmIpFinder不同,TcpDiscoveryMulticastIpFinder使用组播来发现每个节点,这也是默认的IP发现者。如下图所示,两种IP发现方式在编码实现上几乎没有区别,只是需要改变新的ipFinder类型。TcpDiscoveryMulticastIpFinder还可以同时实现基于组播和静态IP发现,通过setMulticastGroup方法从组播中接收IP地址,通过setAddress处理预定义的静态IP地址。3、基于JDBC的IP发现通常我们本地开发可以使用组播或者静态IP发现,但是公司项目一般部署在云环境,IP地址不能保证固定,可能会因为容器故障或者重启其他不可控原因,则3.2节的IP发现方式将失效。Ignite为这种类似的应用场景提供了一个非常方便的SPI:基于JDBC数据库的IP发现机制。下面以一个简单的例子来介绍。服务器程序与2.2和2.3节的服务器程序的区别在于,IpFinder的类型不再是TcpDiscoveryVmIpFinder(基于静态IP)或TcpDiscoveryMulticastIpFinder(基于组播IP),而是TcpDiscoveryJdbcIpFinder。上图中的Ignite服务器程序使用了基于JDBC的IP发现。此时ipFinder不再通过调用setAddress方法设置IP地址,而是通过setDataSource设置一个JDBC数据源。因此,我们首先需要创建一个MysqlDataSource类的MySQL数据源对象,通过它的setURL、setUser和setPassword方法设置数据源的URL地址、用户名和密码,然后作为参数传递给TcpDiscoveryJdbcIpFinder.setDataSource。客户端程序和服务端几乎相同,如2.3节所述,唯一的区别是客户端程序员需要显式调用IgniteConfiguration.setClientMode(true)方法以客户端模式启动Ignite节点。4.Ignite缓存在简单了解了Ignite的简单部署和Ignite集群的相关特性之后,我们将通过一些简单的例子来说明Ignite缓存。1.IgniteCacheIgnite的所有缓存都是IgniteCache类型。其实K是缓存的key,V是缓存的value,分别对应Redis中的key和value。IgniteCache继承了javax包下的Cache接口,所以上面说了Ignite支持JCache规范。2、创建缓存在上一篇文章中,由于只是简单启动了Ignite节点,没有进行缓存操作,所以没有获取到Ignition.start的返回值。当我们要进行缓存相关操作时,需要获取start方法返回的Ignite实例,通过调用实例对象来实现缓存相关操作。如下图所示,可以通过creatCache或者getOrCreateCache获取IgniteCache类型的缓存对象。如方法名所示,creatCache直接创建缓存,getOrCreateCache先获取缓存,不存在则创建缓存。调用createCache时,如果缓存已经存在,则创建失败。具体判断缓存是否存在,是根据缓存的名称来判断的。每个IgniteCache都有一个缓存名称CacheName,我们传入的字符串s会作为cacheName。创建缓存实例。除了字符串,创建缓存时的参数还可以是CacheConfiguration类型的对象,其K和V代表缓存的Key和Value的类型。CacheConfiguration的setName方法可以设置Ignite缓存的名字,相当于createCache(Strings),所以如果像下图这样创建缓存,创建会失败,因为两个缓存的名字都叫“name”.启动Ignite客户端程序,IDEA控制台输出如下错误。可以看出Ignite是通过缓存的name字段来判断缓存是否冲突的。3、获取缓存获取缓存的方法主要有两种:4.2节中的Ignite.cache和Ignite.getOrCreateCache。cache(Strings)方法的参数是缓存的名称,getOrCreateCache的参数可以是String类型的缓存名称,也可以是CacheConfiguration的缓存配置。值得注意的是,缓存必须已经存在,否则会引发异常。Java示例代码:IDEA控制台输出结果如下。从图中我们也可以知道,IgniteCache接口的具体实现类是GatewayProtectedCacheProxy类型的实例对象。4.销毁缓存销毁Ignite缓存的方式也有两种,通过Ignite的destroyCache或者IgniteCache的destroy方法。Java示例代码:IDEA控制台输出结果如下:5.写入数据到缓存Ignite缓存写入主要是通过put方法实现的,key和value都是Object对象,可以是Java原生对象也可以是自定义的类目的。此外,还可以通过putAll一次性存储多个键值对。后缀为Async的方法是异步实现的,带有IfAbsent的方法表示数据不存在时存储,getAndPut会获取写入的缓存数据。6、从缓存中读取数据Ignite缓存主要是通过get方法读取数据,通过传入key获取value。另外,也可以通过getAll传入一个keySet集合,一次性得到Set集合中所有key对应的多个key-value键值对。Java示例代码:IDEA控制台输出如下:五、基于SpringCloud的实例教学在对Ignite的部署、集群、缓存等基本操作有了一定的了解后,我们通过SpringCloud微服务实现一个Redis的Ignite模拟小项目案例加深读者对Ignite应用的理解。由于Ignite缓存是Object类型的,我们通过定义一个常量类型作为缓存名称来对缓存进行分类。比如String类型缓存传入的缓存名称是String,Hash类缓存传入的cacheName是Hash。1、模拟Redis-String缓存对于String类型的数据结构,Redis的主要方法和对应的命令如下:(1)添加/修改数据集键值(2)获取数据获取键(3)删除数据delkey(4)添加/修改多条数据msetkey1value1key2value2...(5)获取多条数据mgetkey1key2...(6)获取数据字符数(字符串长度)strlenkey(7)追加信息到最后(如果不存在则新建一个)appendkeyvalue2。Redis-Hash缓存模拟对于Hash类型的数据结构,Redis的主要方法和对应命令如下:(1)添加/修改数据hset键字段值(2)获取单个数据hget键字段(3)获取所有datahgetallkey(4)删除数据hdelkeyfield1field2...(5)添加/修改多个数据hmsetkeyfield1value1field2value2...(6)获取多个数据hmgetkeyfield1field2...(7)获取哈希表中的字段数hlenkey(8)获取哈希表中是否存在指定字段hexistskeyfield3.Redis-List缓存模拟对于List类型的数据结构,主要是Redis方法及对应的命令如下:(1)添加数据lpush/rpushkeyvalue1value2...(2)获取和移除数据lpop/rpopkey(3)获取指定范围内的数据lrangekeystartend(4)获取指定位置的数据lindexkeyindex(5)获取数据llenkey的个数4.Redis-Set缓存的模拟对于Set类型的数据结构,主要mRedis的方法和对应命令如下:(1)添加数据saddkeymember1member2...(2)获取所有数据smemberskey(3)删除数据sremkeymember1member2...(4)获取总量collectiondatascardkey(5)判断集合中是否包含指定的datasmemberkeymember5.服务端程序不需要使用micro服务的注册只需要通过普通Java类的main方法调用即可表单启动6.客户端程序首先,我们需要在客户端程序中创建一个DataSource配置bean,作为Ignite客户端节点通过JDBC连接时需要的构造参数。其次,创建一个Controller,使用init方法初始化Ignite客户端。当容器启动时,会自动创建一个Ignite实例,并作为Bean注入到上面5.1-5.4节的Ignite工具类Bean中。7.测试最后我们写几个简单的测试方法进行测试。(1)String类型测试启动Ignite服务端程序EurekaServer和EurekaConsumer后,输入url:localhost:8080/ignite/string进行测试,观察浏览器输出:IDEA控制台输出:(2)Hash类型测试在输入url:localhost:8080/ignite/hash进行测试,观察浏览器输出:IDEA控制台输出:(3)List类型测试在url中输入:localhost:8080/ignite/hash进行测试,观察浏览器输出:IDEA控制台输出:(4)set类型测试在url输入:localhost:8080/ignite/set进行测试,观察浏览器输出:IDEA控制台输出:以上是ApacheIgnite的简单入门案例,感谢阅读。笔者介绍的是中国农业银行股份有限公司研发中心软件研发工程师孙俊辉,擅长Java开发。