Redis の基本的な使い方と高度な知識

Redis の基本的な使い方と高度な知識

Redis は、キーと値のペア key と value を使用してデータを保存する非リレーショナル データベースです。そのデータはメモリに保存されるため、読み取りと書き込みの効率が高くなります。一般的に使用されるシナリオには、次のようなものがあります: 大量のデータの読み取りと書き込み、大量のデータ同時読み取りと書き込み、データのキャッシュなど。

1. 基本的なデータ型

Redis データベースには 5 つの基本データ型があり、Redis の新しいバージョンでは 3 つの新しいデータ型 、 、 が追加されています。BitmapsこれらHyperLogLogについてGeospatialはここでは説明しませんが、5 つの基本データ型について簡単に説明するだけです。

1.String

字符串类型,存储的 value 数据为字符串。

2.List

列表类型,存储的 value 数据为一个列表,有序列表,其数据排列的顺序与数据添加的顺序相同。

3.Hash

哈希类型,存储的 value 数据为一个对象,对象内也是采用 key 和 value 进行存储数据的,类似于Java中的 map 数据类型或者Python中的字典 dict 类型。

4.Set

集合类型,存储的 value 数据为一个集合,该集合是 无序 的,集合中不允许有重复值,会自动去重。

5.Zset

有序集合类型,存储的 value 数据也是集合,该集合是 `有序` 的,通过给每个 value 设置 score 值,按照每个 value 的 score 值进行排序,同时该集合也是不包含重复值的,自动去重。

2. 基本的な操作コマンド

1.String

String 文字列型での一般的なコマンド操作

# 设置key为k1,值为10
set k1 10

# 获取key为k1的值
get k1

# 对key为k1的value值进行+1
incr k1

# 对key为k1的value值进行+20
incrby k1 20 

# 对key为k1的value值进行-1
decr k1

# 对key为k1的value值进行-20
decrby k1 20 

# 设置k1的过期时间为20s
expire k1 20

# 设置k2的值为v2,过期时间为30s
setex k2 30 v2

# 查看k2的过期时间(-1表示永久有效,-2表示已失效,其他数字表示剩余过期时间)
ttl k2

# 设置k2的值为v2,若k2已存在,则不设置,否则设置。
setnx k2 v2

# 同时设置多个key和value
mset k1 v1 k2 v2

# 同时获取多个key的value
mget k1 k2

2.List

List リスト型での共通コマンド操作

# 从左边依次添加数据至t1列表中,结果为 3 2 1
lpush t1 1 2 3

# 从右边依次添加数据至t2列表中,结果为 1 2 3
rpush t2 1 2 3

# 从t1列表中获取索引从0到-1的所有value值,索引0代表第一个,索引-1代表最后一个
lrange t1 0 -1

# 从左边依次删除t1列表中的值
lpop t1

# 从右边依次删除t1列表中的值
rpop t1

# 获取t1列表的长度
llen t1

3.Hash

ハッシュ型での一般的なコマンド操作

# 设置key为k1中的id值等于1001,一次只能设置一个
hset k1 id 1001

# 设置key为k1中的name=lucy,age=20,一次可以设置多个值
hmset k1 name lucy age 20

# 获取k1中id的值
hget k1 id

# 一次性获取k1中的id、name、age值
hmget k1 id name age

# 查看key为k1中的所有属性key 结果-> id name age
hkeys k1

# 查看key为k1中的所有属性key所对应的值 结果-> 1001 lucy 20
hvals k1

# 对key为k1中的age值+2
hincrby k1 age 2

4.Set

Set コレクション タイプでの一般的なコマンド操作

# 添加 1 2 3 元素到t1集合中
sadd t1 1 2 3

# 删除t1集合中的3元素
srem t1 3

# 查看t1集合中是否包含4这个元素
sismember t1 4

# 查看t1集合中的所有元素
smembers t1

5.Zset

Zset 順序付きコレクション型での一般的なコマンド操作

# 添加 java c++ php 到t1集合中,并指定相应的score值为 100 200 300
zadd t1 100 java 200 c++ 300 php

# 删除t1集合中的java元素
zrem t1 java

# 查看t1集合中索引从0到-1的所有元素(索引0代表第一个元素,索引-1代表最后一个元素)
# 结果 "java" "c++" "php" (按照score值进行从小到大排序)
zrange t1 0 -1

# 查看t1集合中索引从0到-1的所有元素,并显示相应的score值。
# 结果 "java" 100 "c++" 200 "php" 300
zrange t1 0 -1 withscores

# 查看t1集合中索引从0到-1的所有元素,并按倒序(从大到小)排序
# 结果 "php" "c++" "java"
zrevrange t1 0 -1

# 查看t1集合中索引从0到-1的所有元素,按倒序(从大到小)排序,并显示相应的score值。
# 结果 "php" 300 "c++" 200 "java" 100
zrevrange t1 0 -1 withscores

他の一般的なコマンドを補足する

# 查看符合正则表达式的所有key -> (keys pattern)
# 查看所有的key
keys *

# 删除对应的key
del key

# 设置key的过期时间为20s
expire key 20

# 查看key的过期时间(-1表示永久有效,-2表示已失效,其他数字表示剩余过期时间)
ttl key

3. 高度な知識

1. データの永続性

Redis のデータはメモリに書き込まれるため永続化されず、サーバーを再起動するとデータが失われるため、データを永続化してディスクに書き込む必要があります。

  • RDB模式: ユーザーが設定した時間間隔に従って、条件を満たすデータをバックアップ用ディスクに書き込みます。

    長所と短所: 効率は高いですが、最後の時間間隔のデータが失われる可能性があります。

  • AOF模式: すべての書き込み操作をログ ファイルに記録し、サーバーの再起動時にログ ファイルに従ってデータを復元します。

    長所と短所: データの信頼性を完全に保証できますが、データの回復が比較的遅くなります。

2. マスター/スレーブ レプリケーション

1 つのサーバーはマスター サーバーとして機能し、書き込み操作のみを担当し、他のサーバーはマスター サーバーのスレーブ サーバーとして機能し、データの読み取りのみを担当します。

利点: 読み取りと書き込みの分離、災害復旧、高速復旧

欠点: レプリケーション遅延 (スレーブ同期データには一定の遅延があります)

  • 一仆二主: 1 つのマスターが複数のスレーブに接続されています

  • 薪火相传: マスターとスレーブが接続され、スレーブの配下にスレーブが接続されます。

  • 反客为主: マスター マシンがダウンすると、コマンドを入力することでスレーブ マシンの 1 台がマスター マシンにslaveof no oneアップグレードします(センチネル モードを使用して自動的にアップグレードすることもできます)

    アクションが完了しました)

  • 哨兵模式: マスターの実行ステータスを監視し、マスターがダウンしている場合は、スレーブの 1 つをマスターにアップグレードします。

3. クラスター

クラスタはサービスの高可用性を確保するためのもので、一部のサーバーがダウンしてもサービスを継続して提供できます。

アドバンテージ:

1.容量不足の問題を解決できます。

  	  2. 能够解决高并发读写的问题,分摊服务器压力。
  	  2.  去中心化配置(任何一台服务器都可以作为入口服务器来进行读写)

4. キャッシュの侵入

キャッシュの侵入とは、存在しないデータをクエリするときに、Redis がミスするため、データがデータベース内でクエリされることを意味します。データベースでデータをクエリできない場合、データはキャッシュに書き込まれず、その結果、データが存在しなくなります。毎回データがクエリされるため、データベースにアクセスし、キャッシュの侵入が発生します。

解決:

  1. クエリされた null 値をキャッシュに設定します (有効期限を設定します)。
  2. アクセス可能なホワイトリストを設定する
  3. ブルームフィルター

5. キャッシュの内訳

キャッシュのブレークダウンとは、一部の人気のあるキーがアクセスされると、その時点でキーの有効期限が切れ、その結果データベースへの大量のリクエストが発生し、データベースがダウンすることを意味します。

6. キャッシュ雪崩

キャッシュなだれとは、非常に短期間に、クエリされた多数のキーの有効期限が切れ、その結果、データベースへの大量のリクエストが発生し、データベースがダウンすることを意味します。

7. 分散ロック

分散ロックにより、スナップアップやスパイクなどの同期操作が保証され、過剰販売などの問題が発生しないことが保証されます。JAVAコードは次のとおりです。

public class SellServiceImpl implements SellService {
    
    

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 库存总量
     */
    private static final Integer TOTAL = 1000;

    /**
     * 例如国庆大甩卖 图书大甩卖 库存 1000 件
     * 存放商品信息
     */
    static Map<String, Integer> products;

    /**
     * 抢购成功者信息
     */
    static Map<String, String> orders;

    static {
    
    
        products = new HashMap<>();
        orders = new HashMap<>();
        // 设置商品名称及库存
        products.put("book", TOTAL);
    }

    /**
     * 第一种方法 synchronized 锁机制,解决高并发产生的超卖问题 但效率大大降低 不推荐使用
     * 第二种方法 使用 Redis 分布式锁,解决高并发产生的超卖问题 并且效率相对高很多
     */
    @Override
    public String orderGoods(String productId) {
    
    
        String lockValue = UUID.randomUUID().toString();
        // 设置锁,并设置3s过期时间,防止手动释放锁之前程序出错,导致锁一直未释放。
        Boolean lock = redisTemplate.opsForValue().setIfAbsent("lock", lockValue, 3, TimeUnit.SECONDS);
        // 加锁失败 说明有人正在使用
        if (!lock) {
    
    
            return "抢购失败,请再试试吧...";
        }
        //先获取商品余量
        int number = products.get(productId);
        if(number <= 0){
    
    
            return "商品已抢购完,请您下次再来,谢谢您的理解...";
        }else {
    
    
            //模拟下单(不同用户拥有不同ID)
            orders.put(UUID.randomUUID().toString(), productId);
            //减库存
            number = number - 1;
            //模拟延迟
            try {
    
    
                Thread.sleep(200);
            } catch (InterruptedException e) {
    
    
                e.printStackTrace();
            }
            products.put(productId, number);
        }
        log.info("共抢购 {} 件,抢购详情:{}", orders.size(), orders);
        // 手动解锁
        String value = (String) redisTemplate.opsForValue().get("lock");
        // 确保释放的锁是同一次设置的锁
        if (lockValue.equals(value)){
    
    
            redisTemplate.opsForValue().getOperations().delete("lock");
        }
        return "抢购成功!";
    }

    @Override
    public String queryGoods(String productId) {
    
    
        return "国庆图书大甩卖,库存 " +
                TOTAL + " 件,现余 " +
                products.get(productId) + " 件,已被抢购 " +
                orders.size() + " 件";
    }
}

4、Redis 統合 SpringBoot の使用

1. 依存関係を導入する

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

2.YMLファイルを設定する

spring:
  redis:
    host: 127.0.0.1
    port: 6379
    password: 123456
    database: 0

3. RedisTemplate の構成

RedisTemplate は構成なしで使用することもできますが、キーと値はシリアル化されないため、Redis データベースに保存されるデータは 16 進エンコード形式になります。

package cn.quicklyweb.flea.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/**
 * 自定义RedisTemplate
 */
@Configuration
public class RedisTemplateConfig {
    
    

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
    
    
        // 创建RedisTemplate实例
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        
		// 创建Redis的String字符串序列化对象
        RedisSerializer<String> stringSerializer = new StringRedisSerializer();
        // 创建Redis的Json字符串序列化对象
        GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
        
        // key采用String的序列化方式
        redisTemplate.setKeySerializer(stringSerializer);
        // hash的key也采用String的序列化方式
        redisTemplate.setHashKeySerializer(stringSerializer);
        // value采用Jackson的Json序列化方式
        redisTemplate.setValueSerializer(genericJackson2JsonRedisSerializer);
        // hash的value也采用Jackson的Json序列化方式
        redisTemplate.setHashValueSerializer(genericJackson2JsonRedisSerializer);
        
		// 设置默认的序列化器为Jackson的Json序列化方式
        redisTemplate.setDefaultSerializer(genericJackson2JsonRedisSerializer);
        
		// 设置连接工厂
        redisTemplate.setConnectionFactory(factory);

        return redisTemplate;
    }
}

4.使用する

// 直接注入后便可操作Redis数据库了
@Autowired
private RedisTemplate redisTemplate

redisTemplate.opsForValue.set("key", "value")
redisTemplate.opsForValue.get("key")

おすすめ

転載: blog.csdn.net/L28298129/article/details/122146148