Author: Tommmmm www.jianshu.com/p/ae14101989f2Copy the code
Recommended reading (Click to skip to reading)
1. SpringBoot content aggregation
2. Java interview question content aggregation
3. Design pattern content aggregation
4. Sorting algorithm content aggregation
5. Multi-threaded content aggregation
architecture
Separation of front and rear ends:
The relationship between Nginx and Tomcat can be quickly understood in a few minutes in this article:
https://www.jianshu.com/p/22dcb7ef9172
Supplement:
-
Settings. XML is maven’s global configuration file. The POM.xml file is a local configuration of your project. Settings.xml contains configurations such as local warehouse locations, modifying remote warehouse servers, authentication information, and so on.
-
What Maven does: With Maven, jar packages can be stored only in the “repository”. When the file is needed, the interface to the file can be referenced. There is no need to copy the file to occupy space.
Note: This “Repository” should be the Repository folder in the directory where Maven was installed locally
A distributed lock
Thread lock: When a method or code uses a lock, only one thread executes the method or code segment at a time. Thread locks are only valid within the same JVM, because thread locks are fundamentally implemented by sharing memory between threads. Such as synchronized
Process lock: To control access to a shared resource by multiple processes in the same operating system.
Distributed lock: When multiple processes are not in the same system, a distributed lock is used to control the access of multiple processes to resources.
Distributed locks are generally implemented in three ways:
-
Optimistic database lock;
-
Distributed lock based on Redis;
-
Distributed lock based on ZooKeeper.
Implementation of optimistic locking: Use version identifiers to determine whether the read data is consistent with the data at commit time. Modify the version id after submission, and discard and try again if it is inconsistent.
CAS: You can read this article:
https://www.jianshu.com/p/456bb1ea9627
Distributed lock based on the implementation of Redis :(this system lock is used)
Basic commands:
-
SETNX (SET if Not exist) : Sets the key to value and returns 1 if and only if the key does Not exist. If the given key already exists, SETNX does nothing and returns 0.
-
GETSET: Sets the given key to value and returns the old value of the key. Obtain the old value based on the key, and then set the new value.
-
EXPIRE sets the lifetime for a given key. When the key expires, it will be deleted automatically.
Locking mode:
Jedis here is Java’s integration with Redis
jedis.set(String key, String value, String nxxx, String expx, int time)Copy the code
Wrong locking method 1:
If the program suddenly crashes after executing setnx(), the lock is not set to expire. A deadlock will occur.
Long result = jedis.setnx(Key, value);
ifJedis.expire (Key, expireTime); (result == 1) {// Expire (Key, expireTime); }Copy the code
Wrong locking method 2:
Distributed locks are used with (Key, expiration time) to obtain the expiration time of the lock if it exists, or if it has expired, to obtain the lock and set a new expiration time
Error analysis: Time synchronization between different clients is required.
long expires = System.currentTimeMillis() + expireTime; String expiresStr = String.valueOf(expires); // If the current lock does not exist, success is returnedif (jedis.setnx(lockKey, expiresStr) == 1) {
return true; } String currentValueStr = jedis.get(lockKey);if(currentValueStr ! = null && long.parselong (currentValueStr) < system.currentTimemillis ()) { String oldValueStr = jedis. GetSet (lockKey, expiresStr);if(oldValueStr ! = null && oldValueStr. Equals (currentValueStr)) {// If a thread has the same value as the current one, it has the right to lockreturn true; }} // In other cases, lock failure is returnedreturn false;Copy the code
Unlock: Use jedis.del(lockKey) to release the lock after determining the owner of the lock.
Distributed locks are based on the implementation of Zookeeper
Zookeeper provides a multi-level node namespace (called ZNode). Each node is represented by a path separated by a slash (/), and each node has a parent node (except the root node).
For example, /foo/doo represents a ZNode whose parent is /foo, parent is /, and root has no parent.
The client displays the same view no matter which Server it is connected to. This is the most important performance of ZooKeeper.
At the core of Zookeeper is atomic broadcasting, which ensures synchronization between servers. The protocol that implements this is called the Zab protocol. Zab protocol has two modes: recovery mode (master selection) and broadcast mode (synchronization). Zab goes into recovery mode when the service starts or after the leader crashes, and the recovery mode ends when the leader is elected and most servers have completed state synchronization with the Leader. State synchronization ensures that the leader and Server have the same system state.
Zookeeper uses an incremental transaction ID (ZXID) to identify transactions in order to ensure the consistency of transactions. In this implementation, ZXID is a 64-bit number.
Distributed lock mechanism of Zookeeper
The process for obtaining distributed locks:
-
A temporary sequential node is created under the Locker node (the locker node is the specified node of Zookeeper) when the distributed lock is acquired and deleted when the lock is released.
-
The client calls the createNode method to create temporary order nodes under Locker, and then calls getChildren(” locker “) to get all the children under Locker, noting that no Watcher is set at this time.
-
After obtaining all of the child nodes path, the client is considered to have obtained the lock if it finds that it has created the child node with the smallest sequence number.
-
If you find that the node you created is not the smallest of locker’s child nodes, it means that you have not obtained the lock. In this case, the client needs to find the node that is smaller than it, and then call exist() on it, and register the event listener for it.
-
After that, the Watcher of the client will receive the corresponding notification. At this time, it will judge again whether the node it created is the smallest in the locker child node. If so, it will get the lock.
My explanation:
A creates Node_n under Locker — > loop (get all children under Locker at A time — > sort these nodes by node increment — > determine if Node_n is the first node — > obtain distributed lock if so — > If you do not listen on the previous node node_n-1 and wait for it to release the distributed lock.
Mybatis: @insert writes SQL statements as annotations
Sessions under a distributed system
1, distributed system: multi-node, nodes send data interaction, do not share the main memory, but send messages through the network cooperation.
Distributed: nodes with different functional modules
Cluster: Nodes with the same function
Session and Token
The server sets the SessionID in the HTTP header and the client stores it in a cookie
To use the Token, you need to manually set the Token in the HTTP header. After receiving the request, the server takes out the cookie for authentication.
It’s one user, one logo
3. Session problems in distributed systems
High concurrency: The system is designed to handle many requests in parallel.
When a high number of concurrent requests arrive at the server, they are distributed to a server in the cluster through load balancing. In this way, multiple requests from the same user may be distributed to different servers in the cluster, and session data cannot be obtained.
Load to different servers for different urls
Three machines, A1 deployment category, A2 deployment commodity, and A3 deployment single service
General scheme: Use Redis to save Session information, and the server will ask Redis for it when needed. Save key-value when logging in and disable key-value when logging out
Vertical extension: IP hash IP hash values of the same access to the same server
Session consistency: As long as the user does not restart the browser, the server can locate the session for each HTTP short connection request and maintain the session.
Redis as a distributed lock
High concurrency: The system is designed to handle many requests in parallel. (System learning concurrent knowledge, you can reply “multi-threaded aggregation” in the Java zhiyin public account)
Synchronization: Synchronization in Java refers to making multithreaded access to shared resources thread-safe through artificial control and scheduling.
The Block state of a thread:
A. Call join() and sleep(). The sleep() time ends or is interrupted
B. wait(), keeps the thread in the wait pool until notify()/notifyAll() : does not release resources
In addition, threads in the runnable state are threads that are scheduled, and the yield method in the Thread class can make a running Thread go to runnable.
Q: Why must wait,notify, and notifyAll be used together with synchronized? Obj.wait(), obj. notify Must be synchronized(Obj){… } statement block.
A: Wait means that after A thread acquires the object lock, it releases the object lock and the thread sleeps.
Q: Synchronized:
A: Synchronized is an unfair lock that does not guarantee the order in which waiting threads acquire the lock.
The queues for both fair and unfair locks are based on a bidirectional linked list maintained within the lock. The value of Node is each thread requesting the current lock. A fair lock is one that takes the value from the head of the queue each time.
ReentrantLock reentrant:
Reentrant locking can be seen in both articles, which are relatively simple
https://www.jianshu.com/p/587a4559442b
https://www.jianshu.com/p/1c52f17efaab
Two important annotations to the Spring + Redis cache:
-
@cacheable is executed only once. When the tag is on a method to indicate that the method is cache-enabled, Spring caches its return value after it is called to ensure that the next time the method is executed with the same parameters, the result can be fetched directly from the cache.
-
@cachePUT: Unlike @cacheable, methods using the @cacheput annotation do not check the cache for previously executed results before executing. Instead, the method is executed each time and the result is stored in a specified cache as a key-value pair.
Locking databases (optimistic versus pessimistic)
Pessimistic locks depend on database implementations:
select * from account whereName = "Erica"for updateCopy the code
This SQL statement locks all records in the account table that meet the search criteria (name= “Erica”) so that the record cannot be owned by other threads while it is being modified.
Code layer lock:
String hql ="from TUser as user where user.name='Erica'";
Query query = session.createQuery(hql);
query.setLockMode("user",LockMode.UPGRADE); List userList = query.list(); // Execute query to obtain dataCopy the code
other
@data is like automatically generating getters (), setters (), ToString(), etc.
StreamAPI: Collectors, a new feature in JAVA1.8, provides a variety of ways to accumulate elements from a stream into an aggregation result
List<Menu> menus=Menu.getMenus.stream().collect(Collectors.toList())Copy the code
For each
The for each statement is a new addition to java5, which provides good performance when iterating through groups and collections.
public static void main(String[] args) {
String[] names = {"beibei"."jingjing"};
for(String name : names) { System.out.println(name); }}Copy the code
For each can be used to iterate over arrays or collections, but only for traversal. It cannot be used to modify arrays or collections during traversal.
BindingResult: An @valid argument must be followed by a BindingResult argument, otherwise Spring will throw an exception if the validation fails.
@Data
public class OrderForm {
@NotEmpty(message = "Name required")
private String name;
}Copy the code
Background:
@RequestMapping("save")
public String save( @Valid OrderForm order,BindingResult result) {
//
if(result.hasErrors()){
List<ObjectError> ls=result.getAllErrors();
for (int i = 0; i < ls.size(); i++) {
log.error("Invalid parameter, OrderForm={}", order); Throw new SellException (..................... , result.getFeildError.getDefaultMessage() ) System.out.println("error:"+ls.get(i)); }}return "adduser";
}Copy the code
Result. GetFeildError. GetDefaultMessage () can be thrown “name shall fill in” exceptions.
4. Change List to Map
public class Apple { private Integer id; private String name; private BigDecimal money; private Integer num; /* Constructor */}Copy the code
List<Apple> appleList = new ArrayList<>(); Apple apple1 = new apple (1,"Apple 1",new BigDecimal("3.25"), 10); Apple apple12 = new Apple(1,"Apple 2",new BigDecimal("1.35"), 20); Apple apple2 = new Apple(2,"Banana",new BigDecimal("2.89"), 30); Apple apple3 = new Apple(3,"Litchi",new BigDecimal("9.99"), 40); appleList.add(apple1); appleList.add(apple12); appleList.add(apple2); appleList.add(apple3);Copy the code
Map<Integer, Apple> appleMap =
appleList.stream().collect(Collectors.toMap(Apple::getId, a -> a,(k1,k2)->k1));Copy the code
5, Subclasses of Collection: List, Set
List: ArrayList, LinkedList, Vector
List: Ordered containers that allow null elements and repeat elements
Set: Elements are unordered and no elements are allowed
The most popular is the hashMap-based implementation of HashSet, with hashCode() and equals() guaranteeing uniqueness of elements.
A set can be used to remove duplicate elements from a List. The constructor of a set can take a List, and the constructor is a de-duplicated set.
Addendum to HashMap: It is not under Collection
A Map can use containsKey()/containsValue() to check if it contains a key/value.
A HashMap uses the object’s hashCode to quickly find the key.
Insert process: A hash function is used to determine the insert position of an Entry. Index =hash(key). However, the length of the array is limited, and index conflicts may occur.
Each insertion iterates through the singly linked list under its index. If there is a node with the same Key, replace it and return the new value.
However, the single-linked list does not always add elements. When the number of elements exceeds 8, an attempt is made to convert the single-linked list to red-black tree storage.
Why is the load factor 0.75 by default? (0.75 Start capacity expansion)
A: As you can see from the Javadoc comments in the source code, the bucket frequency distribution of elements in the hash table follows a Poisson distribution of parameter 0.5.
Source code address:
https://github.com/923310233/wxOrder