Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Jhipster Cacahe Demo #54

Open
llccing opened this issue Jun 6, 2023 · 0 comments
Open

Jhipster Cacahe Demo #54

llccing opened this issue Jun 6, 2023 · 0 comments

Comments

@llccing
Copy link
Owner

llccing commented Jun 6, 2023

A new Repo to practise, https://github.com/llccing-demo/jhipster-redis-demo

Jhipster Redis Demo

Simple start

  1. Initialize the project.
    Follow the jhipster CLI

  2. 启动项目

# 注意,先启动 Redis,通过 docker 启动,命令如下:
docker-compose -f redis.yml -d

# 然后启动后端,这个命令同时也会 build 前端, Run your Spring Boot application:
./gradlew

# Start your Webpack development server with:
npm start
  1. simple try cache
    llccing-demo/jhipster-redis-demo@3c0d2c4
  • Define cacheName in CacheConfiguration.java
  • Cache the userList in UserService.java

通过上面两个步骤,即可实现 userList 的缓存,不过当前的缓存时间是1 hour,这个时间处理需要考虑一下。如果能够永不过期,然后异步更新其中的值,这样缓存永不过期,那么api永远是高性能的。

如果仅仅使用 @Cacheable 注解,这个例子实现起来还是很简单的,只不过如果过期时间是固定的,也应该有 update cache 的 logic。

Use Redisson client

Follow this article (https://dzone.com/articles/quickstart-how-to-use-spring-cache-on-redis) to define the Redisson client.

实验逻辑参照(https://www.51cto.com/article/743175.html)

llccing-demo/jhipster-redis-demo@7cd3ef9

Add Redisson simple demo

Try custom cache strategy

llccing-demo/jhipster-redis-demo@1c35d5b

使用 Async 注解来实现异步写入 Redis,这里需要注意 Transactional 和 Async 一起使用的问题([https://ynfatal.github.io/2018/11/02/SpringBoot2/SpringBoot2第二十四篇(三)@Async与事务/](https://ynfatal.github.io/2018/11/02/SpringBoot2/SpringBoot2%E7%AC%AC%E4%BA%8C%E5%8D%81%E5%9B%9B%E7%AF%87(%E4%B8%89)@Async%E4%B8%8E%E4%BA%8B%E5%8A%A1/))。

原本想利用 Redis 实现持久缓存,每次前端调用 api 都从缓存取结果,但是仔细想有个漏洞,如果如果用户通过其他方式更新了db数据,但是redis中没有缓存到,那么API会从Redis拿到空值并返回,然后异步更新Redis,那么用户下次刷新才能拿到新的值,这样也不合理。

所以如果这么做,需要确保所有更新DB的逻辑,同时异步的去更新 Redis;如果这样实现,需要仔细过一遍项目中的api,看哪些涉及了更新DB的逻辑。当然因为我们用 agent rpc (需要学习这两种技术,暂时是了解的范畴)所以很多涉及到用 command 的方式执行,所以也许只要处理几处 command 执行的函数就能够实现全部 更新DB同时异步更新Redis的逻辑。这里还需要去确认下。

Summary

对于Cache算是有个入门的了解,但是如果使用是最佳实践,还是需要时间去积累经验。

Other examples

@Override
public boolean doSecKill(String uid, String productId) {
    //1、uid和productId非空判断
    if (uid == null || productId == null) {
        return false;
    }

    //2、拼接key
    String kcKey = "sk:" + productId + ":qt";   //库存
    String userKey = "sk:" + productId + ":user";  //秒杀成功的用户

    //3、获取库存
    String kc = String.valueOf(redisTemplate.opsForValue().get(kcKey)) ;
    if (kc == null) {
        System.out.println("秒杀还没有开始,请等待");
        return false;
    }

    //4、判断用户是否已经秒杀成功过了
    if (redisTemplate.opsForSet().isMember(userKey, uid)) {
        System.out.println("已秒杀成功,不能重复秒杀");
        return false;
    }
    //5、如果库存数量小于1,秒杀结束
    if (Integer.parseInt(kc) <=0) {
        System.out.println("秒杀结束");
        return false;
    }

    //6、秒杀过程
    redisTemplate.opsForValue().decrement(kcKey);  //库存数量减1
    redisTemplate.opsForSet().add(userKey, uid);
    System.out.println("秒杀成功。。。");
    return true;
}

Tips

Only use Redisson

https://www.jianshu.com/p/e9b26c743cae

if we can use redis like the link example, we can do more things.

Redis command

# connected to Redis in Docker
docker exec -it xxxID redis-cli

# show all the keys in Reids
KEYS *

# return 'OK' if the cache was successfully cleared.
FLUSHALL 

# return the type of key
type key

# get hash value 
hgetall key

Java 乐观锁、悲观锁

https://segmentfault.com/a/1190000016611415

  • 乐观锁,乐观的认为操作不会产生并发问题,不上锁;但是会判断其他线程在这之前 是否对数据进行了修改。可以使用 版本号机制或者 CAS (compare and swap) 算法
  • 悲观锁,总是假设最坏的情况,每次取数据时都认为其他线程会修改,所以会加(悲观)锁。加锁后,不同线程同时执行时,只能有一个线程执行,其他线程在入口处等待,直到锁被释放。悲观锁在 MySQL 和 Java 中有广泛使用
    • MySQL 的读锁、写锁、行锁 etc.
    • Java 的 synchronized 关键字。
  • 读得多,冲突几率小,乐观锁。写得多,冲突几率大,悲观锁。

Postman 压力测试

https://www.cnblogs.com/zjdxr-up/p/14604417.html

postman 的test选项支持压力测试。

Redisson

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant