diff -Nuar a/vendor/magento/module-eav/Model/Config.php b/vendor/magento/module-eav/Model/Config.php
--- a/vendor/magento/module-eav/Model/Config.php
+++ b/vendor/magento/module-eav/Model/Config.php
@@ -157,12 +157,12 @@ class Config
 
     /**
      * @param \Magento\Framework\App\CacheInterface $cache
-     * @param \Magento\Eav\Model\Entity\TypeFactory $entityTypeFactory
-     * @param \Magento\Eav\Model\ResourceModel\Entity\Type\CollectionFactory $entityTypeCollectionFactory
+     * @param Entity\TypeFactory $entityTypeFactory
+     * @param ResourceModel\Entity\Type\CollectionFactory $entityTypeCollectionFactory
      * @param \Magento\Framework\App\Cache\StateInterface $cacheState
      * @param \Magento\Framework\Validator\UniversalFactory $universalFactory
-     * @param SerializerInterface $serializer
-     * @param ScopeConfigInterface $scopeConfig
+     * @param SerializerInterface|null $serializer
+     * @param ScopeConfigInterface|null $scopeConfig
      * @param array $attributesForPreload
      * @codeCoverageIgnore
      */
@@ -245,8 +245,8 @@ class Config
     /**
      * Associate object with identifier
      *
-     * @param   mixed $obj
-     * @param   mixed $id
+     * @param mixed $obj
+     * @param mixed $id
      * @return void
      * @codeCoverageIgnore
      */
@@ -271,8 +271,8 @@ class Config
     /**
      * Specify reference for entity type id
      *
-     * @param   int $id
-     * @param   string $code
+     * @param int $id
+     * @param string $code
      * @return $this
      * @codeCoverageIgnore
      */
@@ -296,9 +296,9 @@ class Config
     /**
      * Specify reference between entity attribute id and attribute code
      *
-     * @param   int $id
-     * @param   string $code
-     * @param   string $entityTypeCode
+     * @param int $id
+     * @param string $code
+     * @param string $entityTypeCode
      * @return $this
      */
     protected function _addAttributeReference($id, $code, $entityTypeCode)
@@ -374,7 +374,9 @@ class Config
         }
         \Magento\Framework\Profiler::start('EAV: ' . __METHOD__, ['group' => 'EAV', 'method' => __METHOD__]);
 
-        if ($this->isCacheEnabled() && ($cache = $this->_cache->load(self::ENTITIES_CACHE_ID))) {
+        if ($this->isCacheEnabled() &&
+            ($cache = $this->_cache->load(self::ENTITIES_CACHE_ID))
+        ) {
             $this->_entityTypeData = $this->serializer->unserialize($cache);
             foreach ($this->_entityTypeData as $typeCode => $data) {
                 $typeId = $data['entity_type_id'];
@@ -522,9 +524,9 @@ class Config
     /**
      * Get attribute by code for entity type
      *
-     * @param   mixed $entityType
-     * @param   mixed $code
-     * @return  AbstractAttribute
+     * @param mixed $entityType
+     * @param mixed $code
+     * @return AbstractAttribute
      * @throws LocalizedException
      */
     public function getAttribute($entityType, $code)
@@ -737,8 +739,8 @@ class Config
     /**
      * Get all entity type attributes
      *
-     * @param  int|string|Type $entityType
-     * @param  \Magento\Framework\DataObject|null $object
+     * @param int|string|Type $entityType
+     * @param \Magento\Framework\DataObject|null $object
      * @return AbstractAttribute[]
      *
      * @SuppressWarnings(PHPMD.CyclomaticComplexity)
@@ -822,6 +824,10 @@ class Config
             $fullAttributeData = array_key_exists('is_required', $attributeData);
 
             if ($existsFullAttribute || (!$existsFullAttribute && !$fullAttributeData)) {
+                $scopeIsRequired = $attributeData['scope_is_required'] ?? null;
+                if ($scopeIsRequired !== null) {
+                    $attribute->setData('scope_is_required', $scopeIsRequired);
+                }
                 return $attribute;
             }
         }
diff -Nuar a/vendor/magento/module-eav/Model/ResourceModel/Entity/Attribute/Set.php b/vendor/magento/module-eav/Model/ResourceModel/Entity/Attribute/Set.php
--- a/vendor/magento/module-eav/Model/ResourceModel/Entity/Attribute/Set.php
+++ b/vendor/magento/module-eav/Model/ResourceModel/Entity/Attribute/Set.php
@@ -6,6 +6,9 @@
 
 namespace Magento\Eav\Model\ResourceModel\Entity\Attribute;
 
+/**
+ * Basic implementation for attribute sets
+ */
 class Set extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb
 {
     /**
@@ -24,8 +27,6 @@ class Set extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb
     protected $eavConfig;
 
     /**
-     * Constructor
-     *
      * @param \Magento\Framework\Model\ResourceModel\Db\Context $context
      * @param GroupFactory $attrGroupFactory
      * @param \Magento\Eav\Model\Config $eavConfig
@@ -54,7 +55,7 @@ class Set extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb
     }
 
     /**
-     * Perform actions after object save
+     * Perform actions after object save.
      *
      * @param \Magento\Framework\Model\AbstractModel $object
      * @return $this
diff -Nuar a/vendor/magento/module-eav/etc/di.xml b/vendor/magento/module-eav/etc/di.xml
--- a/vendor/magento/module-eav/etc/di.xml
+++ b/vendor/magento/module-eav/etc/di.xml
@@ -209,4 +209,14 @@
             </argument>
         </arguments>
     </type>
+    <virtualType name="configured_eav_cache" type="Magento\Framework\App\Cache">
+        <arguments>
+            <argument name="cacheIdentifier" xsi:type="string">eav</argument>
+        </arguments>
+    </virtualType>
+    <type name="Magento\Eav\Model\Config">
+        <arguments>
+            <argument name="cache" xsi:type="object">configured_eav_cache</argument>
+        </arguments>
+    </type>
 </config>
diff -Nuar a/vendor/magento/module-theme/etc/di.xml b/vendor/magento/module-theme/etc/di.xml
--- a/vendor/magento/module-theme/etc/di.xml
+++ b/vendor/magento/module-theme/etc/di.xml
@@ -285,4 +285,24 @@
             <argument name="identifierName" xsi:type="string">theme_id</argument>
         </arguments>
     </type>
+    <virtualType name="configured_design_cache" type="Magento\Framework\App\Cache">
+        <arguments>
+            <argument name="cacheIdentifier" xsi:type="string">layout</argument>
+        </arguments>
+    </virtualType>
+    <virtualType name="design_context" type="Magento\Framework\Model\Context">
+        <arguments>
+            <argument name="cacheManager" xsi:type="object">configured_design_cache</argument>
+        </arguments>
+    </virtualType>
+    <type name="Magento\Theme\Model\Design">
+        <arguments>
+            <argument name="context" xsi:type="object">design_context</argument>
+        </arguments>
+    </type>
+    <type name="Magento\Theme\Model\Theme\ThemeProvider">
+        <arguments>
+            <argument name="cache" xsi:type="object">configured_design_cache</argument>
+        </arguments>
+    </type>
 </config>
diff -Nuar a/app/etc/di.xml b/app/etc/di.xml
--- a/app/etc/di.xml
+++ b/app/etc/di.xml
@@ -1780,8 +1780,6 @@
     <type name="Magento\Framework\Cache\LockGuardedCacheLoader">
         <arguments>
             <argument name="locker" xsi:type="object">Magento\Framework\Lock\Backend\Cache</argument>
-            <argument name="lockTimeout" xsi:type="number">10000</argument>
-            <argument name="delayTimeout" xsi:type="number">20</argument>
         </arguments>
     </type>
     <preference for="Magento\Framework\HTTP\AsyncClientInterface" type="Magento\Framework\HTTP\AsyncClient\GuzzleAsyncClient" />
@@ -1800,4 +1798,14 @@
     </type>
     <preference for="Magento\Framework\GraphQl\Query\ErrorHandlerInterface" type="Magento\Framework\GraphQl\Query\ErrorHandler"/>
     <preference for="Magento\Framework\Filter\VariableResolverInterface" type="Magento\Framework\Filter\VariableResolver\StrategyResolver"/>
+    <virtualType name="configured_block_cache" type="Magento\Framework\App\Cache">
+        <arguments>
+            <argument name="cacheIdentifier" xsi:type="string">block_html</argument>
+        </arguments>
+    </virtualType>
+    <type name="Magento\Framework\View\Element\Context">
+        <arguments>
+            <argument name="cache" xsi:type="object">configured_block_cache</argument>
+        </arguments>
+    </type>
 </config>
diff -Nuar a/vendor/magento/framework/App/Cache.php b/vendor/magento/framework/App/Cache.php
--- a/vendor/magento/framework/App/Cache.php
+++ b/vendor/magento/framework/App/Cache.php
@@ -4,12 +4,11 @@
  * See COPYING.txt for license details.
  */
 
-/**
- * System cache model
- * support id and tags prefix support,
- */
 namespace Magento\Framework\App;
 
+/**
+ * System cache model support id and tags prefix support.
+ */
 class Cache implements CacheInterface
 {
     /**
@@ -30,12 +29,13 @@ class Cache implements CacheInterface
     protected $_frontend;
 
     /**
-     * @param \Magento\Framework\App\Cache\Frontend\Pool $frontendPool
+     * @param Cache\Frontend\Pool $frontendPool
+     * @param string|null $cacheIdentifier
      */
-    public function __construct(\Magento\Framework\App\Cache\Frontend\Pool $frontendPool)
+    public function __construct(\Magento\Framework\App\Cache\Frontend\Pool $frontendPool, $cacheIdentifier = null)
     {
         $this->_frontendPool = $frontendPool;
-        $this->_frontend = $frontendPool->get($this->_frontendIdentifier);
+        $this->_frontend = $frontendPool->get($cacheIdentifier ?? $this->_frontendIdentifier);
     }
 
     /**
diff -Nuar a/vendor/magento/framework/App/Cache/Frontend/Pool.php b/vendor/magento/framework/App/Cache/Frontend/Pool.php
--- a/vendor/magento/framework/App/Cache/Frontend/Pool.php
+++ b/vendor/magento/framework/App/Cache/Frontend/Pool.php
@@ -152,6 +152,15 @@ class Pool implements \Iterator
         if (isset($this->_instances[$identifier])) {
             return $this->_instances[$identifier];
         }
-        throw new \InvalidArgumentException("Cache frontend '{$identifier}' is not recognized.");
+
+        if (!isset($this->_instances[self::DEFAULT_FRONTEND_ID])) {
+            throw new \InvalidArgumentException(
+                "Cache frontend '{$identifier}' is not recognized. As well as " .
+                self::DEFAULT_FRONTEND_ID .
+                "cache is not configured"
+            );
+        }
+
+        return $this->_instances[self::DEFAULT_FRONTEND_ID];
     }
 }
diff -Nuar a/vendor/magento/framework/App/Router/ActionList.php b/vendor/magento/framework/App/Router/ActionList.php
--- a/vendor/magento/framework/App/Router/ActionList.php
+++ b/vendor/magento/framework/App/Router/ActionList.php
@@ -5,6 +5,8 @@
  */
 namespace Magento\Framework\App\Router;
 
+use Magento\Framework\App\Filesystem\DirectoryList;
+use Magento\Framework\App\State;
 use Magento\Framework\Serialize\SerializerInterface;
 use Magento\Framework\Serialize\Serializer\Serialize;
 use Magento\Framework\Module\Dir\Reader as ModuleReader;
@@ -70,12 +72,26 @@ class ActionList
         $this->reservedWords = array_merge($reservedWords, $this->reservedWords);
         $this->actionInterface = $actionInterface;
         $this->serializer = $serializer ?: \Magento\Framework\App\ObjectManager::getInstance()->get(Serialize::class);
-        $data = $cache->load($cacheKey);
-        if (!$data) {
-            $this->actions = $moduleReader->getActionFiles();
-            $cache->save($this->serializer->serialize($this->actions), $cacheKey);
+        $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
+        $state = $objectManager->get(State::class);
+
+        if ($state->getMode() === State::MODE_PRODUCTION) {
+            $directoryList = $objectManager->get(DirectoryList::class);
+            $file = $directoryList->getPath(DirectoryList::GENERATED_METADATA) . '/' . $cacheKey . '.' . 'php';
+
+            if (file_exists($file)) {
+                $this->actions = (include $file) ?? $moduleReader->getActionFiles();
+            } else {
+                $this->actions = $moduleReader->getActionFiles();
+            }
         } else {
-            $this->actions = $this->serializer->unserialize($data);
+            $data = $cache->load($cacheKey);
+            if (!$data) {
+                $this->actions = $moduleReader->getActionFiles();
+                $cache->save($this->serializer->serialize($this->actions), $cacheKey);
+            } else {
+                $this->actions = $this->serializer->unserialize($data);
+            }
         }
     }
 
diff -Nuar a/2.3.5/vendor/magento/framework/Cache/Backend/Redis.php b/vendor/magento/framework/Cache/Backend/Redis.php
new file mode 100644
--- /dev/null
+++ b/vendor/magento/framework/Cache/Backend/Redis.php
@@ -0,0 +1,83 @@
+<?php
+/**
+ * Copyright © Magento, Inc. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Framework\Cache\Backend;
+
+/**
+ * Redis wrapper to extend current implementation behaviour.
+ */
+class Redis extends \Cm_Cache_Backend_Redis
+{
+    /**
+     * Local state of preloaded keys.
+     *
+     * @var array
+     */
+    private $preloadedData = [];
+
+    /**
+     * Array of keys to be preloaded.
+     *
+     * @var array
+     */
+    private $preloadKeys = [];
+
+    /**
+     * @param array $options
+     */
+    public function __construct($options = [])
+    {
+        $this->preloadKeys = $options['preload_keys'] ?? [];
+        parent::__construct($options);
+    }
+
+    /**
+     * Load value with given id from cache
+     *
+     * @param  string  $id                     Cache id
+     * @param  boolean $doNotTestCacheValidity If set to true, the cache validity won't be tested
+     * @return bool|string
+     */
+    public function load($id, $doNotTestCacheValidity = false)
+    {
+        if (!empty($this->preloadKeys) && empty($this->preloadedData)) {
+            $redis =  $this->_slave ?? $this->_redis;
+            $redis = $redis->pipeline();
+
+            foreach ($this->preloadKeys as $key) {
+                $redis->hGet(self::PREFIX_KEY . $key, self::FIELD_DATA);
+            }
+
+            $this->preloadedData = array_filter(array_combine($this->preloadKeys, $redis->exec()));
+        }
+
+        if (isset($this->preloadedData[$id])) {
+            return $this->_decodeData($this->preloadedData[$id]);
+        }
+
+        return parent::load($id, $doNotTestCacheValidity);
+    }
+
+    /**
+     * Cover errors on save operations, which may occurs when Redis cannot evict keys, which is expected in some cases.
+     *
+     * @param string $data
+     * @param string $id
+     * @param array $tags
+     * @param bool $specificLifetime
+     * @return bool
+     */
+    public function save($data, $id, $tags = [], $specificLifetime = false)
+    {
+        try {
+            parent::save($data, $id, $tags, $specificLifetime);
+        } catch (\Throwable $exception) {
+            return false;
+        }
+
+        return true;
+    }
+}
diff -Nuar a/vendor/magento/framework/Cache/Backend/RemoteSynchronizedCache.php b/vendor/magento/framework/Cache/Backend/RemoteSynchronizedCache.php
--- a/vendor/magento/framework/Cache/Backend/RemoteSynchronizedCache.php
+++ b/vendor/magento/framework/Cache/Backend/RemoteSynchronizedCache.php
@@ -9,8 +9,10 @@ namespace Magento\Framework\Cache\Backend;
 /**
  * Remote synchronized cache
  *
- * This class created for correct work local caches with multiple web nodes,
- * that will be check cache status from remote cache
+ * This class created for correct work witch local caches and multiple web nodes,
+ * in order to be sure that we always have up to date local version of cache.
+ * This class will be check cache version from remote cache and in case it newer
+ * than local one, it will update local one from remote cache a.k.a two level cache.
  */
 class RemoteSynchronizedCache extends \Zend_Cache_Backend implements \Zend_Cache_Backend_ExtendedInterface
 {
@@ -36,11 +38,15 @@ class RemoteSynchronizedCache extends \Zend_Cache_Backend implements \Zend_Cache
     protected $cacheInvalidationTime;
 
     /**
-     * {@inheritdoc}
+     * Suffix for hash to compare data version in cache storage.
+     */
+    private const HASH_SUFFIX = ':hash';
+
+    /**
+     * @inheritdoc
      */
     protected $_options = [
         'remote_backend' => '',
-        'remote_backend_invalidation_time_id' => 'default_remote_backend_invalidation_time',
         'remote_backend_custom_naming' => true,
         'remote_backend_autoload' => true,
         'remote_backend_options' => [],
@@ -52,6 +58,7 @@ class RemoteSynchronizedCache extends \Zend_Cache_Backend implements \Zend_Cache
 
     /**
      * @param array $options
+     * @throws \Zend_Cache_Exception
      */
     public function __construct(array $options = [])
     {
@@ -97,76 +104,137 @@ class RemoteSynchronizedCache extends \Zend_Cache_Backend implements \Zend_Cache
     }
 
     /**
-     * Update remote cache status info
+     * @inheritdoc
+     */
+    public function setDirectives($directives)
+    {
+        return $this->local->setDirectives($directives);
+    }
+
+    /**
+     * Return hash sign of the data.
      *
-     * @return void
+     * @param string $data
+     * @return string
      */
-    private function updateRemoteCacheStatusInfo()
+    private function getDataVersion(string $data)
     {
-        $this->remote->save(time(), $this->_options['remote_backend_invalidation_time_id'], [], null);
-        $this->cacheInvalidationTime = null;
+        return \hash('sha256', $data);
     }
 
     /**
-     * {@inheritdoc}
+     * Load data version by id from remote.
+     *
+     * @param string $id
+     * @return false|string
      */
-    public function setDirectives($directives)
+    private function loadRemoteDataVersion(string $id)
     {
-        return $this->local->setDirectives($directives);
+        return $this->remote->load(
+            $id . self::HASH_SUFFIX
+        );
     }
 
     /**
-     * {@inheritdoc}
+     * Save new data version to remote.
+     *
+     * @param string $data
+     * @param string $id
+     * @param array $tags
+     * @param mixed $specificLifetime
+     * @return bool
+     */
+    private function saveRemoteDataVersion(string $data, string $id, array $tags, $specificLifetime = false)
+    {
+        return $this->remote->save($this->getDataVersion($data), $id . self::HASH_SUFFIX, $tags, $specificLifetime);
+    }
+
+    /**
+     * Remove remote data version.
+     *
+     * @param string $id
+     * @return bool
+     */
+    private function removeRemoteDataVersion($id)
+    {
+        return $this->remote->remove($id . self::HASH_SUFFIX);
+    }
+
+    /**
+     * @inheritdoc
      */
     public function load($id, $doNotTestCacheValidity = false)
     {
-        $dataModificationTime = $this->local->test($id);
-        if ($this->cacheInvalidationTime === null) {
-            $this->cacheInvalidationTime = $this->remote->load($this->_options['remote_backend_invalidation_time_id']);
-        }
-        if ($dataModificationTime >= $this->cacheInvalidationTime) {
-            return $this->local->load($id, $doNotTestCacheValidity);
+        $localData = $this->local->load($id);
+        $remoteData = false;
+
+        if (false === $localData) {
+            $remoteData = $this->remote->load($id);
+
+            if (false === $remoteData) {
+                return false;
+            }
         } else {
-            return false;
+            if ($this->getDataVersion($localData) !== $this->loadRemoteDataVersion($id)) {
+                $localData = false;
+                $remoteData = $this->remote->load($id);
+            }
         }
+
+        if ($remoteData !== false) {
+            $this->local->save($remoteData, $id);
+            $localData = $remoteData;
+        }
+
+        return $localData;
     }
 
     /**
-     * {@inheritdoc}
+     * @inheritdoc
      */
     public function test($id)
     {
-        return $this->local->test($id);
+        return $this->local->test($id) ?? $this->remote->test($id);
     }
 
     /**
-     * {@inheritdoc}
+     * @inheritdoc
      */
     public function save($data, $id, $tags = [], $specificLifetime = false)
     {
-        return $this->local->save($data, $id, $tags, $specificLifetime);
+        $dataToSave = $data;
+        $remHash = $this->loadRemoteDataVersion($id);
+
+        if ($remHash !== false && $this->getDataVersion($data) === $remHash) {
+            $dataToSave = $this->remote->load($id);
+        } else {
+            $this->remote->save($data, $id, $tags, $specificLifetime);
+            $this->saveRemoteDataVersion($data, $id, $tags, $specificLifetime);
+        }
+
+        return $this->local->save($dataToSave, $id, [], $specificLifetime);
     }
 
     /**
-     * {@inheritdoc}
+     * @inheritdoc
      */
     public function remove($id)
     {
-        $this->updateRemoteCacheStatusInfo();
-        return $this->local->remove($id);
+         return $this->removeRemoteDataVersion($id) &&
+            $this->remote->remove($id) &&
+            $this->local->remove($id);
     }
 
     /**
-     * {@inheritdoc}
+     * @inheritdoc
      */
     public function clean($mode = \Zend_Cache::CLEANING_MODE_ALL, $tags = [])
     {
-        $this->updateRemoteCacheStatusInfo();
-        return $this->local->clean($mode, $tags);
+        return $this->remote->clean($mode, $tags);
     }
 
     /**
-     * {@inheritdoc}
+     * @inheritdoc
      */
     public function getIds()
     {
@@ -174,7 +242,7 @@ class RemoteSynchronizedCache extends \Zend_Cache_Backend implements \Zend_Cache
     }
 
     /**
-     * {@inheritdoc}
+     * @inheritdoc
      */
     public function getTags()
     {
@@ -182,7 +250,7 @@ class RemoteSynchronizedCache extends \Zend_Cache_Backend implements \Zend_Cache
     }
 
     /**
-     * {@inheritdoc}
+     * @inheritdoc
      */
     public function getIdsMatchingTags($tags = [])
     {
@@ -190,7 +258,7 @@ class RemoteSynchronizedCache extends \Zend_Cache_Backend implements \Zend_Cache
     }
 
     /**
-     * {@inheritdoc}
+     * @inheritdoc
      */
     public function getIdsNotMatchingTags($tags = [])
     {
@@ -198,7 +266,7 @@ class RemoteSynchronizedCache extends \Zend_Cache_Backend implements \Zend_Cache
     }
 
     /**
-     * {@inheritdoc}
+     * @inheritdoc
      */
     public function getIdsMatchingAnyTags($tags = [])
     {
@@ -206,7 +274,7 @@ class RemoteSynchronizedCache extends \Zend_Cache_Backend implements \Zend_Cache
     }
 
     /**
-     * {@inheritdoc}
+     * @inheritdoc
      */
     public function getFillingPercentage()
     {
@@ -214,7 +282,7 @@ class RemoteSynchronizedCache extends \Zend_Cache_Backend implements \Zend_Cache
     }
 
     /**
-     * {@inheritdoc}
+     * @inheritdoc
      */
     public function getMetadatas($id)
     {
@@ -222,7 +290,7 @@ class RemoteSynchronizedCache extends \Zend_Cache_Backend implements \Zend_Cache
     }
 
     /**
-     * {@inheritdoc}
+     * @inheritdoc
      */
     public function touch($id, $extraLifetime)
     {
@@ -230,7 +298,7 @@ class RemoteSynchronizedCache extends \Zend_Cache_Backend implements \Zend_Cache
     }
 
     /**
-     * {@inheritdoc}
+     * @inheritdoc
      */
     public function getCapabilities()
     {
diff -Nuar a/vendor/magento/framework/Cache/LockGuardedCacheLoader.php b/vendor/magento/framework/Cache/LockGuardedCacheLoader.php
--- a/vendor/magento/framework/Cache/LockGuardedCacheLoader.php
+++ b/vendor/magento/framework/Cache/LockGuardedCacheLoader.php
@@ -36,19 +36,43 @@ class LockGuardedCacheLoader
      */
     private $delayTimeout;

+    /**
+     * Timeout for information to be collected and saved.
+     * If timeout passed that means that data cannot be saved right now.
+     * And we will just return collected data.
+     *
+     * Value of the variable in milliseconds.
+     *
+     * @var int
+     */
+    private $loadTimeout;
+
+    /**
+     * Minimal delay timeout in ms.
+     *
+     * @var int
+     */
+    private $minimalDelayTimeout;
+
     /**
      * @param LockManagerInterface $locker
      * @param int $lockTimeout
      * @param int $delayTimeout
+     * @param int $loadTimeout
+     * @param int $minimalDelayTimeout
      */
     public function __construct(
         LockManagerInterface $locker,
         int $lockTimeout = 10000,
-        int $delayTimeout = 20
+        int $delayTimeout = 20,
+        int $loadTimeout = 10000,
+        int $minimalDelayTimeout = 5
     ) {
         $this->locker = $locker;
         $this->lockTimeout = $lockTimeout;
         $this->delayTimeout = $delayTimeout;
+        $this->loadTimeout = $loadTimeout;
+        $this->minimalDelayTimeout = $minimalDelayTimeout;
     }

     /**
@@ -67,25 +91,25 @@ class LockGuardedCacheLoader
         callable $dataSaver
     ) {
         $cachedData = $dataLoader(); //optimistic read
-
-        while ($cachedData === false && $this->locker->isLocked($lockName)) {
-            usleep($this->delayTimeout * 1000);
-            $cachedData = $dataLoader();
-        }
+        $deadline = microtime(true) + $this->loadTimeout / 100;

         while ($cachedData === false) {
-            try {
-                if ($this->locker->lock($lockName, $this->lockTimeout / 1000)) {
+            if ($deadline <= microtime(true)) {
+                return $dataCollector();
+            }
+
+            if ($this->locker->lock($lockName, $this->lockTimeout / 1000)) {
+                try {
                     $data = $dataCollector();
                     $dataSaver($data);
                     $cachedData = $data;
+                } finally {
+                    $this->locker->unlock($lockName);
                 }
-            } finally {
-                $this->locker->unlock($lockName);
             }

             if ($cachedData === false) {
-                usleep($this->delayTimeout * 1000);
+                usleep($this->getLookupTimeout() * 1000);
                 $cachedData = $dataLoader();
             }
         }
@@ -103,14 +127,21 @@ class LockGuardedCacheLoader
     public function lockedCleanData(string $lockName, callable $dataCleaner)
     {
         while ($this->locker->isLocked($lockName)) {
-            usleep($this->delayTimeout * 1000);
-        }
-        try {
-            if ($this->locker->lock($lockName, $this->lockTimeout / 1000)) {
-                $dataCleaner();
-            }
-        } finally {
-            $this->locker->unlock($lockName);
+            usleep($this->getLookupTimeout() * 1000);
         }
+
+        $dataCleaner();
+    }
+
+    /**
+     * Delay will be applied as rand($minimalDelayTimeout, $delayTimeout).
+     * This helps to desynchronize multiple clients trying
+     * to acquire the lock for the same resource at the same time
+     *
+     * @return int
+     */
+    private function getLookupTimeout()
+    {
+        return rand($this->minimalDelayTimeout, $this->delayTimeout);
     }
 }
diff -Nuar a/vendor/magento/framework/Interception/Config/Config.php b/vendor/magento/framework/Interception/Config/Config.php
--- a/vendor/magento/framework/Interception/Config/Config.php
+++ b/vendor/magento/framework/Interception/Config/Config.php
@@ -187,8 +187,6 @@ class Config implements \Magento\Framework\Interception\ConfigInterface
      */
     private function initializeUncompiled($classDefinitions = [])
     {
-        $this->cacheManager->clean($this->_cacheId);
-
         $this->generateIntercepted($classDefinitions);
 
         $this->cacheManager->save($this->_cacheId, $this->_intercepted);
diff -Nuar a/vendor/magento/framework/Lock/Backend/Cache.php b/vendor/magento/framework/Lock/Backend/Cache.php
--- a/vendor/magento/framework/Lock/Backend/Cache.php
+++ b/vendor/magento/framework/Lock/Backend/Cache.php
@@ -24,12 +24,20 @@ class Cache implements \Magento\Framework\Lock\LockManagerInterface
      */
     private $cache;

+    /**
+     * Sign for locks, helps to avoid removing a lock that was created by another client
+     *
+     * @string
+     */
+    private $lockSign;
+
     /**
      * @param FrontendInterface $cache
      */
     public function __construct(FrontendInterface $cache)
     {
         $this->cache = $cache;
+        $this->lockSign = $this->generateLockSign();
     }

     /**
@@ -37,7 +45,26 @@ class Cache implements \Magento\Framework\Lock\LockManagerInterface
      */
     public function lock(string $name, int $timeout = -1): bool
     {
-        return $this->cache->save('1', $this->getIdentifier($name), [], $timeout);
+        if (empty($this->lockSign)) {
+            $this->lockSign = $this->generateLockSign();
+        }
+
+        $data = $this->cache->load($this->getIdentifier($name));
+
+        if (false !== $data) {
+             return false;
+        }
+
+        $timeout = $timeout <= 0 ? null : $timeout;
+        $this->cache->save($this->lockSign, $this->getIdentifier($name), [], $timeout);
+
+        $data = $this->cache->load($this->getIdentifier($name));
+
+        if ($data === $this->lockSign) {
+            return true;
+        }
+
+        return false;
     }

     /**
@@ -45,7 +72,22 @@ class Cache implements \Magento\Framework\Lock\LockManagerInterface
      */
     public function unlock(string $name): bool
     {
-        return $this->cache->remove($this->getIdentifier($name));
+        if (empty($this->lockSign)) {
+            return false;
+        }
+
+        $data = $this->cache->load($this->getIdentifier($name));
+
+        if (false === $data) {
+            return false;
+        }
+
+        $removeResult = false;
+        if ($data === $this->lockSign) {
+            $removeResult = (bool)$this->cache->remove($this->getIdentifier($name));
+        }
+
+        return $removeResult;
     }

     /**
@@ -66,4 +108,27 @@ class Cache implements \Magento\Framework\Lock\LockManagerInterface
     {
         return self::LOCK_PREFIX . $cacheIdentifier;
     }
+
+    /**
+     * Function that generates lock sign that helps to avoid removing a lock that was created by another client.
+     *
+     * @return string
+     */
+    private function generateLockSign()
+    {
+        $sign = implode(
+            '-',
+            [
+                \getmypid(), \crc32(\gethostname())
+            ]
+        );
+
+        try {
+            $sign .= '-' . \bin2hex(\random_bytes(4));
+        } catch (\Exception $e) {
+            $sign .= '-' . \uniqid('-uniqid-');
+        }
+
+        return $sign;
+    }
 }
diff -Nuar a/setup/src/Magento/Setup/Console/Command/DiCompileCommand.php b/setup/src/Magento/Setup/Console/Command/DiCompileCommand.php
--- a/setup/src/Magento/Setup/Console/Command/DiCompileCommand.php
+++ b/setup/src/Magento/Setup/Console/Command/DiCompileCommand.php
@@ -260,9 +260,12 @@ class DiCompileCommand extends Command
      */
     private function getExcludedLibraryPaths(array $libraryPaths)
     {
-        $libraryPaths = array_map(function ($libraryPath) {
-            return preg_quote($libraryPath, '#');
-        }, $libraryPaths);
+        $libraryPaths = array_map(
+            function ($libraryPath) {
+                return preg_quote($libraryPath, '#');
+            },
+            $libraryPaths
+        );
 
         $excludedLibraryPaths = [
             '#^(?:' . join('|', $libraryPaths) . ')/([\\w]+/)?Test#',
@@ -395,7 +398,8 @@ class DiCompileCommand extends Command
                 $compiledPathsList['application'],
                 $compiledPathsList['library'],
                 $compiledPathsList['generated_helpers'],
-            ]
+            ],
+            OperationFactory::APPLICATION_ACTION_LIST_GENERATOR => [],
         ];
 
         return $operations;
diff -Nuar a/2.3.5/setup/src/Magento/Setup/Module/Di/App/Task/Operation/AppActionListGenerator.php b/setup/src/Magento/Setup/Module/Di/App/Task/Operation/AppActionListGenerator.php
new file mode 100644
--- /dev/null
+++ b/setup/src/Magento/Setup/Module/Di/App/Task/Operation/AppActionListGenerator.php
@@ -0,0 +1,58 @@
+<?php
+/**
+ * Copyright © Magento, Inc. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Setup\Module\Di\App\Task\Operation;
+
+use Magento\Setup\Module\Di\App\Task\OperationInterface;
+use Magento\Framework\Module\Dir\Reader as ModuleReader;
+use Magento\Framework\App\ObjectManager\ConfigWriterInterface;
+
+/**
+ * Pregenerates actions for Magento
+ */
+class AppActionListGenerator implements OperationInterface
+{
+    /**
+     * @var ModuleReader
+     */
+    private $moduleReader;
+
+    /**
+     * @var \Magento\Framework\App\ObjectManager\ConfigWriterInterface
+     */
+    private $configWriter;
+
+    /**
+     * @param ModuleReader $moduleReader
+     * @param ConfigWriterInterface $configWriter
+     */
+    public function __construct(
+        ModuleReader $moduleReader,
+        ConfigWriterInterface $configWriter
+    ) {
+        $this->moduleReader = $moduleReader;
+        $this->configWriter = $configWriter;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public function doOperation()
+    {
+        $actionList = $this->moduleReader->getActionFiles();
+        $this->configWriter->write(
+            'app_action_list',
+            $actionList
+        );
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public function getName()
+    {
+        return 'App action list generation';
+    }
+}
diff -Nuar a/setup/src/Magento/Setup/Module/Di/App/Task/OperationFactory.php b/setup/src/Magento/Setup/Module/Di/App/Task/OperationFactory.php
--- a/setup/src/Magento/Setup/Module/Di/App/Task/OperationFactory.php
+++ b/setup/src/Magento/Setup/Module/Di/App/Task/OperationFactory.php
@@ -5,6 +5,12 @@
  */
 namespace Magento\Setup\Module\Di\App\Task;
 
+use Magento\Setup\Module\Di\App\Task\Operation\AppActionListGenerator;
+use Magento\Setup\Module\Di\App\Task\Operation\PluginListGenerator;
+
+/**
+ * Factory that creates list of OperationInterface classes
+ */
 class OperationFactory
 {
     /**
@@ -47,6 +53,11 @@ class OperationFactory
      */
     const APPLICATION_CODE_GENERATOR = 'application_code_generator';
 
+    /**
+     * Application action list generator
+     */
+    const APPLICATION_ACTION_LIST_GENERATOR = 'application_action_list_generator';
+
     /**
      * Operations definitions
      *
@@ -61,6 +72,7 @@ class OperationFactory
         self::INTERCEPTION_CACHE => \Magento\Setup\Module\Di\App\Task\Operation\InterceptionCache::class,
         self::REPOSITORY_GENERATOR => \Magento\Setup\Module\Di\App\Task\Operation\RepositoryGenerator::class,
         self::PROXY_GENERATOR => \Magento\Setup\Module\Di\App\Task\Operation\ProxyGenerator::class,
+        self::APPLICATION_ACTION_LIST_GENERATOR => AppActionListGenerator::class,
     ];
 
     /**

diff -Nuar a/vendor/magento/module-catalog/Model/Product.php b/vendor/magento/module-catalog/Model/Product.php
--- a/vendor/magento/module-catalog/Model/Product.php
+++ b/vendor/magento/module-catalog/Model/Product.php
@@ -72,9 +72,9 @@ class Product extends \Magento\Catalog\Model\AbstractModel implements
     const STORE_ID = 'store_id';

     /**
-     * @var string
+     * @var string|bool
      */
-    protected $_cacheTag = self::CACHE_TAG;
+    protected $_cacheTag = false;

     /**
      * @var string
@@ -874,7 +874,6 @@ class Product extends \Magento\Catalog\Model\AbstractModel implements
      */
     public function beforeSave()
     {
-        $this->cleanCache();
         $this->setTypeHasOptions(false);
         $this->setTypeHasRequiredOptions(false);
         $this->setHasOptions(false);
@@ -1164,7 +1163,7 @@ class Product extends \Magento\Catalog\Model\AbstractModel implements
     /**
      * Get formatted by currency product price
      *
-     * @return  array|double
+     * @return array|double
      * @since 102.0.6
      */
     public function getFormattedPrice()
diff -Nuar a/vendor/magento/module-config/App/Config/Type/System.php b/vendor/magento/module-config/App/Config/Type/System.php
--- a/vendor/magento/module-config/App/Config/Type/System.php
+++ b/vendor/magento/module-config/App/Config/Type/System.php
@@ -20,6 +20,8 @@ use Magento\Framework\Serialize\SerializerInterface;
 use Magento\Store\Model\Config\Processor\Fallback;
 use Magento\Framework\Encryption\Encryptor;
 use Magento\Store\Model\ScopeInterface as StoreScope;
+use Magento\Framework\App\Cache\StateInterface;
+use Magento\Framework\App\Cache\Type\Config;

 /**
  * System configuration type
@@ -98,6 +100,12 @@ class System implements ConfigTypeInterface
     private $lockQuery;

     /**
+     * @var StateInterface
+     */
+    private $cacheState;
+
+    /**
+     * System constructor.
      * @param ConfigSourceInterface $source
      * @param PostProcessorInterface $postProcessor
      * @param Fallback $fallback
@@ -110,6 +118,7 @@ class System implements ConfigTypeInterface
      * @param Encryptor|null $encryptor
      * @param LockManagerInterface|null $locker
      * @param LockGuardedCacheLoader|null $lockQuery
+     * @param StateInterface|null $cacheState
      * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      * @SuppressWarnings(PHPMD.ExcessiveParameterList)
      */
@@ -125,7 +134,8 @@ class System implements ConfigTypeInterface
         Reader $reader = null,
         Encryptor $encryptor = null,
         LockManagerInterface $locker = null,
-        LockGuardedCacheLoader $lockQuery = null
+        LockGuardedCacheLoader $lockQuery = null,
+        StateInterface $cacheState = null
     ) {
         $this->postProcessor = $postProcessor;
         $this->cache = $cache;
@@ -136,6 +146,8 @@ class System implements ConfigTypeInterface
             ?: ObjectManager::getInstance()->get(Encryptor::class);
         $this->lockQuery = $lockQuery
             ?: ObjectManager::getInstance()->get(LockGuardedCacheLoader::class);
+        $this->cacheState = $cacheState
+            ?: ObjectManager::getInstance()->get(StateInterface::class);
     }

     /**
@@ -220,6 +232,10 @@ class System implements ConfigTypeInterface
      */
     private function loadAllData()
     {
+        if (!$this->cacheState->isEnabled(Config::TYPE_IDENTIFIER)) {
+            return $this->readData();
+        }
+
         $loadAction = function () {
             $cachedData = $this->cache->load($this->configType);
             $data = false;
@@ -245,6 +261,10 @@ class System implements ConfigTypeInterface
      */
     private function loadDefaultScopeData($scopeType)
     {
+        if (!$this->cacheState->isEnabled(Config::TYPE_IDENTIFIER)) {
+            return $this->readData();
+        }
+
         $loadAction = function () use ($scopeType) {
             $cachedData = $this->cache->load($this->configType . '_' . $scopeType);
             $scopeData = false;
@@ -271,6 +291,10 @@ class System implements ConfigTypeInterface
      */
     private function loadScopeData($scopeType, $scopeId)
     {
+        if (!$this->cacheState->isEnabled(Config::TYPE_IDENTIFIER)) {
+            return $this->readData();
+        }
+
         $loadAction = function () use ($scopeType, $scopeId) {
             $cachedData = $this->cache->load($this->configType . '_' . $scopeType . '_' . $scopeId);
             $scopeData = false;
@@ -393,6 +417,10 @@ class System implements ConfigTypeInterface
             $this->cache->clean(\Zend_Cache::CLEANING_MODE_MATCHING_TAG, [self::CACHE_TAG]);
         };

+        if (!$this->cacheState->isEnabled(Config::TYPE_IDENTIFIER)) {
+            return $cleanAction();
+        }
+
         $this->lockQuery->lockedCleanData(
             self::$lockName,
             $cleanAction
diff -Nuar a/vendor/magento/module-config/etc/di.xml b/vendor/magento/module-config/etc/di.xml
--- a/vendor/magento/module-config/etc/di.xml
+++ b/vendor/magento/module-config/etc/di.xml
@@ -97,8 +97,6 @@
     <virtualType name="systemConfigQueryLocker" type="Magento\Framework\Cache\LockGuardedCacheLoader">
         <arguments>
             <argument name="locker" xsi:type="object">Magento\Framework\Lock\Backend\Cache</argument>
-            <argument name="lockTimeout" xsi:type="number">42000</argument>
-            <argument name="delayTimeout" xsi:type="number">100</argument>
         </arguments>
     </virtualType>

diff -Nuar a/setup/src/Magento/Setup/Model/ConfigOptionsList/Cache.php b/setup/src/Magento/Setup/Model/ConfigOptionsList/Cache.php
--- a/setup/src/Magento/Setup/Model/ConfigOptionsList/Cache.php
+++ b/setup/src/Magento/Setup/Model/ConfigOptionsList/Cache.php
@@ -20,7 +20,7 @@ use Magento\Setup\Validator\RedisConnectionValidator;
 class Cache implements ConfigOptionsListInterface
 {
     const INPUT_VALUE_CACHE_REDIS = 'redis';
-    const CONFIG_VALUE_CACHE_REDIS = 'Cm_Cache_Backend_Redis';
+    const CONFIG_VALUE_CACHE_REDIS = \Magento\Framework\Cache\Backend\Redis::class;

     const INPUT_KEY_CACHE_BACKEND = 'cache-backend';
     const INPUT_KEY_CACHE_BACKEND_REDIS_SERVER = 'cache-backend-redis-server';
@@ -282,6 +282,6 @@ class Cache implements ConfigOptionsListInterface
      */
     private function generateCachePrefix(): string
     {
-        return substr(\md5(dirname(__DIR__, 6)), 0, 3) . '_';
+        return substr(\hash('sha256', dirname(__DIR__, 6)), 0, 3) . '_';
     }
 }
diff -Nuar a/setup/src/Magento/Setup/Model/ConfigOptionsList/PageCache.php b/setup/src/Magento/Setup/Model/ConfigOptionsList/PageCache.php
--- a/setup/src/Magento/Setup/Model/ConfigOptionsList/PageCache.php
+++ b/setup/src/Magento/Setup/Model/ConfigOptionsList/PageCache.php
@@ -20,7 +20,7 @@ use Magento\Setup\Validator\RedisConnectionValidator;
 class PageCache implements ConfigOptionsListInterface
 {
     const INPUT_VALUE_PAGE_CACHE_REDIS = 'redis';
-    const CONFIG_VALUE_PAGE_CACHE_REDIS = 'Cm_Cache_Backend_Redis';
+    const CONFIG_VALUE_PAGE_CACHE_REDIS = \Magento\Framework\Cache\Backend\Redis::class;

     const INPUT_KEY_PAGE_CACHE_BACKEND = 'page-cache';
     const INPUT_KEY_PAGE_CACHE_BACKEND_REDIS_SERVER = 'page-cache-redis-server';
@@ -284,6 +284,6 @@ class PageCache implements ConfigOptionsListInterface
      */
     private function generateCachePrefix(): string
     {
-        return substr(\md5(dirname(__DIR__, 6)), 0, 3) . '_';
+        return substr(\hash('sha256', dirname(__DIR__, 6)), 0, 3) . '_';
     }
 }
