1. Challenges posed by large-scale concurrency

In my past work, I once faced the high concurrency seckill function of 5W per second. In this process, the whole Web system encountered many problems and challenges. If a Web system is not optimized, it can easily fall into an abnormal state. Let’s discuss the idea and method of optimization.

1. Reasonable design of request interface

A second kill or purchase page, usually divided into two parts, one is static HTML and other content, the other is to participate in the second kill Web background request interface.

Usually static HTML and other content, is through the DEPLOYMENT of CDN, general pressure is not much, the core bottleneck is actually in the background request interface. This back-end interface must be able to support high concurrency requests and, crucially, must return the results of the user’s request as “fast” as possible in the shortest possible time. To achieve this as fast as possible, the back-end storage of the interface uses memory level operations better. Still directly facing MySQL and other storage is not appropriate, if there is such a complex business needs, are recommended to use asynchronous write, Java concurrent programming actual notes.

Of course, there are also some “delayed feedback”, which means that the user does not know the result of the instant kill, and it is possible to see whether the user succeeded in the instant kill from the page after a period of time. However, this kind of behavior belongs to “lazy”, at the same time gives users a bad experience, easy to be considered by users as “black box operation”.

2. High concurrency challenges: Be “fast”

The metric we usually use to measure the throughput of a Web system is QPS (Query Per Second), which is critical for dealing with high concurrency scenarios with tens of thousands of requests Per Second. As an example, let’s assume that the average response time for processing a business request is 100ms, and that there are 20 Apache Web servers on the system, and MaxClients is configured to 500 (representing the maximum number of Apache connections).

So, the theoretical peak QPS of our Web system is (idealized calculation) :

20*500/0.1 = 100000 (100,000 QPS)

Yi? Our system seems so powerful that it can handle 100,000 requests in 1 second. 5W /s seems like a “paper tiger”. The actual situation, of course, is not so ideal. In a real-world scenario with high concurrency, where the machine is under high load, the average response time is greatly increased.

In the case of Web servers, the more connection processes Apache has open, the more context switches the CPU has to handle, adding additional CPU consumption, which in turn directly increases the average response time. Therefore, the number of maxClients mentioned above should be considered based on hardware factors such as CPU and memory. The more the better. You can use Apache’s built-in abench to test for a suitable value. We then select Redis for the memory operation level storage, where the response time of the storage is critical in the state of high concurrency. Network bandwidth is also a factor, but such request packets are generally small and rarely a bottleneck for requests. Load balancing is rarely a bottleneck, so I won’t discuss it here.

So here’s the problem. Suppose our system, at a high concurrency of 5W /s, has an average response time of 100ms to 250ms (or more) :

20*500/0.25 = 40000 (40000 QPS)

So our system is left with 4W QPS for 5w requests per second, with a 1W difference in the middle.

Then, this is where the real nightmare begins. For example, a highway intersection, five cars come in a second, five cars pass every second, the highway intersection works fine. All of a sudden, only four cars a second can pass through this intersection, and the flow of traffic remains the same, resulting in a guaranteed traffic jam. (5 lanes suddenly become 4 lanes)

Similarly, in a given second, 20*500 available connection processes are working at full capacity, but there are still 10,000 new requests, no connection processes are available, and the system will fall into an abnormal state is expected.

In a normal non-concurrent service scenario, a similar situation occurs. A service request interface is faulty and the response time is extremely slow. The response time of the entire Web request is prolonged and the number of available connections of the Web server is gradually filled up.

Problem is, the more terrible is the user’s behavior characteristic, the system is not available, the more users to click on the more frequently, a vicious cycle eventually led to the “avalanche” (one of the Web machine hang up and lead to flow to other working machines, again lead to the normal machine also hang, then cycle), will bring down the entire Web system.

3. Restart and overload protection

If the system is hit by an “avalanche”, the problem cannot be solved by restarting the service. The most common phenomenon is that after starting up, it immediately dies. At this point, it is best to reject traffic at the entry level and then restart. If the redis/memcache service is also down, you need to pay attention to the “warm-up” during the restart, and it may take a long time.

Second kill and snap up the scene, traffic is often beyond our system’s preparation and imagination. At this time, overload protection is necessary. It is also a protection measure to reject requests if the system is detected to be full. Filtering on the front end is the easiest way to do it, but this is the kind of behavior that users often complain about. Better yet, overload protection is placed in the CGI entry layer to quickly return direct requests from the customer.

Two, the means of cheating: attack and defense

Seckill and snap have received a “huge” number of requests, which are actually quite large. Many users, in order to “grab” goods, will use “ticket brushing tool” and other types of auxiliary tools, to help them send as many requests as possible to the server. There are also power users who make powerful automated request scripts. The reason for this approach is very simple, that is, in the second kill and purchase of requests, the number of their own requests accounted for a higher probability of success.

These are the “means of cheating”, however, there is “attack” there is “defense”, this is a battle without smoke of gunpowder ha.

1. Send multiple requests for the same account at a time

Some users send hundreds or more requests at a time with their own accounts through browser plug-ins or other tools at the beginning of the second kill. In fact, such users undermine the fairness of seckilling and buying.

This kind of request can also cause another kind of breach in some systems that do not have data security processing, causing certain judgment conditions to be bypassed. For example, a simple claim logic, first judge whether the user has participated in the record, if not, the claim is successful, and finally written into the participation record. This is a very simple logic, but, in high-concurrency scenarios, there are deep holes. Multiple concurrent requests are distributed to multiple Web servers on the Intranet through the load balancing server. They first send query requests to storage devices. Then, within the time difference between a request being successfully written into the participant record, other requests or query results are “no participant record”. Here, there is a risk that logical judgment will be bypassed.

Solutions:

At the entry point of the program, each account is allowed to accept only one request. Other requests are filtered. This not only solves the problem of sending N requests from the same account, but also ensures the security of subsequent logical processes. In the implementation scheme, a flag bit can be written through Redis memory caching service (only 1 request is allowed to be written successfully, combined with the optimistic lock feature of Watch), and successful writing can continue to participate.

Or you can implement a service yourself that puts requests from the same account into a queue, processes one, and then the next.

2. Multiple accounts send multiple requests at a time

The account registration function of many companies, in the early stage of development is almost unlimited, it is easy to register many accounts. Therefore, it also led to the emergence of some special studios, through writing automatic registration script, accumulated a large number of “zombie accounts”, a huge number of tens of thousands or even hundreds of thousands of accounts, specializing in all kinds of brush behavior (this is the source of “zombie fans” in Microblog). For example, if there is a lottery retransmission activity in weibo, we can use tens of thousands of “zombie numbers” to mix in and forward, so that we can greatly improve the probability of winning.

This kind of account, use in second kill and snap up, is also the same truth. For example, the rush on the iPhone website, train ticket scalpers.

Solutions:

This scenario can be solved by detecting the specific IP request frequency of the machine. If an IP request frequency is found to be high, you can pop up a verification code for it or directly prohibit its request:

  1. Popup captcha, the core pursuit, is to distinguish real users. As a result, you may often find that sites pop up captcha, some of the “ghost” look, sometimes we can’t see it at all. The reason they do this is to make the image of the captcha hard to read, because powerful “automatic scripts” can read the characters in the image and then let the script fill in the captcha itself. In fact, there are some very innovative captcha that work better, such as giving you a simple question to answer, or allowing you to perform some simple actions (such as the captcha on Baidu Tieba).
  2. Banning IP addresses directly is actually a bit rude, because some real users’ network scenarios happen to share the same egress IP, which may cause “accidental injury”. However, this approach is simple and efficient, and can be used according to the actual scene to achieve good results.

3. Multiple accounts with different IP addresses send different requests

While the priest climbs a post, the devil climbs ten. Where there is offense, there will be defense and there will be no rest. These “studios”, once they realize that you have control over the frequency of single IP requests, come up with their own “new attack plan” for this scenario, which is to constantly change the IP.

Some of you may wonder where these random IP services came from. In some cases, organizations themselves occupy a number of independent IP addresses and then create a random proxy IP service, which is offered to these “studios” for a fee. Some of the darker ones are using Trojan horses to hack into the computers of ordinary users. The Trojan horses do not destroy the normal operation of users’ computers, but only do one thing, which is to forward IP packets, and ordinary users’ computers are turned into IP proxy exits. In this way, hackers get their hands on a large number of individual IP addresses and then build services for random IP addresses, just to make money.

Solutions:

To be honest, the request in this scenario is so similar to the behavior of the real user that it’s hard to tell the difference. Further restrictions can easily “accidentally hurt” real users, and such requests can usually be limited by setting a high threshold for business, or by “data mining” account behavior to clear them up in advance.

Zombie accounts also have some common characteristics, such as accounts are likely to belong to the same number segment or even serial number, low activity, low level, incomplete information and so on. According to these characteristics, the participation threshold should be set appropriately, such as limiting the level of accounts participating in seckilling. Through these business means, but also can filter out some zombie number.

The rush for train tickets

See here, do you understand why you can not get the train ticket? It’s really hard if you just go for the tickets honestly. Through the way of multiple accounts, ticket scalpers will occupy a lot of tickets, some powerful scalpers, in the processing of verification code, but also “better”.

Advanced scalpers brush tickets, in the identification of verification code when the use of real people, the middle to build a display of verification code picture transfer software services, real people browse pictures and fill in the real verification code, back to the transfer software. In this way, the protection limitation of captchas has been abolished, and there is no good solution at present.

Because train tickets are based on the id card real-name system, there is a train ticket transfer operation. The general operation mode is to use the buyer’s ID card to open a ticket grab tool, continue to send requests, scalpers choose to refund the ticket account, and then scalpers successfully buy tickets through their ID card. When there is no ticket in a train, there are not many people staring at it, and the scalpers’ grab ticket tools are also very powerful, even if we see a refund, we may not be able to grab them.

In the end, the scalpers successfully transferred the train ticket to the buyer’s ID card.

Solution:

There is no good solution, the only thing you can do is to “data mining” the account data. These scalpers also have some common characteristics, such as snatching tickets and returning tickets often, being extremely active on holidays and so on. Analyze them, and then do further processing and screening.

Data security under high concurrency

We know that when multiple threads write to the same file, there is a “thread-safe” problem (multiple threads running the same code at the same time, if the result of each run is the same as that of a single thread, it is thread-safe). If you use a MySQL database, you can use its lock mechanism to solve the problem. However, MySQL is not recommended for large-scale concurrent scenarios. There is another problem in the SEC and snap scenarios, which is the “overshoot”. If this is not properly controlled, it can cause too many dispatches. We have also heard that some e-commerce companies engage in panic buying activities. After the successful purchase, the sellers do not recognize the validity of the order and refuse to deliver the goods. The problem here may not necessarily be dishonest business, but the system technical level of excess risk.

1. Causes of overhair

Let’s say in a panic buying scenario we only have 100 items in total, and at the last minute we’ve used 99 items down to the last one. At this time, the system sends multiple concurrent requests, which read 99 goods with a margin, and then pass the margin judgment, resulting in oversending. (Same as the scene mentioned earlier in the article)

In the figure above, this results in concurrent user B also “snapping up”, allowing one more person to get the item. This scenario, in the case of high concurrency, is very easy to occur.

2. Pessimistic thinking

There are many ways to solve thread-safety problems, starting with the direction of “pessimistic locking”.

Pessimistic locking, that is, when modifying data, adopts a locked state, excluding external requests for changes. When a locked state is encountered, it must wait.

While the above solution does address the issue of thread safety, remember that our scenario is “high concurrency.” That is, there will be many such modification requests, and each request will have to wait for a “lock” that some thread may never have a chance to grab, and the request will die there. At the same time, the number of such requests can increase the average response time of the system in an instant, and as a result, the number of available connections can be used up and the system can fall into an anomaly.

3. FIFO queue idea

Ok, so let’s modify the above scenario a little bit. We queue requests directly and use FIFO (First Input First Output) so that we don’t end up with some requests never getting the lock. Look at this, doesn’t it feel a bit like forcing multiple threads into a single thread?

Then, we have now solved the lock problem and all requests are processed on a fifo queue. The new problem is that in high-concurrency scenarios, the queue memory can be “overwhelmed” in a fraction of a second because of the number of requests, and then the system falls into an abnormal state. Or designing a huge memory queue is another option, but the system can’t handle a queue as fast as the number of requests pouring into it. In other words, the number of requests in the queue will accumulate and eventually the average response time of the Web system will drop significantly and the system will still fall into an exception.

4. Optimistic thinking

At this point, we can discuss the idea of “optimistic lock”. Optimistic locking is a looser locking mechanism than “pessimistic locking”, which is mostly updated with Version. The implementation is that all requests for this data are eligible to modify, but will get a version number of the data, only the version number can be updated successfully, the other return snap up failed. This way, we do not need to worry about queues, but it can increase CPU computation overhead. But, all in all, it’s a better solution.

There are many apps and services that support optimistic locking, such as Watch in Redis. With this implementation, we keep the data secure.

Four, summary

The Internet is developing at a high speed. The more users use Internet services, the more high concurrency scenarios become. E-commerce seckilling and buying are two typical scenarios of high concurrency on the Internet. While the exact technical solutions to our problems may vary, the challenges are similar, and so are the approaches.

5. Concurrency

Use the examples above to explore the occurrence of concurrent scenarios and techniques for dealing with high concurrency.

1. What is concurrency?

In the Internet age, concurrency, high concurrency, usually refers to concurrent access. That’s how many visits are coming at a time. (PV (Page view) refers to page views.)

The more requests a server can process per unit of time, the higher the capacity of the server, that is, the higher the concurrent processing capacity of the server. The nature of the server’s job is to try to get all the user request data out of the kernel buffer as quickly as possible, process it as quickly as possible, put the response data into a buffer that can send it, and then process the next batch of requests.

2. Measure the server’s concurrent processing capacity?

Some common indicators related to high concurrency include Response Time, Throughput, Query Per Second (QPS), and number of concurrent users.

Response time: Time for the system to respond to a request. For example, if it takes 200ms for the system to process an HTTP request, this 200ms is the system response time.

Throughput: The number of requests processed per unit of time.

QPS: number of response requests per second. In the Internet domain, the distinction between this metric and throughput is not so obvious.

Number of concurrent users: specifies the number of concurrent users who use system functions. For example, in an instant messaging system, the number of simultaneous online users to some extent represents the number of concurrent users of the system.

3. How to improve the concurrent processing capacity of the server?

There are two ways:

3.1 The first is to improve the performance of the single machine;

1. Improve the concurrent computing capability of CPU:

(1) Multi-process & multi-thread

(2) Reduce process switching, use threads, consider process binding CPU

(3) Reduce the use of unnecessary locks and consider lockless programming

(4) Consider the process priority

(5) Pay attention to system load

In addition to user space and kernel space CPU usage, I/O wait is also concerned

2. Reduce system calls.

3. Consider reducing memory allocation and release:

(1) Improve data structure and algorithm complex system

(2) Use the memory pool

(3) Consider using shared memory

4. Consider persistent connections.

5. Improved I/O model:

(1) the DMA technique

Asynchronous I/O (2)

(3) Improved multiway I/O readiness notification strategy, epoll

(4)Sendfile

(5) Memory mapping

(6) the direct I/O

6. Improve server concurrency strategy.

(1) One process processes one connection, non-blocking I/O, using long connections

(2) A process to handle multiple connections, asynchronous I/O, using long connections

7. Improve the hardware environment.

3.2 The second is the distributed development architecture of the Internet, increasing the number of machines.

You can actually reduce the stress on the server by reducing unwanted requests. For example, zombie fans of Weibo and scalpers buying tickets.

4 summarizes

High Concurrency is one of the most important things to consider when designing an Internet distributed system architecture. It usually refers to the idea of designing a system that can handle many requests in parallel.

There are two methods to improve system concurrency: Scale Up and Scale Out. The former vertical extension can improve the concurrency by improving the hardware performance of the single machine, or improve the performance of the single machine architecture, but the performance of the single machine is always limited, the ultimate solution of Internet distributed architecture design with high concurrency is the latter: horizontal extension.

In the hierarchical architecture of the Internet, the practices of the expansion at different levels are different:

(1) The reverse proxy layer can be extended horizontally through “DNS polling”;

(2) The site layer can be extended horizontally through Nginx;

(3) The service layer can be extended horizontally through the service connection pool;

(4) The database can be expanded horizontally according to the data range or data hash;

After the implementation of horizontal expansion of each layer, the system performance can be improved by increasing the number of servers, so that the theoretical performance is infinite.

What is the relationship between multithreading and concurrency

6.1 a multithreaded

1. Java itself is multithreaded;

2, Java multithreading is a programming thought, after a program execution is a process, the so-called multithreading is there are multiple threads in a process, on the macro is multiple threads run at the same time, can make the process finish more things at the same time, the micro is CPU switch between multiple threads, or perform one thread at a time.

6.2 concurrent

1, concurrent generally refers to “concurrent access, such as a number of applications from different clients accessing the same database on the server at the same time, the application server must have capacity to handle concurrent requests, or concurrent requests are process inside thread processing, concurrent access with concurrent programming process is the best solution is multi-threaded.

2. Concurrent programming is an application of multithreaded programming.

3, whether you are doing Web development, database development, or desktop development, will use multithreading.

4. Because of the practical need for concurrency, multithreading came into being.

6.3 The relationship between multithreading and concurrency

1. High concurrency is not unique to JAVA, but is a broad, language-independent concept that provides better Internet services.

Take an extreme example, if 100 people, 1 person is allocated a Web server, then the server resources are their exclusive, they do not need to seize the server resources, 100 requests are processed by 100 servers in parallel, the speed must be very fast, this is high concurrency. Of course this is not possible, but we always try to make it possible for a small number of servers to achieve similar capabilities. This requires the server’s HTML screen, background business logic, DB data access and other details of the processing have reached a parallel extreme, in order to achieve the high parallelism of the whole server for all requests. This is strategic parallelism.

Multithreading is just to achieve the purpose of high concurrency, in a specific point, for the realization of a concurrent function of a specific implementation method, this function can also be realized by multiple processes, of course, also can be realized by multiple processes, multithreading together. This is tactical parallelism.

So it can be said that high concurrency is the end, multi-threading is a means (not the only one), high concurrency can be achieved by multi-threading, but multi-threading does not mean high concurrency.

2. The relationship between concurrency and multithreading is the relationship between ends and means.

Concurrent, “Concurrent,” is the opposite of serial. Serial is like multiple vehicles in a lane, they can only “file”. Concurrency, on the other hand, is like multiple vehicles in multiple lanes. They can “run side by side.”

The ultimate in concurrency is Parallel.

Multithreading is a means, approach, or model for making concurrent (parallel) computations that might otherwise be serial. For this reason, we sometimes call multithreaded programming concurrent programming.

Of course, ends and means are often in a one-to-many relationship. There are other ways to implement concurrent programming, such as Functional programming. Multithreaded programming is often the basis for other concurrent programming models, so its importance is self-evident.

Based on the above points, we can see that:

Concurrency is the ability of a server to handle multiple requests at the same time, and the best way to handle concurrency is to use multiple threads. The CPU quickly calls different ready queues, which appear to be synchronized but are actually processed thread by thread, but this greatly improves server efficiency and reduces thread wait time.

Multithreading is a programming approach that deals with high concurrency. Concurrency requires multithreading.

When a large number of requests are received and the server has no connected process available, the system may generate an exception.

Seven, in the specific project, when is the use of multithreading

7.1 Multi-threading Scenarios

1. If you do Java Web development, you hardly need multithreading! Because where there is multithreading, servlet containers or other development frameworks are already implemented!

There are many ways to use multithreading in web applications! In addition, copy files using multithreading, is useless! The use of multithreading to improve efficiency is typically in CPU computing rather than IO read-write scenarios. CPU can have multiple cores processing computation in parallel, but disk IO does not have this function, only one magnetic head, it is impossible to rely on multithreading to improve efficiency! In general, disk I/O concurrency is 0, which means concurrency is not supported! Network IO because of the bandwidth limit, the use of multithreading processing can only reach the maximum bandwidth. For disk IO, multithreading can be used to make better use of CPU resources by having one thread dedicated to reading and writing files and the other thread dedicated to processing the read data. If it is only a simple file copy, using multithreading operations, will use the magnetic head on the disk constantly seek operations, making the efficiency is even lower!

2. Multithreading is used in stress testing.

3, server programming, will use multithreading.

4. Multithreading may be used when using listeners.

5. Multithreading may be used when running jobs.

6, there is a very common use of multi-threading scenario is UI programming, general UI interface is drawn in the main thread, in order not to block the main thread to make the user experience more smooth, need to create a separate thread processing time-consuming operations, processing and then update the main interface, a typical case is Android application development.

7, some C/S mode such as network games (based on socket protocol) generally in the server side of the processing of a client, a thread; There are also some banking software, using thread synchronization and so on.

7.2 Scenarios of High Concurrency Events

1, the server processes requests per second is a certain number, when the traffic is too large, there is no extra process to handle these requests, it will cause the system breakdown. System crash, such as the breakdown of Weibo some time ago, is too much traffic in a short period of time, resulting in an abnormal state of the system, the page cannot be displayed, users can not log in, etc. In the e-commerce, there is the situation of over-delivery in the second kill. Multiple users buy the same item at the same time, access and modify the same data.

2, as a result of buying tickets, query and browsing the number of surge, 12306.cn website daily visits than usual growth dozens of times, often appear difficult to log in the phenomenon, even recently there was no payment tickets, the system simply paralyzed. Online booking was supposed to be a convenience measure for the people, but the ministry of Railways failed to correctly estimate the concurrency of the website and lacked technical support. The IT industry has pointed out that the biggest reason for the breakdown of 12306 is the crime of technology. In view of the technical test caused by the high concurrency website, we have put forward many instructive technical solutions.

3. The difficulty in logging in and breakdown of 12306 website is a problem of system architecture planning, which leads to the failure to effectively support centralized access with large concurrent volume. Meanwhile, 12306 also had problems in IT management, failing to conduct effective stress tests and run simulations.

7.3 Solution to the oversending problem in high Concurrency

7.3.1 Scenarios in e-commerce Projects

1. When clicking the submit order button of shopping cart, it will judge whether the inventory is sufficient or insufficient and refuse to submit the order.

2. When there is only one item in stock, two or more customers are judged to submit an order in the shopping cart or pay on the order page, and both meet the demand of buying a product. Then, who can buy successfully? Aren’t multiple users paying for the same thing at the same time? This case is called overshoot, and the following will solve the problem of overshoot with high concurrency.

3. Examples:

Let’s say I have 6 in my inventory. There are two clients, A and B. A buy 1; B Customer to buy 6:

(1) When clicking submit order, both of them judge inventory satisfaction and enter the order interface;

(2) Then A completes the payment first. In the process of payment, the inventory is reduced (at this time, the judgment is made. If the inventory is sufficient, the payment will be successful; otherwise, the payment will fail) — PS: Similar to 12306 ticket purchase system.

(3) Then B slowly enters into the payment. Judging that there are only 5 in the inventory at this time, the payment is not allowed and the payment fails.

(4) What if both pay at the same time? How to change inventory, let who buy successful? This involves locking and synchronization. The solution to this problem is discussed below.

7.3.2 Solution to oversending

In general, locking refers to two levels:

Code levels, such as synchronization locks in Java, are typically synchronized;

Database levels, such as pessimistic (physical) and optimistic locks.

1. Pessimistic lock

There are many ways to solve thread-safety problems, starting with the direction of “pessimistic locking”. Pessimistic locking, that is, when modifying data, adopts a locked state, excluding external requests for changes. When a locked state is encountered, it must wait. While the above solution does address the issue of thread safety, remember that our scenario is “high concurrency.” That is, there will be many such modification requests, and each request will have to wait for a “lock” that some thread may never have a chance to grab, and the request will die there. At the same time, the number of such requests can increase the average response time of the system in an instant, and as a result, the number of available connections can be exhausted and the system can run into exceptions.

Pessimistic locking: Locking is implemented through the forUPDATE field of the database. For update must be placed in mysql transactions, namely begin and COMMIT, otherwise it does not work.

Pessimistic locking is locking and synchronizing the data to be modified. Other requests need to wait. Lock the data. How do you do that? How do you write it in code. Need to know.Copy the code

2. FIFO queue idea

Ok, so let’s modify the above scenario a little bit. We queue requests directly and use FIFO (First Input First Output) so that we don’t end up with some requests never getting the lock. Look at this, doesn’t it feel a bit like forcing multiple threads into a single thread?

Then, we have now solved the lock problem and all requests are processed on a fifo queue. The new problem is that in high-concurrency scenarios, the queue memory may be “overwhelmed” in a flash because of the number of requests, and then the system falls into an abnormal state. Or designing a huge memory queue is another option, but the system can’t handle a queue as fast as the number of requests pouring into it. In other words, the number of requests in the queue will accumulate and eventually the average response time of the Web system will drop significantly and the system will still fall into an exception.

3. Optimistic thinking

At this point, we can discuss the idea of “optimistic lock”. Optimistic locking is a looser locking mechanism than “pessimistic locking”, which is mostly updated with Version. The implementation is that all requests for this data are eligible to modify, but will get a version number of the data, only the version number can be updated successfully, the other return snap up failed. This way, we do not need to worry about queues, but it can increase CPU computation overhead. But, all in all, it’s a better solution. There are many apps and services that support optimistic locking, such as Watch in Redis. With this implementation, we keep the data secure.

Own understanding:

For example, to change the version number, version. Assume that there is a Version field in the account information table in the database with the current value of1; The current account balance field (balance) is $1001Operator A then reads it out (version=1) and deduct $from their account balance50($100- $50).2During operator A's operation, operator B also reads this user information (version=1) and deduct $from their account balance20($100- $20).3Operator A completes the modification by adding the data version number by one (version=)2), together with the account balance (balance=$)50), submit to the database for update. At this time, because the version of the submitted data is larger than the current version recorded in the database, the data is updated, and the database record version is updated as24Operator B completes and also increments the version number (version=)2) attempts to commit data to the database (balance=$80), but when comparing the version recorded in the database, it was found that the version number of the data submitted by operator B was2, the database records the current version is also2Operator B's submission is rejected because the optimistic locking policy of "the submitted version must be greater than the current version in order to perform the update" is not met. This avoids operator B using version= based1The result of the old data modification overrides the possible result of operator A's operation.Copy the code

As can be seen from the above example, the optimistic locking mechanism avoids the overhead of database locking in long transactions (operator A and operator B do not lock database data during operation), which greatly improves the overall performance of the system under large concurrency.

Question: What if two people commit transactions at the same time?

7.3.2 Database related

Mysql database lock mechanism

The lock

2. About transactions and dirty data

Dirty data, unrepeatable read, phantom read

Solution:

8. My understanding of multi-threading and high concurrency

8.1 My understanding of multi-threading and high concurrency

My understanding of threads and concurrency may be superficial, theoretical, and basic, because I haven’t dealt with concurrency and multithreading in any of my projects.

My approach to concurrency is simply to improve the concurrency of projects in distributed development and load balancing. In the e-commerce project, I have done the basic operation of distributed and cluster.

Multithreading in the basic concept of the basis, understand the Web server (such as Tomcat) servlet singleton multithreading. Now multithreading is being used in reserve projects, and thread pools are being touched. It is now understood that threads can make applications more efficient at handling requests. As for locking, it must involve multithreading, there is a common access to resources, will involve locking, such as singleton multithreading, there are simple code examples below.

High concurrency refers to the ability of the server to handle a large number of requests simultaneously. Overshooting can occur when high concurrency occurs :(details, combined with overshooting problems encountered in my own project)

The server can also crash when requests exceed its capacity. At this point, we can through the architecture of distributed development, and will refine multiple sub business, this can increase the backend server access to high business request processing ability, but also facilitate later upgrade maintenance, maintenance upgrade easier between each business, through a remote call to realize the relationship between each business. In addition, you can improve the concurrency of the server by clustering. This way to improve the concurrency of the server has become the horizontal improvement of the concurrency of the server, which is also the trend of the future development.

In addition, it is through a single machine, by improving the performance of a single physical machine such as CPU, to improve the concurrency of the server.

So what we need to understand is how to deal with overshooting once we understand what concurrency is, what multi-threading is.

8.2 Multithreading and concurrency that I have come into contact with in actual coding

8.2.1 Simple application: Multi-threading and synchronous code blocks for selling train tickets.

Thread implements threads with Thread:Threads cannot be used to share resources
class MyThread extends Thread  
{     
    private int ticket=5;  
    private String name;  
    public MyThread(String name ){  
        this.name=name;  
    }  
    public void run(){  
        for(int i=0; i<10; i++){if(ticket>5){  
                System.out.println("Thread"+name+"Tickets"+i);  
            }  
        }  
      
    }  
}  
  
public class ThreadDemo02  
{  
    public static void main(String args[]){  
        MyThread A = new MyThread("A");    
        MyThread B = new MyThread("B"); A.start(); B.start(); }} with Runnable:// Use Runnable thread to implement resource sharing
class MyThread implements Runnable  
{  
    private int ticket=5;  
    private String name;  
    public MyThread(String name){  
        this.name=name;  
    }  
    public void run(){  
        for(int i=1; i<=10; i++){if(ticket>0){  
                System.out.println("Thread"+name+"Tickets"+(ticket--));  
                }  
        }  
    }  
}  
public class RunnableDemo02  
{  
    public static void main(String args[]){  
        MyThread A = new MyThread("A");  // Instantiate the task to be performed by the thread
        Thread Ta = new Thread(A);    // Instantiate two thread objects that actually pass a task
        Thread Tb = new Thread(A);    // Since the two threads are performing the same task, the resources are sharedTa.start(); Tb.start(); }}Copy the code

8.2.1 Singleton multithreading of servlets

Why multithreading?

To improve CPU utilization, (improve concurrency).

Why double check?

If the synchronization method, and single thread difference is not big, so, synchronization of common resource objects, narrow the scope of locking, so use double check.

Actual combat interview real topic: Java concurrent programming the most comprehensive test 123.

1. Create a mock servlet generator

package cn.bjsxt.sing;

import java.util.UUID;

public class LszySingleton {
    // Member variables are not recommended for servlets
    // Define member variables for the current servlet
    // String uuid = null;
    static LszySingleton instance = null;

    // Privatizing the constructor means not allowing objects to be continuously built through the constructor
    /* public */private LszySingleton() {
        System.out.println("HungrySingleton.HungrySingleton()");
    }

    public static void init(){
        System.out.println("LazySingleton.init()");
    }
    
    public /*synchronized*/ void  service(){
        // Each time the thread calls the service method, the uUID number is regenerated
        String uuid = UUID.randomUUID().toString().replace("-"."");
        
        // Displays all member UUids carried by the current thread
        System.out.println(Thread.currentThread().getName()+"-"+uuid);
        
    }
    // Provide a special method to get an object (instance)
    // Double thread check doublecheck
    public static/* synchronized */LszySingleton getInstance() {

        if (null == instance) {
            
            // If the current object instance is empty, the object is created
            synchronized (LszySingleton.class) {
                if(null==instance){
                    instance = newLszySingleton(); init(); }}}returninstance; }}Copy the code

2. Simulate the Tomcat server

package cn.bjsxt.sing;

public class tomcatrun implements Runnable {

    @Override
    public void run() {
        // TODO Auto-generated method stubLszySingleton instance = LszySingleton.getInstance(); instance.service(); }}Copy the code

3. Access the Tomcat service

public static void main(String[] args) {
        for (int i = 0; i < 5; i++) {

            new Thread(newtomcatrun()).start(); }}Copy the code

8.2.3 When explaining e-commerce projects, distributed development and Nginx load balancing cluster are established.

Use components such as Redis.

Create distributed projects and clusters.

Now it’s all about microservices.