[Cache]Mysql(JPA)とRedisの使用


今日はRedisとMysql(JPA)の使い方をご紹介します!

なぜRedisとMysqlをバインドするのですか?


Redisはリポジトリとして使用される場合があります.
DB負荷を軽減したり、迅速に選択したりする場合があります

上の図に示すように、キャッシュ・サーバにクエリーするデータがない場合、データベースは直接クエリーを行います.
IOオペレーションを必要とするDBとは異なり、キャッシュサーバRedisはメモリ・リポジトリであるため、クエリの速度が速い

redis+springfoot+mysql設定


スプリングfootをredisに関連付ける操作前回やったから、今日は前回の仕事に続きましょう!
まずはMySQLでJPAに接続しました
pom.xml
       <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-jpa -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
            <version>2.6.6</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
application.yml
spring:
  jpa:
    hibernate:
      ddl-auto: create
    show-sql: true
  datasource:
    url: jdbc:mysql://localhost:3306/redis
    username: DB 아이디
    password : DB 비밀번호 
    driver-class-name: com.mysql.jdbc.Driver
次に、前回作成したStudioオブジェクトをEntityとして作成します.
Student.java
//@RedisHash("Student")
@Entity
@AllArgsConstructor
@NoArgsConstructor
@ToString
@Setter
public class Student implements Serializable {

    public enum Gender{
        MALE, FEMALE
    }

    @Id
    private String id;
    private String name;
    private Gender gender;
    private int grade;

}
  • idをプライマリキー値
  • に設定.
    注記
  • @RedisHash値(前回はRedisを使用するように設定)
  • シリアル化可能な
  • Redisが継承され、ストレージに使用されます.
    シリアル化は次のように保存されます.

    プロファイルに@EnableCachingを追加してキャッシュを有効にします
    RedisConfig.java
    
    @Configuration
    @EnableCaching
    public class RedisConfig {
        @Bean
        JedisConnectionFactory jedisConnectionFactory() {
    
            RedisStandaloneConfiguration redisConfig = new RedisStandaloneConfiguration();
            redisConfig.setHostName("192.168.0.20");
            redisConfig.setPort(6379);
    
            return new JedisConnectionFactory(redisConfig);
    
        }
    
        @Bean
        public RedisTemplate<String, Object> redisTemplate() {
            RedisTemplate<String, Object> template = new RedisTemplate<>();
            template.setConnectionFactory(jedisConnectionFactory());
            return template;
        }
    }
    
    次に、キャッシュ選択のためのコントローラを作成しました.
    StudentController.class
    @Controller
    public class StudentController {
    
        @Autowired
        StudentRepository studentRepository;
    
        @Cacheable(value = "Student")
        public Student findStudentById(String id){
    
            return studentRepository.findById(id)
                    .orElseThrow(RuntimeException::new);
        }
    
    }
    
    「キャッシュ」(value=「保存する名前」)によるキャッシュ値
  • @Cacheableの許可
  • DBに該当する値がない場合、異常
  • が発生する.

    効果があるかどうか見てみましょう


    値を保存し、値を選択するテストコードを作成しました.
    このとき2回selectを選択して時間を比較した(1回目はDB select、2回目はredis select)
    @SpringBootTest
    @TestInstance(TestInstance.Lifecycle.PER_CLASS)
    public class RedisWithMysqlTest {
    
        @Autowired
        StudentRepository studentRepository;
    
        @Autowired
        StudentController studentController;
    
        @Test
        @Order(1)
        void saveTest(){
            Student student1 = new Student("1", "zzarbttoo1", Student.Gender.FEMALE, 1);
            Student student2 = new Student("2", "zzarbttoo2", Student.Gender.FEMALE, 2);
            Student student3 = new Student("3", "zzarbttoo3", Student.Gender.FEMALE, 3);
            Student student4 = new Student("4", "zzarbttoo4", Student.Gender.FEMALE, 4);
            Student student5 = new Student("5", "zzarbttoo5", Student.Gender.FEMALE, 5);
    
            studentRepository.save(student1);
            studentRepository.save(student2);
            studentRepository.save(student3);
            studentRepository.save(student4);
            studentRepository.save(student5);
    
        }
    
    
        @Test
        @Order(2)
        void selectTest(){
    
            long start1 = System.currentTimeMillis();
    
            System.out.println(studentController.findStudentById("1").toString());
            System.out.println(studentController.findStudentById("2").toString());
            System.out.println(studentController.findStudentById("3").toString());
            System.out.println(studentController.findStudentById("4").toString());
            System.out.println(studentController.findStudentById("5").toString());
    
            long end1 = System.currentTimeMillis();
            System.out.println(end1 - start1);
    
            long start2 = System.currentTimeMillis();
    
            System.out.println(studentController.findStudentById("1").toString());
            System.out.println(studentController.findStudentById("2").toString());
            System.out.println(studentController.findStudentById("3").toString());
            System.out.println(studentController.findStudentById("4").toString());
            System.out.println(studentController.findStudentById("5").toString());
    
            long end2 = System.currentTimeMillis();
    
            System.out.println(end2 - start2);
    
        }
    }
  • @TestInstance(Instance.Lifecycle.PER CLASSのテスト)は、テスト間に影響を与えます.
  • @Orderを使用してテスト間の順序を指定し、saveの後に
  • を選択します.
    selectを初めて選択すると、redisにもの値が格納されています.以下に示します.
    次に、1回目と2回目のselect時間を確認します.

    うわ~
    明らかに、2回目の選択時間は明らかに短縮された.
    (何度でも、1回目だけは時間がかかるので、2回目からは早いので注意してください)

    Redisは本当に万能ですか?(mysqlとの同期の問題)


    しかし、redisをキャッシュサーバとして使用するには大きな問題がある.
    キャッシュ・サーバとデータベースの間で同期できない可能性があります.
    このため、次のテストケースを設計しました.
        @Test
        @Order(3)
        void updateTest(){
    
            Student updateStudent = studentRepository.findById("1").get();
            updateStudent.setName("updated Name");
            studentRepository.save(updateStudent);
    
    
            Student selectStudent = studentRepository.findById("1").get();
            System.out.println(selectStudent.toString());
    
            Student redisStudent = studentController.findStudentById("1");
            System.out.println(redisStudent.toString());
    
        }
    
  • 更新後、データベースから直接選択し、キャッシュ・サーバを使用して選択します.

    更新されていないことを確認します.
    次の記事では、これらの問題を解決する方法について説明します.
    ソース
    https://www.baeldung.com/spring-boot-redis-cache
    https://www.youtube.com/watch?v=92NizoBL4uA