Будет ли Java Spring Boot устанавливать и получать значения в Redis безопасным способом? - PullRequest
0 голосов
/ 31 марта 2020

Мне нужно хранить значения ArrayList, которые часто меняются, и сохранять эти значения в случае приложения cra sh. Приложение, над которым я работаю, уже использует базу данных Redis, так что оно показалось мне хорошим выбором.

Ниже я продемонстрировал минимальный пример контроллера с загрузочной пружиной, который подключается к экземпляру Redhost localhost и использует его для хранения сериализованных объектов. Значение можно изменить из конечной точки контроллера или с помощью запланированного задания, которое выполняется каждые 5 секунд. Если вы выполните серию запросов get к localhost:8080/test, вы увидите, что запланированное задание удаляет элементы из ArrayList по одному.

Возможно ли пропустить значение или что-то еще? не потокобезопасно случиться здесь? Я обеспокоен тем, что запланированное задание может конфликтовать с изменениями, внесенными из конечной точки контроллера, если они попытаются изменить объект или одновременно установить значение Redis, особенно если сеть замедляется, но я не уверен, будет ли это на самом деле проблема. Кажется, все работает нормально, так как работает на моем локальном хосте, но я скептически отношусь.

Я прочитал эту статью, в частности, о безопасности потоков, но он не ответил, если какой-либо из эти вещи даже необходимы для этой конкретной ситуации. Я также знаю, что Redis для чтения и записи - это атомы c, но я подумал, что если команды будут отправлены в Redis в неправильном порядке?

Я думал, что если у этой реализации есть проблемы, тогда аннотация @Syncronized от Lombok может быть полезна для абстрагированного метода IO. Я ценю любой вклад и потраченное время.

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import io.lettuce.core.RedisClient;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.api.sync.RedisCommands;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;

@RestController
public class Example {

    RedisClient redisClient = RedisClient.create("redis://localhost:6379/");
    StatefulRedisConnection<String, String> connection = redisClient.connect();
    RedisCommands<String, String> redis = connection.sync();

    Gson gson = new Gson();

    ArrayList<String> someList = new ArrayList<>();


    public Example() {
        if(redis.exists("somekey") == 1){
            Type collectionType = new TypeToken<Collection<VideoDAO>>(){}.getType();
            someList = new ArrayList<>(gson.fromJson(redis.get("somekey"), collectionType));
        }
    }

    @GetMapping("/test")
    public void addToSomeList(){
        someList.add("sample string");
        redis.set("somekey",gson.toJson(someList));
        System.out.println("New item added. " + someList.size() + " items in array");
    }

    @Scheduled(fixedRate = 5000)
    public void popFromSomeList() {
        if (!someList.isEmpty()) {
            someList.remove(0);
            redis.set("somekey", gson.toJson(someList));
            System.out.println("Item removed. " + someList.size() + " items in array");
        }
    }

}

Я использую java 1.8.

1 Ответ

1 голос
/ 31 марта 2020

Очевидно, someList не является поточно-ориентированным, поэтому даже если вы игнорируете Redis, код не работает.

Допустим, мы сделаем его поточно-ориентированным с Collections.synchronizedList(new ArrayList<>());. Тогда add и pop все еще не атомы c, хотя это может не иметь большого значения для функциональности . Вы могли бы просто получить (например) следующий вид выполнения

someList.add("sample string");
someList.remove(0);
redis.set("somekey", gson.toJson(someList));
redis.set("somekey", gson.toJson(someList));

, и сообщения могли бы сбить с толку, поскольку это могло бы показать "Новый элемент добавлен. 4 элемента в массиве", "Новый элемент добавлен . 4 элемента в массиве "," Элемент удален. 4 элемента в массиве "из-за добавления / удаления перед печатью.

Таким образом, для правильной функциональности для данного кода (или аналогичного) вы должны иметь синхронизировать методы или использовать явную общую блокировку. Существует возможность отправки команд в неправильном порядке, но в данном примере (при условии, что список сделан поточно-ориентированным) вероятность реальной опасности отсутствует, поскольку это приведет только к дублированию набора для тех же данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...