«Поиск и заполнение пробелов» для консолидации вашей системы знаний Redis (смеется)

Java
«Поиск и заполнение пробелов» для консолидации вашей системы знаний Redis (смеется)

Windows Redis

Установить

Ссылка на сайт:disk.baidu.com/yes/1MJN ZX_QR…Код извлечения: 2c6w. После копирования этого содержимого откройте мобильное приложение Baidu SkyDrive, операция станет более удобной.

Бездумный следующий шаг

использовать

Произошла ошибка:

creating server tcp listening socket 127.0.0.1:6379: bind No error

решение:

  1. redis-cli.exe
  2. shutdown
  3. exit
  4. redis-server.exe redis.windows.conf

Запуск: redis-server.exe redis.windows.conf

Запуск клиента: redis-cli.exe (по умолчанию, если вы не изменяете конфигурацию)

redis-cli.exe -h 127.0.0.1 -p 6379 -пароль

Основное описание файла

запускаемый файл Описание функции
redis-server служба редис
redis-cli инструмент командной строки redis
redis-benchmark Тестовый тестовый инструмент
redis-check-aof Инструмент обнаружения и восстановления постоянных файлов AOF
redis-check-dump Инструмент обнаружения и восстановления постоянных файлов RDB
redis-sentinel начать часовой
redis-trib инструмент для создания кластера кластера

основная команда

Заказ инструкция
keys * Redis позволяет использовать нечеткие ключи запросов с 3 подстановочными знаками *, ?, []
del key удалить ключ
exists kxm определить, есть ли
expire key 20 установить время истечения - секунды
pexpire key 20000 установить время истечения - миллисекунды
move kxm 2 Переместите ключ в указанное место в библиотеке №2 библиотеки
persist key Удалите срок действия, и ключ будет существовать постоянно.Если настройка выполнена успешно, он вернет 1, иначе вернет 0.
pttl key Возвращает оставшееся время истечения срока действия ключа в миллисекундах.
ttl key Возвращает оставшееся время жизни для данного ключа в секундах
randomkey Возвращает случайный ключ из текущей базы данных
rename key newkxy Измените имя ключа, если оно будет повторяться, оно будет перезаписано
renamenx kxm key Переименуйте ключ в новый ключ, только если новый ключ не существует
type key Возвращает тип значения, сохраненного по ключу
select 0 Выберите первую библиотеку
ping Возврат PONG означает, что соединение нормальное.
quit закрыть текущее соединение

строковая команда

Заказ инструкция
set key aaa Установить значение указанного ключа
get key Получить значение указанного ключа
getrange key 0 1 Возвращает подсимволы строкового значения в ключе, включая 0 и 1 включительно.
getset key aaaaaaaa Устанавливает значение данного ключа в значение и возвращает старое значение ключа
mget key kxm Получить все (одно или несколько) значений для данного ключа
setex test 5 "this is my test" Свяжите значение value с ключом и установите срок действия ключа в секундах (в секундах).
setnx test test Установите значение ключа, только если ключ не существует (для распределенных замков)
strlen test Возвращает длину строкового значения, хранящегося в ключе
mset key1 "1" key2 "2" Установите одну или несколько пар ключ-значение одновременно
msetnx key3 "a" key2 "b" Задайте одну или несколько пар ключ-значение одновременно, сбой всех тогда и только тогда, когда ни один из заданных ключей не существует, и один из них не работает.
incr key Увеличьте числовое значение, хранящееся в ключе, на единицу -> значение ключа, например, строку числового типа, и верните увеличенный результат.
incrby num 1000 Увеличьте числовое значение, хранящееся в ключе, на указанное значение -> значение ключа, например строку числового типа, и верните увеличенный результат.
decr key то же -> минус один
decrby num 500 то же -> минус указанное значение
append key 1123123 Если ключ уже существует и является строкой, команда APPEND добавляет указанное значение к исходному значению ключа.Возвращает длину строки.

Хэш-команда

Заказ инструкция
hdel key field1 [field2] Удалить одно или несколько полей хеш-таблицы
hexistskey field Проверить, существует ли указанное поле в ключе хэш-таблицы
hget key field Получить значение указанного поля, хранящегося в хеш-таблице
hgetall key Получить все поля и значения для указанного ключа в хеш-таблице
hincrby hash yeary 1 Добавить шаг приращения к целочисленному значению указанного поля в ключе хэш-таблицы
hkeys hash Получить все поля в хеш-таблице
hlen hash Получить количество полей в хеш-таблице
hmget hash name year Получить значение всех заданных полей
hmset hash name "i am kxm" year 24 Одновременно установить несколько пар поле-значение (поле-значение) в ключ хэш-таблицы
hset hash name kxm Установите значение поля field в ключе хеш-таблицы на значение
hsetnx key field value Установите значение поля хэш-таблицы, только если поле поля не существует
hvals hash Получить все значения в хеш-таблице
hexists hash name он существует

Кодировка: значение поля состоит из двух форматов кодировки: ziplist и hashtable.

Когда полей мало, используется ziplist, а когда полей много, он станет кодировкой хэш-таблицы

Список команд

Списки Redis — это простые списки строк, отсортированные по порядку вставки. Вы можете добавить элемент в начало (слева) или хвост (справа) списка

Список может содержать не более 232 - 1 элемент (4294967295, более 4 миллиардов элементов в списке)

емкость -> набор, поэтому набор отсортирован

Заказ инструкция
lpush list php Вставить значение в начало списка Возвращать длину списка
lindex list 0 Получить элемент в списке по индексу
blpop key1 [key2 ] timeout Выйдите и получите первый элемент списка, если в списке нет элементов, он заблокирует список до тех пор, пока не истечет время ожидания или не будет найден всплывающий элемент.
brpop key1 [key2 ] timeout Выйдите и получите последний элемент списка, если в списке нет элементов, он заблокирует список до тех пор, пока не истечет время ожидания или не будет найден всплывающий элемент.
linsert list before 3 4 Вставьте 4 перед тем, как значение 3 будет верхним
linsert list after 4 5 вставить 5 после значения 4
llen list получить длину списка
lpop list Выйти и получить первый элемент списка
lpush list c++ c Вставить одно или несколько значений в начало списка
lrange list 0 1 Получить элементы в указанном диапазоне списка, включая 0 и 1-1 для всех (список lrange 0-1)
lrem list 1 c Удалить элемент, значение которого равно c в наборе списка, 1 представляет количество, то есть удалить несколько
lset list 0 "this is update" Установить значение элемента списка по индексу
ltrim list 1 5 Обрезать список, то есть оставить в списке только элементы из указанного диапазона, а элементы, не входящие в указанный диапазон, будут удалены
rpop list Удалить последний элемент списка, вернуть удаленный элемент
rpush list newvalue3 Добавить новое значение снизу
rpoplpush list list2 данные списка передачи

Установить команду

Set — это неупорядоченная коллекция типа String. Члены коллекции уникальны, а это означает, что в коллекции не может быть повторяющихся данных.

Заказ инструкция
sadd set java php c c++ python Добавить одного или нескольких участников в коллекцию
scard set Получить количество членов коллекции
sdiff key1 [key2] Возвращает разницу всех заданных наборов Математически разница
Набор новостей sdiffstore curr (адрес назначения sdiffstore key1 [key2]) Сохраните разницу между набором и набором новостей в curr
sinter set newset Возвращает пересечение всех заданных множеств
набор новостей sinterstore curr (sinterstoredestination key1[key2]) такой же
sismember set c# Определите, является ли элемент-член членом заданного ключа
smembers set Возвращает все элементы в коллекции
srandmember set 2 Случайным образом вытяните два ключа (лотерея для достижения красоты)
Переместить set newtest java (переместить исходный пункт назначения) Переместите элемент-член из исходной коллекции в целевую коллекцию.
sunion set newset Возвращает объединение всех заданных наборов
srem set java Удалить
spop set вытолкнуть элемент из коллекции
sdiff | sinter | sunion Операция: Интерсет Операция: Набор разностей

команда отсортированного набора

Упорядоченные коллекции Redis, как и коллекции, также являются коллекциями элементов строкового типа, и повторяющиеся элементы не допускаются.

Разница в том, что каждый элемент связан с дробью типа double. Redis сортирует элементы набора от меньшего к большему по количеству баллов.

Члены упорядоченного набора уникальны, но оценки могут повторяться.

Заказ инструкция
zadd sort 1 java 2 python Добавьте одного или нескольких участников в отсортированный набор или обновите оценки существующих участников.
zcard sort Получить количество членов отсортированного набора
zcount sort 0 1 подсчитывает количество элементов с указанным значением интервала в отсортированном наборе
zincrby sort 500 java Добавить приращение к оценке указанного члена в отсортированном наборе
zscore sort java Возвращает дробное значение элемента в упорядоченном наборе
zrange sort 0 -1 Получить значение указанного серийного номера, -1 означает все
zrangebyscore sort 0 5 Оценка соответствует диапазону значений
zrangebyscore sort 0 5 limit 0 1 Лимит страниц 0 представляет номер страницы, 1 представляет количество отображаемых страниц
zrem sort java удалить элемент
zremrangebyrank sort 0 1 Удалить элементы по диапазону рангов
zremrangebyscore sort 0 1 Удалить элементы по диапазону баллов
zrevrank sort c# Возвращает ранг указанного члена в отсортированном наборе, отсортированном по убыванию значения оценки (от большего к меньшему).

опубликовать подписаться

Откройте два клиента

Клиент подписывается на канал: subscribe redisChat (название канала — redisChat)

Клиент Б публикует контент: опубликуйте redisChat «Привет, это моя работа» (контент — привет....)

Клиент А должен автоматически получать контент.Схема выглядит следующим образом:

Заказ инструкция
pubsub channels Проверьте, сколько каналов у Redis в настоящее время
pubsub numsub chat1 Посмотрите, сколько подписчиков у канала
unsubscrible chat1 Отписаться от указанного канала
psubscribe java.* Подпишитесь на набор каналов

Транзакции Redis

Транзакции Redis могут выполнять несколько команд одновременно с тремя важными гарантиями:

  • Массовые операции помещаются в буфер очереди перед отправкой команды EXEC.
  • После получения команды EXEC транзакция выполняется, ни одна команда в транзакции не может быть выполнена, а остальные команды продолжают выполняться.
  • Во время выполнения транзакции запросы команд, отправленные другими клиентами, не будут вставлены в последовательность команд выполнения транзакции.

Транзакция проходит следующие три этапа от инициации до выполнения:

  • начать транзакцию
  • очередь команд
  • выполнить транзакцию

注意:redis事务和数据库事务不同,redis事务出错后最大的特点是,一剩下的命令会继续执行,二出错的数据不会回滚

Заказ инструкция
multi отметить начало транзакции
exec выполнить транзакцию
discard После старта транзакции транзакция прерывается в процессе ввода команды в очередь
watch key Следить за одним (или несколькими) ключами, если этот (или эти) ключи будут изменены другими командами до выполнения транзакции, то транзакция будет прервана
unwatch Отменить мониторинг всех ключей командой WATCH

Команды сервера Redis

Заказ инструкция
flushall удалить все ключи из всех баз данных
flushdb Удалить все ключи в текущей базе данных
save Синхронно сохранять данные на жесткий диск

Резервное копирование и восстановление данных Redis

Redis SAVEкоманда для создания резервной копии текущей базы данных

Если вам нужно восстановить данные, просто переместите файл резервной копии (dump.rdb) в каталог установки Redis и запустите службу. Чтобы получить каталог redis, вы можете использоватьCONFIGЗаказ

Тест производительности Redis

Основные команды для тестирования производительности Redis следующие:

redis目录执行:redis-benchmark [option] [option value]

// 会返回各种操作的性能报告(100连接,10000请求)
redis-benchmark -h 127.0.0.1 -p 6379 -c 100 -n 10000

// 100个字节作为value值进行压测
redis-benchmark -h 127.0.0.1 -p 6379 -q -d 100

Java Redis

Jedis

<!-- jedis -->
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>2.8.2</version>
</dependency>

Конфигурация джедая

############# redis Config #############
# Redis数据库索引(默认为0)
spring.redis.database=0
# Redis服务器地址
spring.redis.host=120.79.88.17
# Redis服务器连接端口
spring.redis.port=6379
# Redis服务器连接密码(默认为空)
spring.redis.password=123456
# 连接池中的最大空闲连接
spring.redis.jedis.pool.max-idle=8
# 连接池中的最小空闲连接
spring.redis.jedis.pool.min-idle=0

JedisConfig

@Configuration
public class JedisConfig extends CachingConfigurerSupport {

    @Value("${spring.redis.host}")
    private String host;

    @Value("${spring.redis.port}")
    private int port;

    @Value("${spring.redis.password}")
    private String password;

    @Value("${spring.redis.max-idle}")
    private Integer maxIdle;

    @Value("${spring.redis.min-idle}")
    private Integer minIdle;

    @Bean
    public JedisPool redisPoolFactory(){
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        jedisPoolConfig.setMaxIdle(maxIdle);
        jedisPoolConfig.setMinIdle(minIdle);
        jedisPoolConfig.setMaxWaitMillis(3000L);
        int timeOut = 3;
        return  new JedisPool(jedisPoolConfig, host, port, timeOut, password);
    }
}

Основное использование

@RunWith(SpringRunner.class)
@SpringBootTest(classes = KerwinBootsApplication.class)
public class ApplicationTests {

    @Resource
    JedisPool jedisPool;

    @Test
    public void testJedis () {
        Jedis jedis = jedisPool.getResource();
        jedis.set("year", String.valueOf(24));
    }
}

SpringBoot redis staeter RedisTemplate

<!-- redis -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

<!-- redis 2.X 更换为commons-pool2 连接池 -->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
</dependency>
############# redis Config #############
# Redis数据库索引(默认为0)
spring.redis.database=0
# Redis服务器地址
spring.redis.host=120.79.88.17
# Redis服务器连接端口
spring.redis.port=6379
# Redis服务器连接密码(默认为空)
spring.redis.password=123456
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.jedis.pool.max-active=200
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.jedis.pool.max-wait=1000ms
# 连接池中的最大空闲连接
spring.redis.jedis.pool.max-idle=8
# 连接池中的最小空闲连接
spring.redis.jedis.pool.min-idle=0
# 连接超时时间(毫秒)
spring.redis.timeout=1000ms
//  Cache注解配置类
@Configuration
public class RedisCacheConfig {

    @Bean
    public KeyGenerator simpleKeyGenerator() {
        return (o, method, objects) -> {
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append(o.getClass().getSimpleName());
            stringBuilder.append(".");
            stringBuilder.append(method.getName());
            stringBuilder.append("[");
            for (Object obj : objects) {
                stringBuilder.append(obj.toString());
            }
            stringBuilder.append("]");
            return stringBuilder.toString();
        };
    }

    @Bean
    public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
        return new RedisCacheManager(
                RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory),

                // 默认策略,未配置的 key 会使用这个
                this.getRedisCacheConfigurationWithTtl(15),

                // 指定 key 策略
                this.getRedisCacheConfigurationMap()
        );
    }

    private Map<String, RedisCacheConfiguration> getRedisCacheConfigurationMap() {
        Map<String, RedisCacheConfiguration> redisCacheConfigurationMap  = new HashMap<>(16);
        redisCacheConfigurationMap.put("redisTest", this.getRedisCacheConfigurationWithTtl(15));
        return redisCacheConfigurationMap;
    }

    private RedisCacheConfiguration getRedisCacheConfigurationWithTtl(Integer seconds) {
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);

        RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig();
        redisCacheConfiguration = redisCacheConfiguration.serializeValuesWith(
                RedisSerializationContext
                        .SerializationPair
                        .fromSerializer(jackson2JsonRedisSerializer)
        ).entryTtl(Duration.ofSeconds(seconds));
        return redisCacheConfiguration;
    }
}
// RedisAutoConfiguration
@Configuration
@EnableCaching
public class RedisConfig {

    @Bean
    @SuppressWarnings("all")
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {

        RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
        template.setConnectionFactory(factory);

        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);

        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);

        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();

        // key采用String的序列化方式
        template.setKeySerializer(stringRedisSerializer);

        // hash的key也采用String的序列化方式
        template.setHashKeySerializer(stringRedisSerializer);

        // value序列化方式采用jackson
        template.setValueSerializer(jackson2JsonRedisSerializer);

        // hash的value序列化方式采用jackson
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();
        return template;
    }
}
// 基础使用
@Resource
RedisTemplate<String,Object> redisTemplate;
redisTemplate.opsForList().rightPush("user:1:order", dataList.get(3).get("key").toString());

// 注解使用
@Cacheable(value = "redisTest")
public TestBean testBeanAnnotation () {}

Сценарии использования Redis

тип Применимая сцена
String Кэш, текущий лимит, счетчик, распределенная блокировка, распределенная сессия
Hash Хранить информацию о пользователе, посещения домашней страницы пользователя, комбинированный запрос
List Список подписчиков Weibo, простая очередь
Set Нравится, Не нравится, Тег, Дружба
Zset Таблица лидеров

Или простые очереди сообщений, системы публикации-подписки, реализующие системы сообщений и т. д.

Строка - кеш

// 1.Cacheable 注解
// controller 调用 service 时自动判断有没有缓存,如果有就走redis缓存直接返回,如果没有则数据库然后自动放入redis中
// 可以设置过期时间,KEY生成规则 (KEY生成规则基于 参数的toString方法)
@Cacheable(value = "yearScore", key = "#yearScore")
@Override
public List<YearScore> findBy (YearScore yearScore) {}

// 2.手动用缓存
if (redis.hasKey(???) {
    return ....
} 

redis.set(find from DB)...

Строка - текущий лимит | счетчик

// 注:这只是一个最简单的Demo 效率低,耗时旧,但核心就是这个意思
// 计数器也是利用单线程incr...等等
@RequestMapping("/redisLimit")
public String testRedisLimit(String uuid) {
    if (jedis.get(uuid) != null) {
        Long incr = jedis.incr(uuid);
        if (incr > MAX_LIMITTIME) {
            return "Failure Request";
        } else {
            return "Success Request";
        }
    }

    // 设置Key 起始请求为1,10秒过期  ->  实际写法肯定封装过,这里就是随便一写
    jedis.set(uuid, "1");
    jedis.expire(uuid, 10);
    return "Success Request";
}

Строка — распределенная блокировка (выделение)

/***
 * 核心思路:
 *     分布式服务调用时setnx,返回1证明拿到,用完了删除,返回0就证明被锁,等...
 *     SET KEY value [EX seconds] [PX milliseconds] [NX|XX]
 *     EX second:设置键的过期时间为second秒
 *     PX millisecond:设置键的过期时间为millisecond毫秒
 *     NX:只在键不存在时,才对键进行设置操作
 *     XX:只在键已经存在时,才对键进行设置操作
 *
 * 1.设置锁
 *     A. 分布式业务统一Key
 *     B. 设置Key过期时间
 *     C. 设置随机value,利用ThreadLocal 线程私有存储随机value
 *
 * 2.业务处理
 *     ...
 *
 * 3.解锁
 *     A. 无论如何必须解锁 - finally (超时时间和finally 双保证)
 *     B. 要对比是否是本线程上的锁,所以要对比线程私有value和存储的value是否一致(避免把别人加锁的东西删除了)
 */
@RequestMapping("/redisLock")
public String testRedisLock () {
    try {
        for(;;){
            RedisContextHolder.clear();
            String uuid = UUID.randomUUID().toString();

            String set = jedis.set(KEY, uuid, "NX", "EX", 1000);
            RedisContextHolder.setValue(uuid);

            if (!"OK".equals(set)) {
                // 进入循环-可以短时间休眠
            } else {
                // 获取锁成功 Do Somethings....
                break;
            }
        }
    } finally {
        // 解锁 -> 保证获取数据,判断一致以及删除数据三个操作是原子的, 因此如下写法是不符合的
        /*if (RedisContextHolder.getValue() != null && jedis.get(KEY) != null && RedisContextHolder.getValue().equals(jedis.get(KEY))) {
                jedis.del(KEY);
            }*/

        // 正确姿势 -> 使用Lua脚本,保证原子性
        String luaScript = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end";
        Object eval = jedis.eval(luaScript, Collections.singletonList(KEY), Collections.singletonList(RedisContextHolder.getValue()));
    }
    return "锁创建成功-业务处理成功";
}

Строка — распределенный сеанс (выделение)

// 1.首先明白为什么需要分布式session -> nginx负载均衡 分发到不同的Tomcat,即使利用IP分发,可以利用request获取session,但是其中一个挂了,怎么办?? 所以需要分布式session

注意理解其中的区别  A服务-用户校验服务  B服务-业务层

情况A:
A,B 服务单机部署:
cookie:登录成功后,存储信息到cookie,A服务自身通过request设置session,获取session,B服务通过唯一key或者userid 查询数据库获取用户信息

cookie+redis:登录成功后,存储信息到cookie,A服务自身通过request设置session,获取session,B服务通过唯一key或者userid 查询redis获取用户信息


情况B:
A服务多节点部署,B服务多节点部署
B服务获取用户信息的方式其实是不重要的,必然要查,要么从数据库,要么从cookie

A服务:登录成功后,存储唯一key到cookie, 与此同时,A服务需要把session(KEY-UserInfo)同步到redis中,不能存在单纯的request(否则nginx分发到另一个服务器就完犊子了)

官方实现:
spring-session-data-redis
有一个内置拦截器,拦截request,session通过redis交互,普通使用代码依然是request.getSession....  但是实际上这个session的值已经被该组件拦截,通过redis进行同步了

Список простых очередей-стеков

// 说白了利用redis - list数据结构 支持从左从右push,从左从右pop
@Component
public class RedisStack {

    @Resource
    Jedis jedis;

    private final static String KEY = "Stack";

    /** push **/
    public void push (String value) {
        jedis.lpush(KEY, value);
    }

    /** pop **/
    public String pop () {
        return jedis.lpop(KEY);
    }
}
@Component
public class RedisQueue {

    @Resource
    JedisPool jedisPool;

    private final static String KEY = "Queue";

    /** push **/
    public void push (String value) {
        Jedis jedis = jedisPool.getResource();
        jedis.lpush(KEY, value);
    }

    /** pop **/
    public String pop () {
        Jedis jedis = jedisPool.getResource();
        return jedis.rpop(KEY);
    }
}

List Social APP - Список друзей

根据时间显示好友,多个好友列表,求交集,并集  显示共同好友等等...
疑问:难道大厂真的用redis存这些数据吗???多大的量啊... 我个人认为实际是数据库存用户id,然后用算法去处理,更省空间

Установить лотерею | Дружба (слияние, союз, пересечение)

// 插入key 及用户id
sadd cat:1 001 002 003 004 005 006

// 返回抽奖参与人数
scard cat:1

// 随机抽取一个
srandmember cat:1

// 随机抽取一人,并移除
spop cat:1

Zset Таблица лидеров

根据分数实现有序列表
微博热搜:每点击一次 分数+1 即可

--- 不用数据库目的是因为避免order by 进行全表扫描

Общие вопросы интервью

Q1: Почему Redis такой быстрый?

1.Redis完全基于内存,绝大部分请求是纯粹的内存操作,执行效率高。
2.Redis使用单进程单线程模型的(K,V)数据库,将数据存储在内存中,存取均不会受到硬盘IO的限制,因此其执行速度极快,另外单线程也能处理高并发请求,还可以避免频繁上下文切换和锁的竞争,同时由于单线程操作,也可以避免各种锁的使用,进一步提高效率
3.数据结构简单,对数据操作也简单,Redis不使用表,不会强制用户对各个关系进行关联,不会有复杂的关系限制,其存储结构就是键值对,类似于HashMap,HashMap最大的优点就是存取的时间复杂度为O(1)
5.C语言编写,效率更高
6.Redis使用多路I/O复用模型,为非阻塞IO
7.有专门设计的RESP协议

Объясните по четвертому пункту ->

Существует четыре распространенные модели ввода-вывода:

  • Синхронный блокирующий ввод-вывод (Blocking IO): традиционная модель ввода-вывода.

  • Синхронный неблокирующий ввод-вывод (неблокирующий ввод-вывод): сокеты, созданные по умолчанию, заблокированы.Неблокирующий ввод-вывод требует, чтобы для сокета было установлено значение NONBLOCK. Обратите внимание, что упомянутая здесь NIO не является библиотекой Java NIO (New IO).

  • Мультиплексирование ввода-вывода: классический шаблон проектирования Reactor, иногда называемый асинхронным блокирующим вводом-выводом. Обе модели — Selector в Java и epoll в Linux.

  • Асинхронный ввод-вывод (асинхронный ввод-вывод): классический шаблон проектирования Proactor, также известный как асинхронный неблокирующий ввод-вывод.

Синхронные, асинхронные, блокирующие и неблокирующие концепции:

Предположим, Redis использует синхронный блокирующий ввод-вывод:

Основная программа Redis (один поток на стороне сервера) -> несколько клиентских подключений (реальная ситуация такова, что разработчики подключаются к redis, а программа redispool подключается к redis), каждое из которых соответствует клиенту, предполагая 100 клиентов, из которых Когда один взаимодействует, если принят метод синхронной блокировки, то остальные 99 должны ждать на месте, что неизбежно будет ненаучным.

мультиплексирование ввода-вывода

Redis использует модель мультиплексирования ввода/вывода

В модели мультиплексирования ввода-вывода наиболее важным вызовом функции являетсяselect, этот метод может отслеживать доступность для чтения и записи нескольких файловых дескрипторов одновременно.Когда некоторые из файловых дескрипторов доступны для чтения или записи,selectМетод возвращает количество файловых дескрипторов, доступных для чтения и записи.

注:redis默认使用的是更加优化的算法:epoll

select poll epoll
Метод работы траверс траверс Перезвони
низкоуровневая реализация множество связанный список хеш-таблица
Эффективность ввода-вывода Каждый вызов проходится линейно, а временная сложность составляет O (n) Каждый вызов проходится линейно, а временная сложность составляет O (n) В методе уведомления о событии всякий раз, когда fd будет готов, будет вызываться функция обратного вызова, зарегистрированная системой, и готовый fd будет помещен в readyList.Временная сложность O(1)
Максимальное количество подключений 1024 (x86) или 2048 (x64) неограниченный неограниченный

Таким образом, мы можем сказать, что Redis устроен так: нет сомнений, что сервер является однопоточным.При подключении нескольких клиентов, если клиент не инициирует никаких действий, сервер будет рассматривать его как неактивный поток ввода-вывода и приостанавливать его. , Когда есть реальное действие, соответствующее событие будет выполнено в виде обратного вызова

Q2: запрос ключа с фиксированным префиксом из большого количества ключей

A. Глупый метод: KEYS [шаблон] Обратите внимание, что если ключей много, это определенно вызовет проблемы и приведет к сбою Redis.

B. Курсор SCAN [MATCH pattern] [COUNT count] поиск курсора

Q3: Как реализовать распределенные блокировки через Redis

见上文

Q4: Как реализовать асинхронную очередь

上文说到利用 redis-list 实现队列
假设场景:A服务生产数据 - B服务消费数据,即可利用此种模型构造-生产消费者模型

1. 使用Redis中的List作为队列
2.使用BLPOP key [key...] timeout  -> LPOP key [key ...] timeout:阻塞直到队列有消息或者超时
(方案二:解决方案一中,拿数据的时,生产者尚未生产的情况)

3.pub/sub:主题订阅者模式
基于reds的终极方案,上文有介绍,基于发布/订阅模式
缺点:消息的发布是无状态的,无法保证可达。对于发布者来说,消息是“即发即失”的,此时如果某个消费者在生产者发布消息时下线,重新上线之后,是无法接收该消息的,要解决该问题需要使用专业的消息队列

Вопрос 5. Какие типы данных поддерживает Redis?

见上文

Q6: Что такое постоянство Redis? Какие методы сохранения есть в Redis? Какие преимущества и недостатки?

Постоянство — это запись данных из памяти на диск, чтобы предотвратить потерю данных памяти, когда служба не работает.

Redis предоставляет два метода сохранения: RDB (по умолчанию) и AOF.

РБД:

rdb — это аббревиатура Redis DataBase.

Функция ядра функции rdbSave (создание файла RDB) и rdbLoad (загрузка памяти из файла) две функции

RDB: процесс создания файла моментального снимка текущих данных процесса и его сохранения на жесткий диск. Делится на ручной триггер и автоматический триггер

Ручной триггер -> сохранение (не рекомендуется, серьезная блокировка) bgsave -> (оптимизированная версия сохранения, блокировка в микросекундах)

shutdowm 关闭服务时,如果没有配置AOF,则会使用bgsave持久化数据

bgsave - как это работает

Разветвит дочерний процесс от текущего родительского процесса, а затем сгенерирует файл rdb

Недостатки: низкая частота, невозможность обеспечения постоянства в реальном времени.

AOF:

Aof — это сокращение от «Файл только для добавления», и файл AOF также хранится в протоколе RESP.

Функция flushAppendOnlyFile вызывается всякий раз, когда выполняется серверная (временная) задача или функция.Эта функция выполняет следующие две задачи.

aof написать сохранить:

ЗАПИСАТЬ: Записать кеш в aof_buf в файл AOF в соответствии с условием

СОХРАНИТЬ: В зависимости от условий вызовите функцию fsync или fdatasync, чтобы сохранить файл AOF на диск.

Структура хранения:

Содержимое представляет собой хранилище текста команды в формате протокола связи Redis (RESP).

принцип:

Это эквивалентно хранению команды выполнения redis (аналогично журналу операторов sql mysql), а целостность и согласованность данных выше.

сравнивать:

1. Файл aof обновляется чаще, чем rdb

2. aof более безопасен, чем rdb

3, производительность rdb лучше

PS: Правильная остановка службы redis должна основываться на команде подключения плюс выключение -> иначе будут проблемы с сохранением данных

Q7: протокол связи redis (RESP)

Redis — это REmote Dictionary Server (служба удаленного словаря);

Спецификация протокола Redis — это протокол сериализации Redis (протокол сериализации Redis).

RESP — это протокол связи, который ранее использовался клиентом и сервером Redis;

Особенности RESP: простая реализация, быстрый синтаксический анализ, хорошая читабельность.

Соглашение заключается в следующем:

Клиент отправляет команды на сервер в указанном формате

set key value 协议翻译如下:

* 3    ->  表示以下有几组命令

$ 3    ->  表示命令长度是3
SET

$6     ->  表示长度是6
keykey

$5     ->  表示长度是5
value

完整即:
* 3
$ 3
SET
$6
keykey
$5 
value

После выполнения последней команды сервер возвращает результат в следующем формате:

Для простых строк первым байтом ответа является ответ «+».

Для ошибок первым байтом ответа является "-" ошибка

Для целых чисел первым байтом ответа является ":"

Для групповых строк первым байтом ответа является строка «$».

Для массивов первым байтом ответа является массив "*"

// 伪造6379 redis-服务端,监听  jedis发送的协议内容
public class SocketApp {
    
    /***
     * 监听 6379 传输的数据
     * JVM端口需要进行设置
     */
    public static void main(String[] args)  {
        try {
            ServerSocket serverSocket = new ServerSocket(6379);
            Socket redis = serverSocket.accept();
            byte[] result = new byte[2048];
            redis.getInputStream().read(result);
            System.out.println(new String(result));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

// jedis连接-发送命令
public class App {
    public static void main(String[] args){
        Jedis jedis = new Jedis("127.0.0.1");
        jedis.set("key", "This is value.");
        jedis.close();
    }
}

// 监听命令内容如下:
*3
$3
SET
$3
key
$14

Вопрос 8. Какие существуют архитектуры Redis?

один узел

репликация master-slave

Master-slave  主从赋值,此种结构可以考虑关闭master的持久化,只让从数据库进行持久化,另外可以通过读写分离,缓解主服务器压力

часовой

Redis sentinel 是一个分布式系统中监控 redis 主从服务器,并在主服务器下线时自动进行故障转移。其中三个特性:

监控(Monitoring):    Sentinel  会不断地检查你的主服务器和从服务器是否运作正常。

提醒(Notification): 当被监控的某个 Redis 服务器出现问题时, Sentinel 可以通过 API 向管理员或者其他应用程序发送通知。

自动故障迁移(Automatic failover): 当一个主服务器不能正常工作时, Sentinel 会开始一次自动故障迁移操作。

特点:
1、保证高可用
2、监控各个节点
3、自动故障迁移

缺点:主从模式,切换需要时间丢数据
没有解决 master 写的压力

кластер

Кластеры Redis-cluster поддерживаются с версии redis 3.0.Redis-Cluster использует нецентрализованную структуру.Каждый узел хранит данные и состояние всего кластера, и каждый узел подключен ко всем другим узлам.

Функции:

1. Нет центральной архитектуры (никакой узел не влияет на узкие места производительности) и отсутствует прокси-уровень.

2. Данные распределяются по нескольким узлам в соответствии с хранилищем слотов, и данные распределяются между узлами, а распределение данных можно регулировать динамически.

3. Масштабируемость, возможность линейного расширения до 1000 узлов, а также возможность динамического добавления или удаления узлов.

4. Высокая доступность, когда некоторые узлы недоступны, кластер все равно доступен. Резервное копирование данных путем добавления Slave

5. Реализуйте автоматическое переключение при сбое, обмен информацией о состоянии между узлами через протокол сплетен и используйте механизм голосования для завершения повышения роли от ведомого до ведущего.

недостаток:

1. Изоляция ресурса плохая, и он подвержен взаимному влиянию.

2. Данные реплицируются асинхронно, и строгая согласованность данных не гарантируется.

Q9: Кластер Redis — как быстро найти то, что вам нужно, из массива данных?

  • Фрагментация

    Разделяйте данные по определенным правилам и храните их разбросанными по нескольким узлам. Уменьшите нагрузку на один сервер Redis, разделив данные между несколькими серверами Redis.

  • Последовательный алгоритм хеширования

    Поскольку данные должны быть сегментированы, обычным методом является получение хэш-значения узла, а затем вычисление модуля в соответствии с количеством узлов, но у этого метода есть очевидные недостатки.Когда количество узлов Redis необходимо динамически увеличивается или уменьшается, это приведет к тому, что большое количество клавиш не может быть нажато. Итак, Redis представилПоследовательный алгоритм хеширования. алгоритмВозьмите модуль 2 ^ 32 и сформируйте виртуальное кольцо из пространства значений хэша., запрессовано все кольцопо часовой стрелкеОрганизация направления, каждый узел имеет последовательность 0, 1, 2...2^32-1, а затем каждый сервер подвергается хеш-операции для определения адреса сервера в этом хеш-кольце.После определения адреса сервера используйте данные Тот же алгоритм хеширования находит данные на определенном сервере Redis. Если в найденном расположении нет экземпляра сервера Redis, продолжайте поиск по часовой стрелке, и первый найденный сервер будет конечным расположением сервера данных.

    一致性Hash算法

Проблема перекоса данных Hash Ring

Когда в хеш-кольце мало серверных узлов, легко столкнуться с проблемой неравномерных серверных узлов, что приведет кперекос данных, Перекос данных относится к тому факту, что большая часть кэшированных объектов сосредоточена на одном или нескольких серверах в кластере Redis.

Как показано на рисунке выше, большая часть данных после последовательного алгоритма хеширования хранится на узле A, в то время как узел B хранит только небольшой объем данных, и узел A со временем взорвется.Внедрить виртуальные узлы

Например, на картинке выше: Разделите NodeA и NodeB на Node A#1-A#3 NodeB#1-B#3.

Q10: Что такое проникновение в кэш? Как этого избежать? Что такое кэш-лавина? Как этого избежать? Что такое разбивка кеша? Как этого избежать?

проникновение в кеш

Общая система кэширования кэширует запросы в соответствии с ключом. Если соответствующего значения нет, он должен обратиться к серверной системе, чтобы найти его (например, БД). Некоторые вредоносные запросы намеренно запрашивают несуществующие ключи, а объем запросов будет очень большим, что вызовет большую нагрузку на серверную систему. Это называется проникновением в кэш.

Как этого избежать?

1: Кэш также выполняется, когда результат запроса пуст, а время кэширования установлено на меньшее или кэш очищается после вставки данных, соответствующих ключу.

2: Отфильтровать ключи, которые не должны существовать. Вы можете поместить все возможные ключи в большое растровое изображение и фильтровать растровое изображение при запросе.

3: Поскольку параметры запроса являются недопустимыми (параметры, которые не существуют, запрашиваются каждый раз), мы можем использовать фильтр Блума или фильтр сжатия для предварительного перехвата, и запрос не будет допущен на уровень базы данных, если он незаконно.

Кэш Лавина

Когда сервер кеша перезапускается или большое количество кешей выходит из строя в течение определенного периода времени, это оказывает сильное давление на серверную систему, когда она выходит из строя. вызвать сбой системы.

Как этого избежать?

1: после того, как кеш становится недействительным, количество потоков, читающих базу данных и записывающих в кеш, контролируется блокировкой или постановкой в ​​очередь. Например, только одному потоку разрешено запрашивать данные и записывать кэш для определенного ключа, а другие потоки ждут.

2: выполните кеш второго уровня, A1 — это исходный кеш, A2 — это кеш-копия, при сбое A1 вы можете получить доступ к A2, время аннулирования кеша A1 установлено на краткосрочный период, а A2 — на долгосрочный.

3: Разные ключи, установите разное время истечения срока действия, чтобы время аннулирования кеша было как можно более однородным.

4: Включите текущую стратегию ограничения, чтобы максимально избежать уничтожения базы данных.

разбивка кеша

концепция Для существующего ключа, когда срок действия кеша истекает, одновременно поступает большое количество запросов, и эти запросы будут разбиваться на БД, что приводит к большому количеству мгновенных запросов к БД и внезапному увеличению нагрузки.

решение A. Прежде чем получить доступ к ключу, используйте SETNX (установите, если он не существует), чтобы установить другой краткосрочный ключ, чтобы заблокировать доступ к текущему ключу, и удалите краткосрочный ключ после окончания доступа.

B. Обработка сервисного уровня — блокировка метода + двойная проверка:

// 锁-实例
private Lock lock = new ReentrantLock();

public String getProductImgUrlById(String id){
    // 获取缓存
    String product = jedisClient.get(PRODUCT_KEY + id);
    if (null == product) {
        // 如果没有获取锁等待3秒,SECONDS代表:秒
        try {
            if (lock.tryLock(3, TimeUnit.SECONDS)) {
                try {
                    // 获取锁后再查一次,查到了直接返回结果
                    product = jedisClient.get(PRODUCT_KEY + id);
                    if (null == product) {
                        // ....
                    }
                    return product;
                } catch (Exception e) {
                    product = jedisClient.get(PRODUCT_KEY + id);
                } finally {
                    // 释放锁(成功、失败都必须释放,如果是lock.tryLock()方法会一直阻塞在这)
                    lock.unlock();
                }
            } else {
                product = jedisClient.get(PRODUCT_KEY + id);
            }
        } catch (InterruptedException e) {
            product = jedisClient.get(PRODUCT_KEY + id);
        }
    }
    return product;
}

объяснять основное решение
проникновение в кеш При обращении к несуществующему ключу кеш не работает, запрос проникнет в БД, а БД зависнет при большом трафике 1. Используйте фильтр Блума и используйте достаточно большое растровое изображение для хранения ключей, к которым можно получить доступ, а несуществующие ключи фильтруются напрямую 2. Если ключ доступа не находит значения в БД, нулевое значение тоже записывается в кеш, но можно поставить меньшее время истечения
Кэш Лавина Большое количество ключей устанавливается с одинаковым сроком действия, что приводит к одновременному сбою всех кешей, что приводит к большому количеству мгновенных запросов к БД, внезапному увеличению давления и лавине Вы можете добавить случайное значение времени в кеш при установке времени истечения срока действия, чтобы время истечения срока действия каждого ключа распределялось и не аннулировалось одновременно.
разбивка кеша Для существующего ключа, когда срок действия кеша истекает, одновременно поступает большое количество запросов, и эти запросы будут разбиваться на БД, что приводит к большому количеству мгновенных запросов к БД и внезапному увеличению нагрузки. Перед доступом к ключу используйте SETNX (установите, если он не существует), чтобы установить другой краткосрочный ключ для блокировки доступа к текущему ключу и удалить краткосрочный ключ после окончания доступа.

Q11: Кэш согласуется с двойной записью базы данных

Если вы просто читаете данные, такой проблемы нет

Если это новые данные, такой проблемы нет

Когда данные необходимо обновить, как обеспечить согласованность двойной записи между кешем и базой данных?

Три стратегии обновления:

  1. Сначала обновите базу данных, затем обновите кеш ->

  2. Сначала удалите кэш, затем обновите базу данных.

  3. Сначала обновите базу данных, затем удалите кеш

Вариант 1: при одновременном выполнении порядок выполнения не может быть гарантирован.Возможно, A сначала обновляет базу данных, а B обновляет базу данных позже, но сначала обновляет кеш

​ Если заблокировать, то этого можно избежать, но пропускная способность снизится, что можно считать по бизнес-сценарию

Сценарий 2: Причина, по которой этот сценарий приведет к несогласованности, заключается в следующем. В то же время есть запрос A на операцию обновления и другой запрос B на операцию запроса. Тогда произойдет следующая ситуация: (1) Запрос A на выполнение операции записи и удаление кеша (2) Запросите B сделать запрос и обнаружить, что кэш не существует. (3) Запросите B запросить базу данных, чтобы получить старое значение (4) Запросить B записать старое значение в кеш (5) Запрос A на запись нового значения в базу данных

Так что используйте:Используйте стратегию отложенного двойного удаленияТо есть ключ удаляется после входа в логику, после завершения операции ключ удаляется после задержки.

Вариант 3: Обновите базу данных — удалите кеш Сценарии, которые могут вызвать проблемы:

(1) Кэш просто не работает (2) Запрос A на запрос к базе данных и получение старого значения (3) Запросить B записать новое значение в базу данных (4) Запрос B на удаление кеша (5) Запрос A записать найденное старое значение в кеш

Врожденные требования: операция чтения второго шага запроса занимает больше времени, чем операция обновления, а условия более строгие.

Но что, если это произойдет?

A. Установите разумный срок действия ключа

B. Клавиша удаления асинхронной задержки

Q12: Как убедиться, что данные в Redis являются горячими данными

A. Данные точки доступа могут быть загружены вручную или активно

Б. У Redis есть собственная стратегия удаления данных:

Когда размер набора данных памяти Redis возрастет до определенного размера, будет реализована стратегия устранения данных (стратегия повторного использования). Redis предлагает 6 стратегий удаления данных:

  1. volatile-lru: выберите данные из набора данных (server.db[i].expires), которые использовались наименее недавно, с установленным временем истечения срока действия.
  2. volatile-ttl: выберите данные, срок действия которых истекает, из набора данных (server.db[i].expires), в котором установлено время истечения срока действия.
  3. volatile-random: произвольный выбор удаления данных из набора данных с установленным временем истечения срока действия (server.db[i].expires)
  4. allkeys-lru: выбрать наименее использованные данные из набора данных (server.db[i].dict) для исключения
  5. allkeys-random: Случайный выбор данных из набора данных (server.db[i].dict) для исключения
  6. no-enviction: запретить удаление данных

Q13: Как решить проблему конкурентной борьбы Redis?

即多线程同时操作统一Key的解决办法:

Redis为单进程单线程模式,采用队列模式将并发访问变为串行访问。Redis本身没有锁的概念,Redis对于多个客户端连接并不存在竞争,但是在Jedis客户端对Redis进行并发访问时会发生连接超时、数据转换错误、阻塞、客户端关闭连接等问题,这些问题均是由于客户端连接混乱造成

对此有多种解决方法:
A:条件允许的情况下,请使用redis自带的incr命令,decr命令
B:乐观锁方式
watch price
get price $price
$price = $price + 10
multi
set price $price
exec

C:针对客户端,操作同一个key的时候,进行加锁处理
D:场景允许的话,使用setnx 实现

Вопрос 14: Как работает процесс утилизации Redis?Какой алгоритм использует Redis?

Как упоминалось в вопросе 12, когда требуемый объем памяти превышает настроенный максимальный объем памяти, Redis активирует правило исключения данных.

Правило по умолчанию: # maxmemory-policy noeviction

То есть разрешено только чтение, и нельзя продолжать добавлять ключи

Поэтому часто необходимо настроить стратегию исключения, такую ​​как алгоритм LRU.

LRU算法最为精典的实现,就是HashMap+Double LinkedList,时间复杂度为O(1)

Q15: Redis добавляет данные большими партиями

Справочная статья:woo woo woo.cn blog on.com/Patrick l IU/…

В конвейерном режиме команда для запуска выглядит следующим образом:

cat data.txt | redis-cli --pipe

текст data.txt:

SET Key0 Value0
SET Key1 Value1
...
SET KeyN ValueN

# 或者是 RESP协议内容 - 注意文件编码!!!

*8
$5
HMSET
$8
person:1
$2
id
$1
1

Это приведет к выводу, подобному этому:

All data transferred. Waiting for the last reply...
Last reply received from server.
errors: 0, replies: 1000000

Утилита redis-cli также гарантирует, что в стандартный вывод перенаправляются только ошибки, полученные от экземпляра Redis.

Демо:

cat redis_commands.txt | redis-cli -h 192.168.127.130 -p 6379 [-a "password"] -n 0 --pipe

All data transferred.Waiting for the last reply...
Last reply received from server.
errors:0,replies:10000000

mysql数据快速导入到redis 实战:Детали файла: см. Redis-канал боя

Сообщение блога:woohoo.cn blog.com/Tommy-yellow…

# 1.准备一个table
create database  if not exists `test`;
use `test`;
CREATE TABLE `person` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(200) NOT NULL,
  `age` varchar(200) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

# 2.插入七八万条数据

# 3.SQL查询,将其转化为 RESP协议命令   Linux 版本: -> 不要在windows环境试,没啥意义
SELECT CONCAT(
   "*8\r\n",
   '$',LENGTH(redis_cmd),'\r\n',redis_cmd,'\r\n',
   '$',LENGTH(redis_key),'\r\n',redis_key,'\r\n',
   '$',LENGTH(hkey1),'\r\n',hkey1,'\r\n','$',LENGTH(hval1),'\r\n',hval1,'\r\n',
   '$',LENGTH(hkey2),'\r\n',hkey2,'\r\n','$',LENGTH(hval2),'\r\n',hval2,'\r\n',
   '$',LENGTH(hkey3),'\r\n',hkey3,'\r\n','$',LENGTH(hval3),'\r\n',hval3,'\r'
)FROM(
   SELECT 'HMSET' AS redis_cmd,
   concat_ws(':','person', id) AS redis_key,
   'id' AS hkey1, id AS hval1,
   'name' AS hkey2, name AS hval2,
   'age' AS hkey3, age AS hval3
   From person
)AS t

# 4.如果用的就是线上数据库+线上Linux -> 把sql存到 order.sql,进行执行
mysql -uroot -p123456 test --default-character-set=utf8 --skip-column-names --raw < order.sql  
|
redis-cli -h 127.0.0.1 -p 6379 -a 123456 --pipe

# 5.本地数据库+线上redis
利用Navicat导出数据 -> data.txt,清理格式(导出来的数据里面各种 " 符号),全局替换即可
cat data.txt | redis-cli -h 127.0.0.1 -p 6379 -a 123456  --pipe

81921条数据 一瞬间导入完成

注意事项: RESP协议要求,不要有莫名其妙的字符,注意文件类型是Unix编码类型

Q16: Расширение: Фильтр Блума

Структуры данных и алгоритмы / Фильтр Блума

Реализация Redis

Плагин фильтра Блума доступен для Redis 4.X и выше.

Установите плагин свечения redis в Centos:blog.CSDN.net/U013030276/…

грамматика:[bf.add key options]

Синтаксис: [ключевые параметры bf.exists]

Уведомление:redis 布隆过滤器提供的是 最大内存512M,2亿数据,万分之一的误差率

Q17: Сценарий Lua связан

Преимущества использования Lua-скриптов:

  • Уменьшите нагрузку на сеть. Несколько запросов могут быть отправлены одновременно в виде сценариев, чтобы уменьшить задержку в сети.
  • Атомарная операция, Redis выполнит весь скрипт как единое целое и не будет вставлен другими командами посередине. Поэтому не нужно беспокоиться о состоянии гонки в процессе написания скриптов, и нет необходимости использовать транзакции
  • Повторное использование, сценарий, отправленный клиентом, будет постоянно храниться в Redis, чтобы другие клиенты могли повторно использовать этот сценарий без использования кода для выполнения той же логики.
@RequestMapping("/testLua")
public String testLua () {

    String key   = "mylock";
    String value = "xxxxxxxxxxxxxxx";

    //        if redis.call('get', KEYS[1]) == ARGV[1]
    //            then
    //                return redis.call('del', KEYS[1])
    //        else
    //            return 0
    //        end

    // lua脚本,用来释放分布式锁 - 如果使用的较多,可以封装到文件中, 再进行调用
    String luaScript = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end";
    Object eval = jedis.eval(luaScript, Collections.singletonList(key), Collections.singletonList(value));
    return eval.toString();
}

Q18: Связано с производительностью — анализ медленных запросов Redis

Команда redis будет помещена во встроенную очередь redis, а затем основной поток будет выполняться один за другим, поэтому одна из команд будет выполняться слишком долго, что вызовет пакетную блокировку.

命令:slowlog get Получить записи медленных запросов slowlog len Получить количество записей медленных запросов (Очередь медленных запросов работает по принципу «первым пришел — первым обслужен», поэтому при заполнении новых значений старые будут уходить)

Медленный запрос Redis -> фаза выполнения занимает слишком много времени

conf文件设置: slowlog-low-slower-than 10000 -> 10000 микросекунд, 10 миллисекунд (по умолчанию) 0 -> логировать все команды -1 -> не записывать команды Максимальное количество записей, хранящихся в slow-max-len

慢查询导致原因: value 值过大,解决办法:Сегментация данных (более детальное хранение данных)

Q19: Как повысить эффективность обработки Redis?Пакетная обработка Конвейерная обработка на основе Jedis

Jedis jedis = new Jedis("127.0.0.1", 6379);
Pipeline pipelined = jedis.pipelined();
for (String key : keys) {
    pipelined.del(key);
}

pipelined.sync();
jedis.close();

// pipelined 实际是封装过一层的指令集 ->  实际应用的还是单条指令,但是节省了网络传输开销(服务端到Redis环境的网络开销)

Наконец

Эта статья представляет собой большой сборник.Должно быть в середине ссылки на многие чужие статьи или картинки.Однако из-за длительного периода времени записи о них на тот момент не было.Прошу прощения за это.Если есть автор находит свою статью или картинку, вы можете пообщаться со мной в частном порядке, и я добавлю больше.

Если вы обнаружите, что пишете неплохо, можете поискать в публичном аккаунте»это Кервин", совершенствуйтесь вместе!

также посмотретьДомашняя страница Кервина на GitHub