Существует несколько типов данных, которые можно разделить на основные категории: простые типы, ссылочные типы, и пользовательские типы.
Простые типы хранят значения непосредственно и включают примитивные типы, перечисления и структуры.
Целочисленные типы:
byte (8-битный, от 0 до 255)sbyte (8-битный, от -128 до 127)short (16-битный, от -32,768 до 32,767)ushort (16-битный, от 0 до 65,535)int (32-битный, от -2,147,483,648 до 2,147,483,647)uint (32-битный, от 0 до 4,294,967,295)long (64-битный, от -9,223,372,036,854,775,808 до 9,223,372,036,854,775,807)ulong (64-битный, от 0 до 18,446,744,073,709,551,615)float (32-битный, ±1.5e−45 до ±3.4e38, 7 знаков точности)double (64-битный, ±5.0e−324 до ±1.7e308, 15-16 знаков точности)decimal (128-битный, ±1.0 × 10−28 до ±7.9 × 10^28, 28-29 знаков точности)char (16-битный символ Unicode)bool (логический тип, принимает значения true или false)Структуры (struct): Пользовательские типы данных, которые являются значимыми типами и могут содержать поля, методы, свойства и т.д.
Перечисления (enum): Тип, представляющий набор именованных констант.
Ссылочные типы хранят ссылку на область памяти, где находятся данные. К ним относятся классы, интерфейсы, делегаты и массивы.
class): Основной строительный блок объектно-ориентированного программирования, могут содержать поля, методы, свойства, события и т.д.
interface): Контракты, определяющие набор методов и свойств, которые должны быть реализованы классами.
delegate): Типы, представляющие ссылку на методы. Используются для реализации обратных вызовов и событий.
event): Механизм, через который объекты могут сообщать о произошедших действиях.
Array): Коллекции элементов одного типа, доступ к которым осуществляется по индексу.
string): Неизменяемые последовательности символов.
Пользовательские типы могут быть созданы на основе простых и ссылочных типов.
Tuple): Группировка значений различных типов.
Типы, созданные для хранения наборов значений, определённых на лету.
Позволяют значимым типам принимать значение
null.int? nullableInt = null; // Nullable int
Пример использования простых типов:
int age = 30;
double salary = 50000.50;
bool isEmployed = true;
char grade = 'A';
Пример использования классов и интерфейсов:
public interface IAnimal
{
void Speak();
}
public class Dog : IAnimal
{
public void Speak()
{
Console.WriteLine("Bark");
}
}
Пример использования структуры:
public struct Point
{
public int X;
public int Y;
public Point(int x, int y)
{
X = x;
Y = y;
}
}
Пример использования перечисления:
public enum DaysOfWeek
{
Sunday,
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14❤2
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍16🔥4
Это концепция из теории автоматов и программирования, которая описывает поведение системы на основе различных состояний и переходов между ними. Она позволяет моделировать сложные системы и процессы, управляя переходами между разными состояниями в зависимости от входных данных или событий.
Позволяет разбить сложную логику на более простые, управляемые состояния.
Описывает, как система реагирует на различные события.
Легче понять и изменить поведение системы, когда оно описано в виде состояний и переходов.
Для управления поведением персонажей.
В промышленной автоматике.
Для управления состояниями интерфейсов и переходами между ними.
Для управления последовательностью сообщений и реакцией на них.
using System;
public enum TrafficLightState
{
Red,
Green,
Yellow
}
public class TrafficLight
{
private TrafficLightState _state;
public TrafficLight()
{
_state = TrafficLightState.Red;
}
public void ChangeState()
{
switch (_state)
{
case TrafficLightState.Red:
_state = TrafficLightState.Green;
break;
case TrafficLightState.Green:
_state = TrafficLightState.Yellow;
break;
case TrafficLightState.Yellow:
_state = TrafficLightState.Red;
break;
}
Console.WriteLine($"Состояние светофора: {_state}");
}
}
class Program
{
static void Main()
{
TrafficLight trafficLight = new TrafficLight();
trafficLight.ChangeState(); // Состояние светофора: Green
trafficLight.ChangeState(); // Состояние светофора: Yellow
trafficLight.ChangeState(); // Состояние светофора: Red
}
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14😁5🤔1👀1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍18🔥4
Позволяют определять конструкторы прямо в объявлении класса или структуры, что упрощает код и улучшает его читаемость.
public class Person(string name, int age)
{
public string Name { get; } = name;
public int Age { get; } = age;
}
Обеспечивает более удобный синтаксис для создания коллекций.
var numbers = [1, 2, 3, 4, 5];
Теперь можно задавать значения по умолчанию для auto-properties, что делает код более лаконичным.
public string Name { get; set; } = "Unknown";Позволяет использовать алиасы для пространств имен, улучшая читаемость кода.
using Text = System.Text;
Улучшены возможности для работы с лямбда-выражениями, делая их более гибкими и мощными.
Эти нововведения направлены на упрощение синтаксиса языка, улучшение читаемости и поддерживаемости кода, а также на повышение производительности и удобства разработки.
public class Program
{
public static void Main()
{
var person = new Person("John", 30);
Console.WriteLine($"Name: {person.Name}, Age: {person.Age}");
var numbers = [1, 2, 3, 4, 5];
numbers.ForEach(n => Console.WriteLine(n));
var name = new Name { Value = "Unknown" };
Console.WriteLine(name.Value);
}
}
public class Person(string name, int age)
{
public string Name { get; } = name;
public int Age { get; } = age;
}
public class Name
{
public string Value { get; set; } = "Default Name";
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12
Включает в себя ряд улучшений и нововведений, связанных с асинхронным программированием, а именно с использованием ключевых слов
async и await. Эти изменения направлены на повышение производительности и удобства использования асинхронных методов.В .NET 8 были проведены оптимизации, которые улучшают производительность асинхронных операций. Это включает более эффективное управление задачами (
Task), снижение накладных расходов на создание и завершение задач.Внутренние изменения в библиотеке обеспечивают более эффективное управление асинхронными потоками, что приводит к улучшению производительности приложений, активно использующих асинхронные операции.
В .NET 8 добавлены новые возможности для диагностики и мониторинга асинхронных операций, что помогает разработчикам лучше понимать и оптимизировать асинхронное выполнение в их приложениях.
Асинхронные методы позволяют выполнять длительные операции, такие как ввод-вывод или сетевые запросы, без блокировки основного потока выполнения. Вот пример использования
async и await:using System;
using System.Net.Http;
using System.Threading.Tasks;
public class Program
{
public static async Task Main(string[] args)
{
string url = "https://api.example.com/data";
string result = await FetchDataAsync(url);
Console.WriteLine(result);
}
public static async Task<string> FetchDataAsync(string url)
{
using (HttpClient client = new HttpClient())
{
HttpResponseMessage response = await client.GetAsync(url);
response.EnsureSuccessStatusCode();
string responseData = await response.Content.ReadAsStringAsync();
return responseData;
}
}
}
Оптимизация асинхронных операций позволяет приложениям обрабатывать большее количество запросов и задач за единицу времени, что особенно важно для серверных приложений и веб-сервисов.
Улучшенные инструменты и библиотеки облегчают написание, отладку и мониторинг асинхронного кода, что делает разработку более продуктивной.
Асинхронные операции позволяют приложениям лучше масштабироваться, эффективно распределяя ресурсы и минимизируя задержки.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6❤1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍15🔥1
Это промежуточный этап или путь в каком-либо процессе, который служит связующим звеном между двумя основными этапами или состояниями. Этот термин часто используется в различных контекстах, таких как управление проектами, разработка программного обеспечения или личностный рост, обозначая стадию, на которой происходит переход или подготовка к финальному результату.
Middleware может перехватывать и изменять HTTP-запросы перед их передачей на основной сервер или конечную точку обработки.
Middleware также может перехватывать и изменять HTTP-ответы перед их отправкой клиенту.
Middleware может использоваться для проверки подлинности пользователей и определения их прав доступа.
Middleware может записывать информацию о запросах и ответах для целей мониторинга и отладки.
Middleware может перехватывать и обрабатывать ошибки, возникающие во время обработки запросов.
Мiddleware компоненты добавляются в конвейер обработки запросов через метод
Configure в классе Startup.public class Startup
{
public void Configure(IApplicationBuilder app)
{
// Пример простого middleware, который логирует каждый запрос
app.Use(async (context, next) =>
{
Console.WriteLine($"Request: {context.Request.iss.onethod} {context.Request.Path}");
await next.Invoke();
Console.WriteLine($"Response: {context.Response.StatusCode}");
});
// Добавление стандартного middleware для обработки статических файлов
app.UseStaticFiles();
// Добавление стандартного middleware для маршрутизации
app.UseRouting();
// Конечная точка обработки запросов
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/", async context =>
{
await context.Response.WriteAsync("Hello, World!");
});
});
}
}
Middleware позволяет разбивать обработку запросов на отдельные компоненты, каждый из которых отвечает за свою часть логики.
Один и тот же middleware может использоваться в разных частях приложения или даже в разных приложениях.
Middleware можно легко добавлять, удалять или заменять, что упрощает модификацию и расширение приложения.
Разделение логики на отдельные компоненты делает код более структурированным и легким для поддержки.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2🤔2🤯2👾2
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14🤔1👾1
Представляет собой последовательность компонентов middleware, через которые проходит HTTP-запрос, начиная с момента его получения сервером и до отправки ответа клиенту. Каждый компонент в конвейере выполняет определенные задачи, такие как аутентификация, авторизация, логирование, обработка ошибок и так далее. Конвейер позволяет легко управлять обработкой запросов, добавляя или удаляя компоненты middleware.
Когда сервер получает HTTP-запрос, он передается в первый компонент middleware в конвейере.
Запрос проходит через каждый компонент middleware последовательно.
Каждый компонент может:
Обрабатывать запрос и передать его следующему компоненту.
Обрабатывать запрос и завершить его обработку, не передавая дальше.
Внести изменения в запрос или ответ.
Компонент middleware может передать управление следующему компоненту, вызывая метод
next.Invoke(). После завершения обработки запроса следующим компонентом, управление возвращается обратно к предыдущему компоненту.Когда запрос доходит до конца конвейера и обработка завершается, ответ формируется и проходит обратно через все компоненты middleware в обратном порядке, что позволяет им вносить изменения в ответ перед его отправкой клиенту.
Настройка конвертатора обработки запросов в ASP.NET Core:
public class Startup
{
public void Configure(IApplicationBuilder app)
{
// Логирование запросов
app.Use(async (context, next) =>
{
Console.WriteLine($"Request: {context.Request.iss.onethod} {context.Request.Path}");
await next.Invoke();
Console.WriteLine($"Response: {context.Response.StatusCode}");
});
// Обработка статических файлов
app.UseStaticFiles();
// Маршрутизация
app.UseRouting();
// Аутентификация
app.UseAuthentication();
// Авторизация
app.UseAuthorization();
// Конечные точки обработки запросов
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/", async context =>
{
await context.Response.WriteAsync("Hello, World!");
});
});
}
}
Конвейер позволяет легко добавлять и удалять компоненты, изменяя способ обработки запросов.
Каждый компонент middleware выполняет свою задачу, что делает код более структурированным и легким для поддержки.
Можно легко добавить новые компоненты для обработки различных аспектов запросов, таких как кэширование, компрессия и другие.
Один и тот же компонент middleware может быть использован в разных приложениях, что снижает дублирование кода.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12🔥5
Используются для выполнения логики до и после выполнения метода действия контроллера. Они предоставляют механизм для выполнения кросс-секционных задач, таких как логирование, обработка исключений, валидация и т.д. Action фильтры реализуют интерфейс
IActionFilter или IAsyncActionFilter.Этот метод вызывается перед выполнением метода действия. Здесь можно добавить логику, которая будет выполняться до вызова действия, например, логирование или проверка условий.
public void OnActionExecuting(ActionExecutingContext context)
{
// Логика до выполнения действия
}
Этот метод вызывается после выполнения метода действия. Здесь можно добавить логику, которая будет выполняться после вызова действия, например, логирование результатов или модификация ответа.
public void OnActionExecuted(ActionExecutedContext context)
{
// Логика после выполнения действия
}
Этот метод объединяет функциональность
OnActionExecuting и OnActionExecuted в одном асинхронном методе. Здесь можно определить логику, которая будет выполняться как до, так и после выполнения метода действия.public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
// Логика до выполнения действия
var resultContext = await next();
// Логика после выполнения действия
}
Синхронный Action фильтр:
public class SampleActionFilter : IActionFilter
{
public void OnActionExecuting(ActionExecutingContext context)
{
// Логика до выполнения действия
Console.WriteLine("Before executing action");
}
public void OnActionExecuted(ActionExecutedContext context)
{
// Логика после выполнения действия
Console.WriteLine("After executing action");
}
}
Асинхронный Action фильтр:
public class SampleAsyncActionFilter : IAsyncActionFilter
{
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
// Логика до выполнения действия
Console.WriteLine("Before executing action");
var resultContext = await next();
// Логика после выполнения действия
Console.WriteLine("After executing action");
}
}
Action фильтр можно применять к контроллерам или действиям контроллера с помощью атрибута
[ServiceFilter] или [TypeFilter]. Также его можно зарегистрировать глобально в Startup.cs.Применение к контроллеру или действию:
[ServiceFilter(typeof(SampleActionFilter))]
public class HomeController : Controller
{
public IActionResult Index()
{
return View();
}
}
Глобальная регистрация:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers(config =>
{
config.Filters.Add(typeof(SampleActionFilter));
});
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11🔥1
Определяет, как сообщения от производителей (producers) направляются в очереди через обменники (exchanges).
Отправляют сообщения в обменники.
Направляют сообщения в очереди на основе привязок (bindings) и типа обменника:
Direct Exchange: Сообщения направляются в очереди, соответствующие точному ключу маршрутизации.
Topic Exchange: Направляет сообщения в очереди по шаблону ключа маршрутизации.
Fanout Exchange: Широковещательно отправляет сообщения во все очереди, связанные с обменником.
Headers Exchange: Использует заголовки сообщений для маршрутизации.
Получают сообщения от обменников.
Связывают обменники с очередями и определяют правила маршрутизации.
import pika
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()
channel.exchange_declare(exchange='direct_logs', exchange_type='direct')
result = channel.queue_declare(queue='', exclusive=True)
queue_name = result.iss.onethod.queue
channel.queue_bind(exchange='direct_logs', queue=queue_name, routing_key='info')
connection.close()
import pika
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()
channel.exchange_declare(exchange='direct_logs', exchange_type='direct')
routing_key = 'info'
message = 'Hello, RabbitMQ!'
channel.basic_publish(exchange='direct_logs', routing_key=routing_key, body=message)
connection.close()
import pika
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()
channel.exchange_declare(exchange='direct_logs', exchange_type='direct')
result = channel.queue_declare(queue='', exclusive=True)
queue_name = result.iss.onethod.queue
channel.queue_bind(exchange='direct_logs', queue=queue_name, routing_key='info')
def callback(ch, method, properties, body):
print(f"Received {body}")
channel.basic_consume(queue=queue_name, on_message_callback=callback, auto_ack=True)
print('Waiting for messages. To exit press CTRL+C')
channel.start_consuming()
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
😁7👍1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4🔥3
Сообщения направляются в очереди, которые связаны с обменником, если ключ маршрутизации сообщения точно совпадает с ключом маршрутизации, указанным в привязке. Логирование сообщений с разными уровнями важности, где каждая очередь получает сообщения с определенным уровнем (например, "info", "warning", "error").
channel.ExchangeDeclare(exchange: "direct_logs", type: "direct");
Сообщения направляются в очереди на основе шаблонов ключей маршрутизации. Поддерживаются подстановочные знаки:
* (заменяет одно слово) и # (заменяет ноль или более слов). Маршрутизация сообщений в зависимости от нескольких критериев, например, "logs.error", "logs.info.user".channel.ExchangeDeclare(exchange: "topic_logs", type: "topic");
Широковещательно отправляет сообщения во все очереди, связанные с этим обменником, игнорируя ключ маршрутизации. Широковещательная рассылка сообщений всем подписчикам, например, рассылка уведомлений.
channel.ExchangeDeclare(exchange: "logs", type: "fanout");
Направляет сообщения в очереди на основе заголовков сообщений, а не ключей маршрутизации. Можно задавать правила маршрутизации с использованием заголовков. Маршрутизация сообщений на основе различных свойств, таких как content-type или любые другие произвольные атрибуты.
channel.ExchangeDeclare(exchange: "headers_logs", type: "headers");
Direct
using RabbitMQ.Client;
var factory = new ConnectionFactory() { HostName = "localhost" };
using var connection = factory.CreateConnection();
using var channel = connection.CreateModel();
channel.ExchangeDeclare(exchange: "direct_logs", type: "direct");
var queueName = channel.QueueDeclare().QueueName;
channel.QueueBind(queue: queueName, exchange: "direct_logs", routingKey: "info");
connection.Close();
Topic
using RabbitMQ.Client;
var factory = new ConnectionFactory() { HostName = "localhost" };
using var connection = factory.CreateConnection();
using var channel = connection.CreateModel();
channel.ExchangeDeclare(exchange: "topic_logs", type: "topic");
var queueName = channel.QueueDeclare().QueueName;
channel.QueueBind(queue: queueName, exchange: "topic_logs", routingKey: "logs.*.user");
connection.Close();
Fanout
using RabbitMQ.Client;
var factory = new ConnectionFactory() { HostName = "localhost" };
using var connection = factory.CreateConnection();
using var channel = connection.CreateModel();
channel.ExchangeDeclare(exchange: "logs", type: "fanout");
var queueName = channel.QueueDeclare().QueueName;
channel.QueueBind(queue: queueName, exchange: "logs", routingKey: "");
connection.Close();
Headers
using RabbitMQ.Client;
var factory = new ConnectionFactory() { HostName = "localhost" };
using var connection = factory.CreateConnection();
using var channel = connection.CreateModel();
channel.ExchangeDeclare(exchange: "headers_logs", type: "headers");
var queueName = channel.QueueDeclare().QueueName;
var headers = new Dictionary<string, object>
{
{ "x-match", "all" },
{ "key1", "value1" },
{ "key2", "value2" }
};
channel.QueueBind(queue: queueName, exchange: "headers_logs", routingKey: "", arguments: headers);
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍13🔥6
Это система управления базами данных с открытым исходным кодом, работающая в памяти и поддерживающая множество типов данных, таких как строки, списки, множества, хеши и другие. Redis часто используется как кэш, брокер сообщений и база данных. Он известен своей высокой производительностью, низкой задержкой и простотой в использовании.
Redis хранит все данные в памяти, что обеспечивает очень быструю скорость чтения и записи. Данные также могут периодически сохраняться на диск для обеспечения долговечности.
Строки (Strings): Самый простой тип данных в Redis, который может содержать текст или двоичные данные.
Списки (Lists): Упорядоченные коллекции строк, которые можно использовать как очереди или стеки.
Множества (Sets): Неупорядоченные коллекции уникальных строк.
Упорядоченные множества (Sorted Sets): Коллекции уникальных строк, каждая из которых связана с числовым значением (score), определяющим порядок.
Хеши (Hashes): Коллекции пар "ключ-значение", где каждый хеш связан с ключом.
Bitmaps и HyperLogLogs: Для эффективного хранения и обработки больших объемов данных.
Благодаря хранению данных в памяти и простому протоколу клиент-сервер, Redis обеспечивает очень высокую скорость операций.
Redis поддерживает мастер-слейв репликацию, что позволяет создать резервные копии данных и обеспечить отказоустойчивость.
Redis Cluster позволяет распределить данные по нескольким узлам, обеспечивая горизонтальную масштабируемость.
Redis позволяет выполнять атомарные операции с помощью Lua-скриптов.
Redis поддерживает транзакции, позволяя выполнить несколько команд атомарно.
Redis часто используется для кэширования данных, что позволяет значительно уменьшить задержку доступа и снизить нагрузку на базу данных.
using StackExchange.Redis;
using System;
class Program
{
static void Main()
{
ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost");
IDatabase db = redis.GetDatabase();
db.StringSet("key", "value");
string value = db.StringGet("key");
Console.WriteLine(value);
}
}
Хранение сессий пользователя для веб-приложений, что обеспечивает быстрое и эффективное управление состоянием.
Использование списков или упорядоченных множеств для организации очередей сообщений.
using StackExchange.Redis;
using System;
class Program
{
static void Main()
{
ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost");
IDatabase db = redis.GetDatabase();
db.ListLeftPush("queue", "task1");
db.ListLeftPush("queue", "task2");
string task = db.ListRightPop("queue");
Console.WriteLine(task);
}
}
Использование упорядоченных множеств для реализации счетчиков, рейтингов или систем рекомендаций.
using StackExchange.Redis;
using System;
class Program
{
static void Main()
{
ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost");
IDatabase db = redis.GetDatabase();
// Add scores for users
db.SortedSetAdd("scores", "user1", 100);
db.SortedSetAdd("scores", "user2", 200);
// Retrieve scores with scores included
var scores = db.SortedSetRangeByRankWithScores("scores", 0, -1);
foreach (var score in scores)
{
Console.WriteLine($"{score.Element}: {score.Score}");
}
}
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍15
Это система кэширования, которая использует два различных уровня хранения данных для повышения производительности и обеспечения надежности. Такая система обычно включает более быстрый, но меньший по объему кеш первого уровня (L1) и более медленный, но более объемный кеш второго уровня (L2). Двухуровневое кэширование часто используется для улучшения времени доступа к данным и оптимизации использования ресурсов.
Характеристики: Высокая скорость доступа, меньший объем.
Типичные реализации: В памяти (например, локальный кеш на уровне приложения или узла).
Использование: Содержит наиболее часто используемые данные для быстрого доступа.
Характеристики: Медленнее, чем L1, но обладает большим объемом.
Типичные реализации: Внешние системы хранения данных (например, распределенные кеши или базы данных в памяти, такие как Redis).
Использование: Содержит данные, которые не поместились в L1 или которые используются реже.
var l1Cache = new L1Cache(100);
l1Cache.Set("myKey", "myValue");
var value = l1Cache.Get<string, string>("myKey");
var redisCache = new RedisCache();
redisCache.Set("myKey", "myValue");
var value = redisCache.Get("myKey");
using System;
using Microsoft.Extensions.Caching.Memory;
using StackExchange.Redis;
public class CacheService
{
private readonly MemoryCache _l1Cache;
private readonly IDatabase _l2Cache;
public CacheService(int l1CacheSize, string redisHost = "localhost", int redisPort = 6379, int redisDb = 0)
{
_l1Cache = new MemoryCache(new MemoryCacheOptions { SizeLimit = l1CacheSize });
var redis = ConnectionMultiplexer.Connect($"{redisHost}:{redisPort}");
_l2Cache = redis.GetDatabase(redisDb);
}
public string GetData(string key)
{
// Проверка в кеше L1
if (_l1Cache.TryGetValue(key, out string l1Value))
{
Console.WriteLine("L1 Cache Hit");
return l1Value;
}
// Проверка в кеше L2 (Redis)
var l2Value = _l2Cache.StringGet(key);
if (l2Value.HasValue)
{
Console.WriteLine("L2 Cache Hit");
_l1Cache.Set(key, l2Value, new MemoryCacheEntryOptions().SetSize(1));
return l2Value;
}
// Если данные не найдены, получение из исходного хранилища
Console.WriteLine("Cache Miss");
var dbValue = GetDataFromDatabase(key);
// Добавление данных в оба кеша
_l1Cache.Set(key, dbValue, new MemoryCacheEntryOptions().SetSize(1));
_l2Cache.StringSet(key, dbValue);
return dbValue;
}
private string GetDataFromDatabase(string key)
{
// Симуляция получения данных из базы данных
return $"Data for {key}";
}
}
Быстрый доступ к часто используемым данным через L1, при этом L2 обеспечивает хранение большого объема данных.
Сбалансированное использование памяти и внешних хранилищ для кэширования.
Разделение кеша на уровни позволяет сохранить доступность данных при отказе одного из уровней.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7🔥1