- Install Java connector
- Install TDB images and tt cli
- Generate simple TDB application
- Run TDB and Redis
- Add TDB migration
- Generate simple maven project
- Add minimal spring application and Jshell script
- Build classpath to use it in Jshell
- Run Jshell with classpath
- Interact with Redis
- Change 3 files to use Tarantool instead of Redis
- Interact with Tarantool
Установить коннектор по инструкции.
Установить образы можно с customer_zone tarantool.io
tt cli можно установить с помощью стандартного пакетного менеджера:
# for linux with apt dep manager:
curl -L https://tarantool.io/release/3/installer.sh | bash && sudo apt-get install tt
# for macos:
brew install tttt init
# Скопируем шаблон tarantooldb
git clone git@gitlab:tarantool/tdb/tarantooldb.git
cp -r tarantooldb/templates/* templates
tt create tarantool_db --name myappЗапустим tdb шаблон:
cd myapp
make upЗапустим redis server:
# macos:
brew install redis
brew services start redis
# linux with apt dep manager:
sudo apt install redis-server
sudo systemctl start redis-serverЗайдите в TCM http://localhost:8081/cluster/migrations (admin, secret -- логин пароль по умолчанию).
Добавьте миграцию 0000002_person.lua в раздел migrations.
Спейс будет выглядит так же как в практике по синглинстанс тарантулу
local helpers = require('tt-migrations.helpers')
local function apply()
local space_name = 'person'
local space = box.schema.space.create(space_name, { if_not_exists = true })
space:format({
{'id', 'integer'},
{'name', 'string'},
{'createdAt', 'datetime'},
{'metadata', 'map', is_nullable = true},
{'bucket_id', 'unsigned'},
})
space:create_index('pk', { parts = {'id'}, if_not_exists = true})
space:create_index('bucket_id', { parts = {'bucket_id'}, unique = false, if_not_exists = true})
helpers.register_sharding_key(space_name, {'id'})
return true
end
return {
apply = {
scenario = apply,
}
}mvn archetype:generate -DgroupId=com.example -DartifactId=my-tarantool-app -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=falsecd my-tarantool-appДобавить минимальное приложение можно с помощью git патча:
git init
git add . && git commit -m "Init app"
wget https://gist.githubusercontent.com/ArtDu/d6e1a927a1841e9877777844d14eecc1/raw/37534655e5625eead8448baf560ab048217c0d45/diff.patch
git apply diff.patchЛибо можно пройтись ручками добавить 4 файла и 1 поменять:
Create/modify 5 files
Add deps to pom.xml:
bash
cat > pom.xml <<EOL
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>my-tarantool-app</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>my-tarantool-app</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>3.2.12</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>3.2.12</version>
</dependency>
<!-- <dependency>-->
<!-- <groupId>io.tarantool</groupId>-->
<!-- <artifactId>tarantool-spring-data-32</artifactId>-->
<!-- <version>1.2.1</version>-->
<!-- </dependency>-->
</dependencies>
</project>
EOL
exitЗачем нужна команда bash выше?
Если используется zsh то он экранирует символы xml для этого скрипта, поэтому bash нужен только для создания файла pom.xml с зависимостями выше.Add application.yaml to your redis/tarantool env
mkdir src/main/resources
cat > src/main/resources/application.yaml <<EOL
spring:
data:
redis:
host: localhost
port: 6379
tarantool:
host: localhost
port: 3301
EOLAdd Person POJO:
cat > src/main/java/com/example/Person.java <<EOL
package com.example;
//import com.fasterxml.jackson.annotation.JsonFormat;
//import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import org.springframework.data.annotation.Id;
import org.springframework.data.keyvalue.annotation.KeySpace;
import org.springframework.data.redis.core.RedisHash;
import org.springframework.data.redis.core.index.Indexed;
import java.time.Instant;
import java.util.Map;
//@JsonFormat(shape = JsonFormat.Shape.ARRAY)
//@JsonIgnoreProperties(ignoreUnknown = true) // for example bucket_id
@KeySpace("person")
@RedisHash("person")
public class Person {
@Id
public Integer id;
@Indexed
public String name;
public Instant createdAt;
public Map metadata;
public Person(Integer id, String name, Instant createdAt, Map metadata) {
this.id = id;
this.name = name;
this.createdAt = createdAt;
this.metadata = metadata;
}
public Person() {
}
@Override
public String toString() {
return "Person{" +
"id=" + id +
", name='" + name + '\'' +
", createdAt=" + createdAt +
", metadata=" + metadata +
'}';
}
}
EOLAdd Person Repository:
cat > src/main/java/com/example/PersonRepository.java <<EOL
package com.example;
import org.springframework.data.repository.CrudRepository;
import java.util.List;
public interface PersonRepository extends CrudRepository<Person, Integer> {
List<Person> findByName(String name);
}
EOLModify App java main Class:
cat > src/main/java/com/example/App.java <<EOL
package com.example;
//import io.tarantool.spring.data32.repository.config.EnableTarantoolRepositories;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.data.redis.repository.configuration.EnableRedisRepositories;
@SpringBootApplication
//@EnableTarantoolRepositories
@EnableRedisRepositories
public class App {
public static void main(String[] args) {
App.bootstrap(args);
}
public static ApplicationContext bootstrap(String[] args) {
return SpringApplication.run(App.class, args);
}
}
EOLmvn clean package dependency:build-classpath -Dmdep.outputFile=classpath.txtjshell --class-path $(cat classpath.txt):target/classesЗагрузить зависимости и запустить spring:
import com.example.*;
import java.time.*;
var context = App.bootstrap(new String[] {}) Используем repository API:
var rep = context.getBean(PersonRepository.class);
rep.save(new Person(1, "art", Instant.now(), Map.of("hello", "world")));
rep.findById(1);
Поменяем приложение с помощью git патча:
rm diff.patch
wget https://gist.githubusercontent.com/ArtDu/7560100d1355efc73bf35c135f483a26/raw/c68f75c096bd0c14b19f6613b0640d8c4ffff736/diff.patch
git apply diff.patchЛибо можно пройтись ручками обновив 3 файла по diff ниже:
Update 3 files
Удалим зависимость на redis и добавим зависимость на tarantool:
diff --git a/pom.xml b/pom.xml
index 975111a..8d917f9 100644
--- a/pom.xml
+++ b/pom.xml
@@ -19,15 +19,10 @@
<artifactId>spring-boot-starter</artifactId>
<version>3.2.12</version>
</dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-data-redis</artifactId>
- <version>3.2.12</version>
- </dependency>
-<!-- <dependency>-->
-<!-- <groupId>io.tarantool</groupId>-->
-<!-- <artifactId>tarantool-spring-data-32</artifactId>-->
-<!-- <version>1.2.1</version>-->
-<!-- </dependency>-->
+ <dependency>
+ <groupId>io.tarantool</groupId>
+ <artifactId>tarantool-spring-data-32</artifactId>
+ <version>1.2.1</version>
+ </dependency>
</dependencies>
</project>Добавим аннотаций над POJO Person для Tarantool и удалим аннотации нужные для Redis:
diff --git a/src/main/java/com/example/Person.java b/src/main/java/com/example/Person.java
index 645b410..f4d8b6d 100644
--- a/src/main/java/com/example/Person.java
+++ b/src/main/java/com/example/Person.java
@@ -1,23 +1,19 @@
package com.example;
-//import com.fasterxml.jackson.annotation.JsonFormat;
-//import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import org.springframework.data.annotation.Id;
import org.springframework.data.keyvalue.annotation.KeySpace;
-import org.springframework.data.redis.core.RedisHash;
-import org.springframework.data.redis.core.index.Indexed;
import java.time.Instant;
import java.util.Map;
-//@JsonFormat(shape = JsonFormat.Shape.ARRAY)
-//@JsonIgnoreProperties(ignoreUnknown = true) // for example bucket_id
+@JsonFormat(shape = JsonFormat.Shape.ARRAY)
+@JsonIgnoreProperties(ignoreUnknown = true) // for example bucket_id
@KeySpace("person")
-@RedisHash("person")
public class Person {
@Id
public Integer id;
- @Indexed
public String name;
public Instant createdAt;
public Map metadata;В точку запуска скажем Spring чтобы использовал репозитории Tarantool вместо репозиториев Redis:
diff --git a/src/main/java/com/example/App.java b/src/main/java/com/example/App.java
index 0bfdc90..cc6a7b5 100644
--- a/src/main/java/com/example/App.java
+++ b/src/main/java/com/example/App.java
@@ -1,14 +1,12 @@
package com.example;
-//import io.tarantool.spring.data32.repository.config.EnableTarantoolRepositories;
+import io.tarantool.spring.data32.repository.config.EnableTarantoolRepositories;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
-import org.springframework.data.redis.repository.configuration.EnableRedisRepositories;
@SpringBootApplication
-//@EnableTarantoolRepositories
-@EnableRedisRepositories
+@EnableTarantoolRepositories
public class App {
public static void main(String[] args) {
App.bootstrap(args);Соберем и запустим jshell
mvn clean package dependency:build-classpath -Dmdep.outputFile=classpath.txt && jshell --class-path $(cat classpath.txt):target/classesimport com.example.*;
import java.time.*;
var context = App.bootstrap(new String[] {});
var rep = context.getBean(PersonRepository.class);
rep.save(new Person(1, "art", Instant.now(), Map.of("hello", "world")));
rep.findById(1);