Nice programing

캐싱이란 무엇입니까?

nicepro 2020. 11. 18. 21:30
반응형

캐싱이란 무엇입니까?


나는 사람 y가 캐싱을 통해 해결 한 성능 문제 x를 가지고 있다는 이야기를 끊임없이 듣고 있습니다.

또는 프로그램 코드에서 x, y, z를 수행하면 캐싱 기능이 손상 될 수 있습니다.

최신 팟 캐스트 중 하나에서도 Jeff Atwood는 신속한 검색을 위해 특정 값을 캐시하는 방법에 대해 이야기합니다.

"캐시"와 "캐싱"이라는 용어에 약간의 모호함이있는 것 같고 다른 경우에서 의미에 대해 혼란스러워했습니다. 응용 프로그램 또는 데이터베이스 캐싱, CPU 등을 언급하는지 여부와 그 의미.

캐싱이란 무엇이며 다른 유형은 무엇입니까?

컨텍스트에서 나는 자주 검색된 값을 메인 메모리에 저장하고 그것에 대한 빠른 조회 액세스를 갖는 것에 대한 감각을 얻을 수 있습니다. 그러나 그것은 정말로 무엇입니까?

이 단어는 약간 다른 의미 (cpu, 데이터베이스, 응용 프로그램 등)를 가진 많은 다른 문맥에서 사용되는 것으로 보이며 정말로 그것을 정리하려고합니다.

애플리케이션에서 캐싱이 작동하는 방식과 데이터베이스 캐싱 사이에 차이가 있습니까?

누군가가 캐싱을 해칠 수있는 코드 조각을 발견했다고 말하고이를 수정 한 후 앱의 속도를 향상 시켰습니다. 무엇에 대해 이야기하고 있습니까?

프로그램의 캐싱이 자동으로 수행됩니까? 프로그램에서 값이 캐시되도록 허용하는 방법은 무엇입니까? 이 사이트의 사용자가 애플리케이션에 값을 캐시했다고 말하는 것을 자주 읽습니다. 여기 앉아서 그들이 의미하는 바가 궁금합니다.

또한 누군가가 데이터베이스 캐싱에 대해 이야기 할 때 실제로 무엇을 의미합니까? 이것은 단순히 데이터베이스에서 설정하는 기능입니까? 값을 명시 적으로 캐시해야합니까? 아니면 데이터베이스가 캐시 할 값을 선택합니까?

성능 향상을 위해 직접 항목 캐싱을 시작하려면 어떻게해야합니까?

응용 프로그램 에서 값 캐싱을 시작하는 방법에 대한 몇 가지 예를 제공 할 수 있습니까 ? 또는 다시 말하지만,이 작업은 이미 수행 된 작업이고 내부적으로 "캐싱"을 허용하는 특정 방식으로 코드를 작성해야합니까?

데이터베이스 캐싱은 어떻습니까? 어떻게 시작합니까? memcache와 같은 것에 대해 들었습니다. 이러한 유형의 유틸리티는 데이터베이스에서 캐시하는 데 필요합니까?

나는 응용 프로그램과 데이터베이스의 캐싱, 사용 방법 및 두 경우 모두에서 구현되는 방법 사이의 좋은 구별을 찾고 있습니다.


캐싱은 명시 적 또는 암시 적으로 고성능 저장소 (일반적으로 메모리)에서 데이터를 저장하고 검색하는 방법입니다.

설명하겠습니다. 메모리는 파일, 원격 URL (일반적으로), 데이터베이스 또는 원하는 기타 외부 정보 저장소보다 액세스가 더 빠릅니다. 따라서 이러한 외부 리소스 중 하나를 사용하는 작업이 중요한 경우 캐싱을 통해 성능을 높일 수 있습니다.

Knuth는 조기 최적화가 모든 악의 근원이라고 말했습니다. 글쎄, 조기 캐싱은 내가 생각하는 한 모든 골칫거리의 근원입니다. 당신이 때까지 문제를 해결하지 마십시오 문제. 당신이 내리는 모든 결정은 당신이 지금 그것을 구현하기 위해 지불하고 나중에 그것을 변경하기 위해 다시 지불해야하는 비용이옵니다. 그래서 당신이 더 오래 제빙을하고 시스템을 더 좋게 바꾸는 것을 연기 할 수 있습니다.

따라서 먼저 실제로 문제가 있고 어디에 있는지 확인하십시오 . 프로파일 링, 로깅 및 기타 형태의 성능 테스트가 여기에서 도움이 될 것입니다. 이 단계가 얼마나 중요한지 충분히 강조 할 수 없습니다. 사람들이 문제가되지 않는 것을 "최적화"하는 것을 본 횟수는 엄청납니다.

좋습니다. 성능 문제가 있습니다. 페이지에서 시간이 오래 걸리는 쿼리를 실행하고 있다고 가정 해 보겠습니다. 읽기의 경우 여러 옵션이 있습니다.

  • 쿼리를 별도의 프로세스로 실행하고 결과를 캐시에 저장합니다. 모든 페이지는 단순히 캐시에 액세스합니다. 캐시 된 버전을 적절한 횟수만큼 자주 업데이트 할 수 있습니다 (하루에 한 번, 일주일에 한 번, 5 초에 한 번).
  • 지속성 공급자, ORM 등을 통해 투명하게 캐시합니다. 물론 이것은 사용중인 기술에 따라 다릅니다. 예를 들어 Hibernate와 Ibatis는 쿼리 결과 캐싱을 지원합니다.
  • 결과가 캐시에없는 경우 (또는 지정된 "연령"보다 오래 전에 계산 된 "부실"인 경우) 페이지에서 쿼리를 실행하고 캐시에 넣습니다. 두 개 (또는 그 이상의) 개별 프로세스가 모두 결과를 업데이트해야한다고 결정하면 동시성 문제가 발생하여 동일한 (비싼) 쿼리를 한 번에 8 번 실행하게됩니다. 이 캐시 잠금을 처리 할 수 ​​있지만 다른 성능 문제가 발생합니다. 또한 사용중인 언어의 동시성 메서드 (예 : Java 5 동시성 API)로 대체 할 수도 있습니다.

업데이트 (또는 읽기 캐시에 반영되어야하는 업데이트가 발생하는 경우) 인 경우 캐시에 이전 값이 있고 데이터베이스에 새로운 값이있어 페이지를 제공하는 것이 좋지 않기 때문에 조금 더 복잡합니다. 일관되지 않은 데이터보기가 있습니다. 그러나 광범위하게 말하면 이에 대한 네 가지 접근 방식이 있습니다.

  • 캐시를 업데이트 한 다음 요청을 큐에 넣어 관련 저장소를 업데이트합니다.
  • 캐싱을 통한 쓰기 : 캐시 공급자는 업데이트를 유지하고 변경 될 때까지 호출자를 차단하는 메커니즘을 제공 할 수 있습니다.
  • Write-behind 캐싱 : write-through 캐싱과 동일하지만 호출자를 차단하지 않습니다. 업데이트는 비동기 적으로 개별적으로 발생합니다.
  • 서비스로서의 지속성 모델 : 이것은 캐싱 메커니즘이 일종의 관찰 가능성 (예 : 캐시 이벤트 리스너)을 지원한다고 가정합니다. 기본적으로 호출자에게 알려지지 않은 완전히 별도의 프로세스는 캐시 업데이트를 수신하고 필요에 따라 유지합니다.

위의 방법 중 선택하는 방법은 요구 사항, 사용중인 기술 및 기타 요소 (예 : 클러스터링 및 장애 조치 지원이 필요합니까?)에 따라 크게 달라집니다.

그보다 더 구체적이고 문제에 대해 훨씬 더 자세한 정보 (문제가 있는지 여부 등) 를 알지 못한 상태에서해야 할 일에 대한 지침을 제공하는 것은 어렵습니다 .


웹 애플리케이션의 맥락에서 캐싱에 대해 읽을 가능성이 높습니다. 웹의 특성으로 인해 캐싱은 성능에 큰 차이를 만들 수 있습니다.

다음을 고려하세요:

웹 페이지 요청은 웹 서버에 도착하여 응용 프로그램 서버에 요청을 전달합니다.이 서버는 페이지를 렌더링하는 일부 코드를 실행합니다.이 서버는 데이터를 동적으로 검색하기 위해 데이터베이스로 전환해야합니다.

페이지에 대한 요청 수가 증가함에 따라 서버는 모든 요청에 ​​대해 동일한 작업을 반복해야하기 때문에이 모델은 제대로 확장되지 않습니다.

웹 서버, 애플리케이션 서버 및 데이터베이스가 서로 다른 하드웨어에 있고 네트워크를 통해 서로 통신하는 경우 이는 더욱 문제가됩니다.

이 페이지를 방문하는 사용자가 많은 경우 모든 요청에 ​​대해 데이터베이스를 완전히 검색하지 않는 것이 좋습니다. 대신 다른 수준의 캐싱에 의존합니다.

결과 집합 캐시

결과 집합 캐싱은 응용 프로그램의 쿼리와 함께 데이터베이스 쿼리 결과를 저장합니다. 웹 페이지가 쿼리를 생성 할 때마다 애플리케이션은 결과가 이미 캐시되었는지 확인하고, 캐시 된 경우 대신 인 메모리 데이터 세트에서 결과를 가져옵니다. 애플리케이션은 여전히 ​​페이지를 렌더링해야합니다.

구성 요소 캐시

웹 페이지는 페이지 릿 또는 호출 할 수있는 다른 구성 요소로 구성됩니다. 구성 요소 캐싱 전략은 구성 요소를 요청하는 데 사용 된 매개 변수를 알아야합니다. 예를 들어, 사이트의 작은 "최신 뉴스"막대는 사용자의 지리적 위치 또는 선호도를 사용하여 지역 뉴스를 표시합니다. 결과적으로 위치에 대한 뉴스가 캐시되면 구성 요소를 렌더링 할 필요가 없으며 캐시에서 가져올 수 있습니다.

페이지 캐시

전체 페이지를 캐싱하는 한 가지 전략은 완전히 렌더링 된 HTML과 함께 쿼리 문자열 및 / 또는 헤더 매개 변수를 저장하는 것입니다. 파일 시스템은이를 위해 충분히 빠릅니다. 페이지를 렌더링하기 위해 응용 프로그램 서버를 호출하는 것보다 웹 서버가 파일을 읽는 것이 훨씬 저렴합니다. 이 경우 동일한 쿼리 문자열을 보내는 모든 사용자는 동일한 캐시 된 콘텐츠를 받게됩니다.

이러한 캐싱 전략을 지능적으로 결합하는 것은 다수의 동시 사용자를 위해 확장 가능한 웹 앱을 만드는 유일한 방법입니다. 쉽게 알 수 있듯이 여기에서 잠재적 인 위험은 캐시의 콘텐츠 조각을 키로 고유하게 식별 할 수없는 경우 사람들이 잘못된 콘텐츠를보기 시작한다는 것입니다. 특히 사용자에게 세션이 있고 보안 컨텍스트가있는 경우 이는 매우 복잡해질 수 있습니다.


내가 아는 두 가지 의미가 있습니다.


하나는 애플리케이션 캐싱 입니다. 데이터가 어딘가에서 (예 : 네트워크를 통해) 가져 오는 속도가 느리거나 계산 속도가 느린 경우 애플리케이션이 데이터 사본을 캐시합니다 (다시 가져 오거나 다시 계산할 필요가 없습니다. 이미 캐시 됨). 캐시를 구현하려면 약간의 추가 응용 프로그램 소프트웨어 (캐시를 사용하는 논리)와 추가 메모리 (캐시 된 데이터를 저장하기위한)가 필요합니다.

여기에서 인용하는 것처럼 "캐싱"이 사용됩니다.

컨텍스트에서 나는 자주 검색된 값을 주 메모리에 저장하고 이에 대한 빠른 조회 액세스 권한을 얻을 수 있습니다.


또 하나는 CPU 캐싱 인데, 이 Wikipedia 기사 에서 설명 합니다. CPU 캐싱은 자동으로 발생합니다. 적은 양의 메모리에서 많은 읽기를 수행하면 CPU가 캐시에서 대부분의 읽기를 수행 할 수 있습니다. 많은 양의 메모리에서 읽는 경우 OTOH는 캐시에 모두 들어갈 수 없으며 CPU는 느린 메모리로 작업하는 데 더 많은 시간을 소비해야합니다.

여기에서 인용하는 것처럼 "캐싱"이 사용됩니다.

누군가가 캐싱을 해칠 수있는 코드 조각을 발견했다고 말하고이를 수정 한 후 앱의 속도를 향상 시켰습니다. 무엇에 대해 이야기하고 있습니까?

이는 캐시 미스 를 줄이기 위해 코드를 재배 열하는 방법을 찾았 음을 의미 합니다.


데이터베이스 캐싱에 관해서는 모르겠습니다.


몇 가지 문제가 있습니다.

하나는 세분성입니다. 응용 프로그램은 데이터베이스가 수행하는 작업보다 훨씬 높은 수준의 캐싱을 가질 수 있습니다. 예를 들어, 데이터베이스는 특정 행이 아니라 단순히 데이터 페이지를 캐시 할 가능성이 높습니다.

또 다른 점은 애플리케이션이 데이터를 "기본"형식으로 저장할 수있는 반면, DB는 내부 형식으로 만 캐시한다는 것입니다.

간단한 예.

당신이 열 구성되어 데이터베이스에서 사용자가 말 : USERID, FIRSTNAME, LASTNAME. 아주 간단합니다.

사용자를 USERID=123응용 프로그램 에로드하려고 합니다. 관련된 단계는 무엇입니까?

  1. 데이터베이스 호출 실행
  2. 요청 파싱 ( SELECT * FROM USER WHERE USERID = ?)
  3. 요청 계획 (즉, 시스템이 데이터를 가져 오는 방법)
  4. 디스크에서 데이터 가져 오기
  5. 데이터베이스에서 애플리케이션으로 데이터 스트리밍
  6. Converting the Database data to application data (i.e. USERID to an integer, say, the names to Strings.

The database cache will, likely, caches steps 2 and 3 (that's a statement cache, so it won't parse or replan the query), and caches the actual disk blocks.

So, here's the key. Your user, USER ID 123, name JESSE JAMES. You can see that this isn't a lot of data. But the database is caching disk blocks. You have the index block (with the 123 on it), then the data block (with the actual data, and all of the other rows that fit on that block). So what is nominally, say, 60-70 bytes of data actually has a caching and data impact on the DB of, probably, 4K-16K (depends on block size).

The bright side? If you need another row that's nearby (say USER ID = 124), odds are high the index and data are already cached.

But even with that caching, you still have to pay the cost to move the data over the wire (and it's alway over the wire unless you're using a local DB, then that's loopback), and you're "unmarshalling" the data. That is, converting it from Database bits to language bits, to Application bits.

Now, once the Application get its USER ID 123, it stuff the value in a long lived hash map.

If the application ever wants it again, it will look in the local map, the application cache, and save the lookup, wire transport, and marshalling costs.

The dark side of application caching is synchronization. If someone comes in and does a UPDATE USER SET LASTNAME="SMITH" WHERE USERID=123, your application doesn't "know that", and thus the cache is dirty.

So, then there's a bunch of details in handling that relationship to keep the application in sync with the DB.

Having a LOT of database cache is very nice for large queries over a "hot" set of data. The more memory you have, the more "hot" data you can have. Up to the point if you can cache the entire DB in RAM, you eliminate the I/O (at least for reads) delay of moving data from the disk to a RAM buffer. But you still have the transport and marshalling costs.

The Application can be much more selective, such as caching more limited subsets of data (DBs just cache blocks), and having the data "closer" to the application ekes out that much better performance.

The down side is that not everything is cached in the Application. The database tends to store data more efficiently, overall, than the application. You also lack a "query" language against your app cached data. Most folks simply cache via a simple key and go from there. Easy to find USER ID 123, harder for "ALL USERS NAMED JESSE".

Database caching tends to be "free", you set a buffer number and the DBMS handles the rest. Low impact, reduces overall I/O and disk delays.

Application caching is, well, application specific.

It works very well for isolated "static" data. That's very easy. Load a bunch of stuff in to lookup tables at startup and restart the app if they change. That's easy to do.

After that complexity starts to increase as you add in "dirty" logic, etc.

What it all comes down to, tho, is that as long as you have a Data API, you can cache incrementally.

So, as long as you call getUser(123) everywhere rather than hitting the DB, then you can later come back and add caching to getUser without impacting your code.

So, I always suggest some kind of Data Access Layer in everyone's code, to provide that bit of abstraction and interception layer.


caching is taking the result of a long or cpu intensive algorithm and saving the answer so that you do not have to run the algorithm again, you just reuse the result.


The cache concept is an overloaded term here. I'm not familiar with the nuts and bolts of database caching.

In applications there are two uses of the term.

When someone says that they found a piece of code that would hurt caching and after they fixed it, it improved the speed of their app, what are they talking about?

In this case they're making reference to the CPU cache.

The CPU cache is on-CPU memory that's a lot quicker than RAM, but it doesn't have random access. What the CPU decides to load into cache can get a little complicated. See Ulrich Dreppers What every programmer should know about memory for lots of details.

Being mindful of the CPU cache can speed things up pretty well - you just have to pay a little more attention to where things are going to placed relative to each other in physical memory and when they're likely to be used.

One example (also probably an anti-pattern for maintainability) is that is you have an array of structures and you do a lot of looping over the members of the structure you might be better served with a structure where the fields are all arrays. If the data you're looping over is contiguous in memory you have a better chance at non upsetting the cache.

All kinds of things can effect the efficiency of your cache usage - branch prediction for code loaded into the cache, size and alignment of data structures and access patterns, where and when to declare local variables that are going to be put onto the stack.

The other common use of the term for application programming can be done by something called memoization. The factorial example on that wikipedia page explains things better than I would have done.


Caching in databases is typically a function the database and it is managed automatically by the database. Caching in applications is going to vary from one platform to another.

An object cache is a mechanism that you can use to put commonly used objects into memory so that you don't need to pay the cost to retrieve the data and recreate them. This is generally managed via code and varies on what caching solution you are using.

There are distributed cache solutions that involve setting up services on multiple servers to give you a cache farm of sorts. This provides scalability and redundancy. The clients can request the cached information across the network. Again this is a manual procedure in your code. An example of a distributed cache provider is memcached:

http://www.danga.com/memcached/

An example of a specific type of caching would be the asp.net caching. Asp.net supports several kinds of cache. There is the traditional object cache (which can be used in all kinds of .net apps, not just websites). There is also caching features that allow you to configure pages and user controls to automatically cache their output. This doesn't cache data, it caches the end result (the HTML of the page) and serves that up when the user requests the same page with the same query string parms as a previous user.


It's probably easier than you could imagine--and that's why people are trying to close it.

It just means to store the values in your memory rather than go back to the database for them every time.

There are lots of ways to do so, but the concept itself is trivial.

Edit: It can be done at ANY level too--anything that takes a long time can be cached somewhere that you can get to more quickly.


Caching does not necessarily only apply to 'oft retrieved' values but to anything you can save time on by reducing the number of times you recompute it. A simple example that comes to mind is calculating the fibonacci sequence. The simplest recursive implementation looks like this (in psuedo-code):

function f(n)
    if n < 2 then
        return n;
    return f(n - 1) + f(n - 2)

This can be improved with caching to prevent recalculating already known values:

fib_cache = {}

function f(n)
    if n < 2 then
        return n;
    if fib_cache.contains(n) then
        return fib_cache[n]
    fib_cache[n] = f(n - 1) + f(n - 2)
    return fib_cache[n]

참고URL : https://stackoverflow.com/questions/548301/what-is-caching

반응형