All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.springframework.data.redis.cache.BatchStrategies Maven / Gradle / Ivy

There is a newer version: 3.2.5
Show newest version
/*
 * Copyright 2021-2022 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.springframework.data.redis.cache;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Optional;

import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.util.Assert;

/**
 * A collection of predefined {@link BatchStrategy} implementations using {@code KEYS} or {@code SCAN} command.
 *
 * @author Mark Paluch
 * @author Christoph Strobl
 * @since 2.6
 */
public abstract class BatchStrategies {

	private BatchStrategies() {
		// can't touch this - oh-oh oh oh oh-oh-oh
	}

	/**
	 * A {@link BatchStrategy} using a single {@code KEYS} and {@code DEL} command to remove all matching keys.
	 * {@code KEYS} scans the entire keyspace of the Redis database and can block the Redis worker thread for a long time
	 * on large keyspaces.
	 * 

* {@code KEYS} is supported for standalone and clustered (sharded) Redis operation modes. * * @return batching strategy using {@code KEYS}. */ public static BatchStrategy keys() { return Keys.INSTANCE; } /** * A {@link BatchStrategy} using a {@code SCAN} cursors and potentially multiple {@code DEL} commands to remove all * matching keys. This strategy allows a configurable batch size to optimize for scan batching. *

* Note that using the {@code SCAN} strategy might be not supported on all drivers and Redis operation modes. * * @return batching strategy using {@code SCAN}. */ public static BatchStrategy scan(int batchSize) { Assert.isTrue(batchSize > 0, "Batch size must be greater than zero!"); return new Scan(batchSize); } /** * {@link BatchStrategy} using {@code KEYS}. */ static class Keys implements BatchStrategy { static Keys INSTANCE = new Keys(); @Override public long cleanCache(RedisConnection connection, String name, byte[] pattern) { byte[][] keys = Optional.ofNullable(connection.keys(pattern)).orElse(Collections.emptySet()) .toArray(new byte[0][]); if (keys.length > 0) { connection.del(keys); } return keys.length; } } /** * {@link BatchStrategy} using {@code SCAN}. */ static class Scan implements BatchStrategy { private final int batchSize; Scan(int batchSize) { this.batchSize = batchSize; } @Override public long cleanCache(RedisConnection connection, String name, byte[] pattern) { Cursor cursor = connection.scan(ScanOptions.scanOptions().count(batchSize).match(pattern).build()); long count = 0; PartitionIterator partitions = new PartitionIterator<>(cursor, batchSize); while (partitions.hasNext()) { List keys = partitions.next(); count += keys.size(); if (keys.size() > 0) { connection.del(keys.toArray(new byte[0][])); } } return count; } } /** * Utility to split and buffer outcome from a {@link Iterator} into {@link List lists} of {@code T} with a maximum * chunks {@code size}. * * @param */ static class PartitionIterator implements Iterator> { private final Iterator iterator; private final int size; PartitionIterator(Iterator iterator, int size) { this.iterator = iterator; this.size = size; } @Override public boolean hasNext() { return iterator.hasNext(); } @Override public List next() { if (!hasNext()) { throw new NoSuchElementException(); } List list = new ArrayList<>(size); while (list.size() < size && iterator.hasNext()) { list.add(iterator.next()); } return list; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy