{"id":19889343,"url":"https://github.com/codeprometheus/springboot-the-avengers","last_synced_at":"2026-04-07T20:31:31.152Z","repository":{"id":104067209,"uuid":"288228730","full_name":"CodePrometheus/SpringBoot-The-Avengers","owner":"CodePrometheus","description":"Java Practice Projects \u0026\u0026 Spring Boot, Practical Learning Cases. Integrated learning records with current technologies","archived":false,"fork":false,"pushed_at":"2021-10-21T14:36:44.000Z","size":7075,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-01-03T22:55:57.748Z","etag":null,"topics":["idempotent","jwt","jwt-springboot","lock","nginx","rabbitmq","redis","springboot","swagger","zookeeper"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/CodePrometheus.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-08-17T16:19:33.000Z","updated_at":"2023-03-13T17:03:15.000Z","dependencies_parsed_at":null,"dependency_job_id":"4d5359c1-3f77-4539-8d2d-a66253ce73a5","html_url":"https://github.com/CodePrometheus/SpringBoot-The-Avengers","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/CodePrometheus/SpringBoot-The-Avengers","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CodePrometheus%2FSpringBoot-The-Avengers","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CodePrometheus%2FSpringBoot-The-Avengers/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CodePrometheus%2FSpringBoot-The-Avengers/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CodePrometheus%2FSpringBoot-The-Avengers/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/CodePrometheus","download_url":"https://codeload.github.com/CodePrometheus/SpringBoot-The-Avengers/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CodePrometheus%2FSpringBoot-The-Avengers/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31528279,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-07T16:28:08.000Z","status":"ssl_error","status_checked_at":"2026-04-07T16:28:06.951Z","response_time":105,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["idempotent","jwt","jwt-springboot","lock","nginx","rabbitmq","redis","springboot","swagger","zookeeper"],"created_at":"2024-11-12T18:09:51.400Z","updated_at":"2026-04-07T20:31:31.123Z","avatar_url":"https://github.com/CodePrometheus.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"SpringBoot-The-Avengers\n======\nSpringboot与时下最新流行技术的整合学习记录\n\u003cbr/\u003e\n以及Java相关技术点的实现\n\n#### I can do this all day.\n\n#### I am Iron Man\n\n![image](https://pic4.zhimg.com/80/v2-93f36044d20d3b3c8803474d96c8e1ad_1440w.jpg?source=1940ef5c)\n\n![image](https://pic2.zhimg.com/80/v2-d04ec9628faf75b94ffa7c349d0847dc_1440w.jpg?source=1940ef5c)\n\n🔥 I love you three thousand\n\n---\n\n## 简介\n\n该仓库为SpringBoot2.x与其他相关技术的整合\n\n## 内容\n\n#### Springboot + RabbitMQ\n\n- RabbitMQ常用几大模型的使用，包括Hello World,Work queues,Routing,Topics\n- Springboot整合MQ的使用\n\n#### Springboot + JWT\n\n- JWT前后端分离系统的认证方案，单点登录系统的认证\n- JWT整合Springboot完成认证以及认证优化\n- 基于客户端的存储认证标记的解决方案\n\n#### Springboot + Swagger\n\n- swagger3的使用，加入Token授权相关\n- http://localhost:8080/swagger-ui/index.html\n\n#### Springboot + Redis\n\n- 基于注解与Token方案实现接口幂等性\n- 一次和多次请求某一个资源对于资源本身应该具有同样的结果（网络超时等问题除外）。也就是说，其任意多次执行对资源本身所产生的影响均与一次执行的影响相同\n\n#### 一致性哈希的实现\n\n- 虚拟节点处理哈希偏斜问题\n\n#### 线程池异步记录日志\n\n- 切面实现\n\n#### Springboot + Mybatis\n\n- 单表查询\n- 多表查询 (一对一，一对多，分步查询)\n- 分页查询\n\n#### Springboot + zookeeper\n\n- 2n+1台server，只要有n+1台就可以使用，若server少于一半集群整体失效\n\n#### Zookeeper实现分布式锁\n\n- 分布式锁是控制分布式系统之间同步访问共享资源的一种方式。如果不同的系统或是同一个系统的不同主机之间共享了一个或一组资源，\n  那么访问这些资源的时候，往往需要通过一些互斥手段来防止彼此之间的干扰，以保证一致性，在这种情况下，就需要使用分布式锁了。\n\n**排他锁**\n\n- 排他锁的核心是如何保证当前有且仅有一个事务获得锁，并且锁被释放后，所有正在等待获取锁的事务都能够被通知到。\n- 在通常的 Java 开发编程中，有两种常见的方式可以用来定义锁，分别是 synchronized 机制和JDK5提供的 ReentrantLock。然而，在 ZooKeeper 中，没有类似于这样的 API 可以直接使用，而是通过\n  ZooKeeper 上的数据节点来表示一个锁，例如 /exclusive_ lock/lock 节点就可以被定义为一个锁。\n- 在需要获取排他锁时，所有的客户端都会试图通过调用 create() 接口， 在 /exclusive_ lock 节点下创建临时子节点 /exclusive_ lock/lock。ZooKeeper\n  会保证在所有的客户端中，最终只有一个客户端能够创建成功，那么就可以认为该客户端获取了锁。同时，所有没有获取到锁的客户端就需要到 /exclusive_ lock 节点上注册一个子节点变更的 Watcher 监听，以便实时监听到 lock\n  节点的变更情况。\n- /exclusive_ lock/lock 是一个临时节点，因此在以下两种情况下，都有可能释放锁。\n    - 当前获取锁的客户端机器发生宕机，那么 ZooKeeper 上的这个临时节点就会被移除。\n    - 正常执行完业务逻辑后，客户端就会主动将自己创建的临时节点删除。\n- 无论在什么情况下移除了 lock 节点，ZooKeeper 都会通知所有在 /exclusive_ lock 节点上注册了子节点变更 Watcher 监听的客户端。这些客户端在接收到通知后，再次重新发起分布式锁获取。\n\n**共享锁**\n\n- 共享锁和排他锁最根本的区别在于，加上排他锁后，数据对象只对一个事务可见，而加上共享锁后，数据对所有事务都可见。\n- 和排他锁-样，同样是通过 ZooKeeper 上的数据节点来表示一个锁，是一个类似于 /shared_ lock/[Hostname]-请求类型-序号 的临时顺序节点，例如 /shared_ lock/\n  192.168.0.1-R-0000000001，那么，这个节点就代表了一个共享锁\n- 根据共享锁的定义，不同的事务都可以同时对同一个数据对象进行读取操作，而更新操作必须在当前没有任何事务进行读写操作的情况下进行。基于这个原则，我们来看看如何通过 ZooKeeper 的节点来确定分布式读写顺序，大致可以分为如下4个步骤。\n    - 创建完节点后，获取 /shared_lock 节点下的所有子节点，并对该节点注册子节点变更的 Watcher 监听。\n    - 确定自己的节点序号在所有子节点中的顺序。\n    -\n    对于读请求：如果没有比自己序号小的子节点，或是所有比自己序号小的子节点都是读请求，那么表明自己已经成功获取到了共享锁，同时开始执行读取逻辑。如果比自己序号小的子节点中有写请求，那么就需要进入等待。对于写请求：如果自己不是序号最小的子节点，那么就需要进入等待。\n    - 接收到 Watcher 通知后，重复步骤1。\n\n**羊群效应**\n\n- 一个特定的znode 改变的时候ZooKeeper 触发了所有watches 的事件。\n- 举个例子，如果有1000个客户端watch\n  一个znode的exists调用，当这个节点被创建的时候，将会有1000个通知被发送。这种由于一个被watch的znode变化，导致大量的通知需要被发送，将会导致在这个通知期间的其他操作提交的延迟。因此，只要可能，我们都强烈建议不要这么使用watch。仅仅有很少的客户端同时去watch一个znode比较好，理想的情况是只有1个。\n\n#### Zookeeper实现分布式队列\n\n- 分布式队列，简单地讲分为两大类，一种是常规的先入先出队列，另一种则是要等到队列元素集聚之后才统一安排执行的Barrier模型。\n\n**FIFO**\n\n- 使用 ZooKeeper 实现 FIFO 队列，和共享锁的实现非常类似。FIFO 队列就类似于一个全写的共享锁模型，大体的设计思路其实非常简单：所有客户端都会到 /queue_fifo 这个节点下面创建一个临时顺序节点，例如\n  /queue_fifo/192.168.0.1-0000000001。\n- 创建完节点之后，根据如下4个步骤来确定执行顺序。\n    - 通过调用 getChildren() 接口来获取 /queue_fifo 节点下的所有子节点，即获取队列中所有的元素。\n    - 确定自己的节点序号在所有子节点中的顺序。\n    - 如果自己不是序号最小的子节点，那么就需要进入等待，同时向比自己序号小的最后一个节点注册 Watcher 监听。\n    - 接收到 Watcher 通知后，重复步骤1。\n\n**Barrier**\n\n- Barrier\n  原意是指障碍物、屏障，而在分布式系统中，特指系统之间的一个协调条件，规定了一个队列的元素必须都集聚后才能统一进行安排，否则一直等待。这往往出现在那些大规模分布式并行计算的应用场景上：最终的合并计算需要基于很多并行计算的子结果来进行。这些队列其实是在\n  FIFO 队列的基础上进行了增强\n- 大致的设计思想如下：开始时，/queue_barrier 节点是一个已经存在的默认节点，并且将其节点的数据内容赋值为一个数字n来代表 Barrier 值，例如n=10表示只有当 /queue_barrier\n  节点下的子节点个数达到10后，才会打开 Barrier。之后，所有的客户端都会到 /queue_barrier 节点下创建一个临时节点，例如 /queue_barrier/l92.168.0.1。\n\n#### RabbitMQ微服务外卖\n\n#### Starry-Douban\n\n- 仿豆瓣电影搜索引擎\n\n- 前端: Vue + Bootstrap\n- 后端: Spring Boot + ElasticSearch + Jsoup\n\n\u003cimg src=\"./images/image-20210515143659573.png\" alt=\"image-20210515143659573\" style=\"zoom:50%;\" /\u003e\n\n#### Starry-Nginx\n\n- 实现简易版Nginx\n\n- 一致性Hash\n- 轮询\n\n#### Starry-BloomFilter\n\n实现布隆过滤器并于List，Map，Guava进行比较\n\n- 数据量不大，且不能有误差\n\n  那么用List或者Map都可以，虽然说List判断该元素是否存在采用的是遍历集合的方式，在性能在会比Map差，但就像上面测试一样，100万的数据，\n\n  List遍历和Map都不超过1毫秒，选谁不都一样，何必在乎那0.几毫秒的差异。\n\n- 数据量不大，且允许有误差\n\n  这就可以考虑用Google布隆过滤器了，尽管查询数据效率都差不多，但关键是它可以减少内存的开销，这就很关键。\n\n- 数据量大，且不能有误差。\n\n  推荐用Redis的map数据结构来存储数据，这样可以大大减少JVM内存开销，而且不需要每次重启都要往集合中存储数据。\n\n- 数据量大，且允许有误差。\n\n  如果是单体应用，数据量内存也可以接收，那么可以考虑Google布隆过滤器，因为它的查询速度会比redis要快。毕竟它不需要网络IO开销。\n\n  如果是分布式集群架构，或者数据量非常大，那么还是考虑用redis布隆过滤器吧，毕竟它不需要往每一节点都存储数据，而且不占用JVM虚拟机内存。\n\n#### Starry-ELK\n\n- ELk搭建日志收集\n\n#### Starry-MVC\n\n- mvc源码学习\n\n### Starry-Sharding\n\n- 分库分表Demo\n\n### Stream流操作\n\n### Starry-Kafka\n\n实现延迟队列\n\n### Starry-Mongodb\n\nCRUD\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodeprometheus%2Fspringboot-the-avengers","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcodeprometheus%2Fspringboot-the-avengers","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodeprometheus%2Fspringboot-the-avengers/lists"}