In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-04-11 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
This article introduces the knowledge of "how to implement simple distributed locks in SpringBoot". Many people will encounter this dilemma in the operation of actual cases, so let the editor lead you to learn how to deal with these situations. I hope you can read it carefully and be able to achieve something!
1. Brief introduction
There are many ways to distribute locks, and the usual solutions are:
Based on mysql database, based on redis, based on ZooKeeper
There are many ways to implement it on the Internet. This article mainly introduces how to use mysql to implement a simple distributed lock. The locking process is shown below:
In fact, the general ideas are as follows:
1. Acquire the lock based on a value (that is, my tag here). If the lock does not currently exist, insert a record in the database, then process the business, and release the lock (delete the lock) when it is over.
two。 If there is a lock, determine whether the lock expires, update the validity period of the lock if it expires, then continue to process the business, and release the lock when it ends. If it does not expire, then the acquisition of the lock fails and exits.
two。 Database design
2.1 introduction to the data sheet
The database table is automatically generated by JPA, and the entities will be introduced later, as follows:
CREATE TABLE `lock_ info` (`id` bigint (20) NOT NULL, `status` datetime NOT NULL, `status` int (11) NOT NULL, `tag` varchar (255) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `uk_ tag` (`tag`) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
Where:
Id: primary key tag: lock mark. Take an order as an example, you can lock the order id expiration_time: expiration time status: lock status, 0, unlocked, 1, already locked
3. Realize
This article uses SpringBoot 2.0.3.RELEASE to focus the JPA used by MySQL 8.0.16 orm layer.
3.1 pom
Create a new project and add jpa and mysql dependencies to the project. The complete content is as follows:
4.0.0 org.springframework.boot spring-boot-starter-parent 2.0.3.RELEASE com.dalaoyang springboot2_distributed_lock_mysql 0.0.1-SNAPSHOT springboot2_distributed_lock_mysql springboot2_distributed_lock_mysql 1.8 org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-data-jpa mysql mysql-connector-java runtime org.springframework.boot spring-boot-starter-test test org.projectlombok lombok 1.16.22 provided Org.springframework.boot spring-boot-maven-plugin
3.2 Profil
The configuration file configures the database information and the basic configuration of jpa, as follows:
Server.port=20001## database configuration # # database address spring.datasource.url=jdbc:mysql://localhost:3306/lock?characterEncoding=utf8&useSSL=false## database user name spring.datasource.username=root## database password spring.datasource.password=12345678## database driver spring.datasource.driver-class-name=com.mysql.jdbc.Driver##validate when loading hibernate, verify the creation of database table structure # # create re-create the database table structure each time hibernate is loaded This is the reason for the loss of database table data. # # create-drop created when loading hibernate, exit is deleted table structure # # update loads hibernate automatic update database structure # # validate verifies the structure of the table at startup, no table is created # # none starts without any operation spring.jpa.hibernate.ddl-auto=update## console prints sqlspring.jpa.show-sql=true## to set innodbspring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
3.3 entity class
The entity classes are as follows, where a unique index is set for the tag field to prevent repeated insertion of the same data:
Package com.dalaoyang.entity;import lombok.Data;import javax.persistence.*;import java.util.Date;@Data@Entity@Table (name = "LockInfo", uniqueConstraints= {@ UniqueConstraint (columnNames= {"tag"}, name = "uk_tag")}) public class Lock {public final static Integer LOCKED_STATUS = 1; public final static Integer UNLOCKED_STATUS = 0; / * * Primary key id * / @ Id @ GeneratedValue (strategy = GenerationType.AUTO) private Long id / * * lock indication. Take an order as an example, you can lock the order id * / @ Column (nullable = false) private String tag; / * expiration time * / @ Column (nullable = false) private Date expirationTime; / * lock status, 0, unlocked, 1, has been locked * / @ Column (nullable = false) private Integer status; public Lock (String tag, Date expirationTime, Integer status) {this.tag = tag; this.expirationTime = expirationTime This.status = status;} public Lock () {}}
3.4 repository
The repository layer only adds two simple methods to find locks based on tag and delete locks based on tag, as follows:
Package com.dalaoyang.repository;import com.dalaoyang.entity.Lock;import org.springframework.data.jpa.repository.JpaRepository;public interface LockRepository extends JpaRepository {Lock findByTag (String tag); void deleteByTag (String tag);}
3.5 service
The service API defines two methods to acquire and release the lock, as follows:
Package com.dalaoyang.service;public interface LockService {/ * attempts to acquire the key of the lock * @ param tag lock * @ param expiredSeconds lock expiration time (in seconds). Default is 10s * @ return * / boolean tryLock (String tag, Integer expiredSeconds); / * * release key * @ param tag lock * / void unlock (String tag);}
The implementation class implements the above method, and its content is consistent with the above flow chart. It is not introduced here. The complete content is as follows:
Package com.dalaoyang.service.impl;import com.dalaoyang.entity.Lock;import com.dalaoyang.repository.LockRepository;import com.dalaoyang.service.LockService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import org.springframework.transaction.annotation.Propagation;import org.springframework.transaction.annotation.Transactional;import org.springframework.util.StringUtils;import java.util.Calendar;import java.util.Date;import java.util.Objects;@Servicepublic class LockServiceImpl implements LockService {private final Integer DEFAULT_EXPIRED_SECONDS = 10 Autowired private LockRepository lockRepository; @ Override @ Transactional (rollbackFor = Throwable.class) public boolean tryLock (String tag, Integer expiredSeconds) {if (StringUtils.isEmpty (tag)) {throw new NullPointerException ();} Lock lock = lockRepository.findByTag (tag); if (Objects.isNull (lock)) {lockRepository.save (tag, this.addSeconds (new Date (), expiredSeconds), Lock.LOCKED_STATUS); return true;} else {Date expiredTime = lock.getExpirationTime (); Date now = new Date () If (expiredTime.before (now)) {lock.setExpirationTime (this.addSeconds (now, expiredSeconds)); lockRepository.save (lock); return true;}} return false;} @ Override @ Transactional (rollbackFor = Throwable.class) public void unlock (String tag) {if (StringUtils.isEmpty (tag)) {throw new NullPointerException ();} lockRepository.deleteByTag (tag);} private Date addSeconds (Date date, Integer seconds) {if (Objects.isNull (seconds)) {seconds = DEFAULT_EXPIRED_SECONDS } Calendar calendar = Calendar.getInstance (); calendar.setTime (date); calendar.add (Calendar.SECOND, seconds); return calendar.getTime ();}}
3.6 Test class
Create a test controller for testing, in which a test method is written, and the method will sleep 2 seconds when acquiring the lock, so it is convenient for us to test. The complete content is as follows:
Package com.dalaoyang.controller;import com.dalaoyang.service.LockService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;@RestControllerpublic class TestController {@ Autowired private LockService lockService; @ GetMapping ("/ tryLock") public Boolean tryLock (String tag, Integer expiredSeconds) {return lockService.tryLock (tag, expiredSeconds);} @ GetMapping ("/ unlock") public Boolean unlock (String tag) {lockService.unlock (tag); return true } @ GetMapping ("/ test") public String test (String tag, Integer expiredSeconds) {if (lockService.tryLock (tag, expiredSeconds)) {try {/ / do something / / here sleep is used for two seconds to observe the situation where the lock cannot be obtained Thread.sleep (2000);} catch (Exception e) {} finally {lockService.unlock (tag);} return "acquired the lock successfully, tag is:" + tag } return "current tag:" + tag + "already has a lock, please try again later!" ;}}
3. test
The project is packaged in maven and started with two ports, 20000 and 20001, respectively.
Java-jar springboot2_distributed_lock_mysql-0.0.1-SNAPSHOT.jar-- server.port=20001
Java-jar springboot2_distributed_lock_mysql-0.0.1-SNAPSHOT.jar-- server.port=20000
As shown in the figure, only one request can acquire the lock for the project that accesses the two ports.
4. Summary
The distributed lock implemented in this case is only a simple implementation scheme, and it still has many problems, so it is not suitable for production environment.
That's all for "how to implement simple distributed locks in SpringBoot". Thank you for reading. If you want to know more about the industry, you can follow the website, the editor will output more high-quality practical articles for you!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.