В информатике постоянная память — это любой метод или устройство для эффективного хранения структур данных, к которым можно продолжать получать доступ с помощью инструкций памяти или API памяти даже после завершения процесса, который их создал или в последний раз изменил. [ 1]
Постоянная память, которую часто путают с энергонезависимой памятью с произвольным доступом (NVRAM), на самом деле более тесно связана с концепцией постоянства , поскольку она делает акцент на состоянии программы, которое существует за пределами зоны сбоя процесса, создавшего ее. (Процесс — это программа, находящаяся в процессе выполнения. Зона сбоя процесса — это подмножество состояния программы, которое может быть повреждено процессом, продолжающим выполняться после возникновения сбоя, например, из-за ненадежного компонента, используемого в компьютере, выполняющем программу.)
Эффективный, подобный памяти доступ является определяющей характеристикой постоянной памяти. [2] Он может быть предоставлен с использованием инструкций памяти микропроцессора , таких как загрузка и сохранение. Он также может быть предоставлен с использованием API, которые реализуют действия удаленного прямого доступа к памяти (RDMA), такие как чтение RDMA и запись RDMA. Другие методы с низкой задержкой , которые обеспечивают доступ к данным с побайтовым [ требуется разъяснение ] , также подходят.
Возможности постоянной памяти выходят за рамки энергонезависимости хранимых битов. Например, потеря ключевых метаданных, таких как записи таблицы страниц или другие конструкции, которые преобразуют виртуальные адреса в физические адреса, может сделать постоянные биты непостоянными. В этом отношении постоянная память напоминает более абстрактные формы компьютерного хранения, такие как файловые системы . Фактически, почти все существующие технологии постоянной памяти реализуют по крайней мере базовую файловую систему, которая может использоваться для связывания имен или идентификаторов с хранимыми экстентами, и как минимум предоставляют методы файловой системы, которые могут использоваться для именования и выделения таких экстентов.
Проблема чтения неперсистентной записи обнаружена для программ без блокировки в постоянной памяти. Поскольку операции сравнения и обмена (CAS) не сохраняют записанные значения в постоянной памяти, измененные данные могут быть сделаны видимыми протоколом когерентности кэша для параллельного наблюдателя до того, как измененные данные смогут быть замечены наблюдателем сбоя в постоянной памяти. Если сбой питания происходит сразу после того, как запись становится видимой, но еще не сохраняется, может возникнуть проблема чтения неперсистентной записи, т. е. переменная данных, измененная операцией сравнения и обмена, может быть сделана видимой для параллельного наблюдателя до наблюдателя сбоя, что приводит к потенциальным несоответствиям сбоя.
Чтобы проиллюстрировать проблему: для однократно связанного списка без блокировки узел может быть вставлен производителем thread A
после head
узла, next
указатель головного узла атомарно переключается (CAS) для указания на новый node A
, однако этот CAS не сохраняется. Затем другой узел вставляется производителем thread B
после node A
, так как CAS для node A
уже виден всем параллельным потокам. CAS атомарно переключает next
указатель node A
на на node B
, и этот CAS сохраняется. Если в этот момент произойдет сбой питания, приложение, использующее связанный список, останется в несогласованном состоянии, причем оба node A
и будут node B
потеряны, так как next
указатель с head
узла на node A
не был сохранен. Как node B
был опубликован, но не может быть доступен после перезагрузки, и могли быть сохранены другие данные, к которым осуществляется доступ через или которые зависят от node B
, все последующие доступы к таким данным будут невозможны, что приведет к потере данных. [3]
Проблема чтения-непостоянной-записи не ограничивается связными списками без блокировки, ее можно найти в любых структурах данных без блокировки, где может существовать потенциальный разрыв между параллельной видимостью и постоянной видимостью. Например, похожая проблема может возникнуть с постоянными кольцевыми буферами . [4]