Redis 의 List 형식 을 자세히 설명 합 니 다.
Redis List 의 실현 은 양 방향 링크 입 니 다.즉,역방향 검색 과 옮 겨 다 니 는 것 을 지원 하고 조작 하기에 더욱 편리 합 니 다.그러나 일부 추가 메모리 비용 을 가 져 왔 습 니 다.Redis 내부 의 많은 실현 은 발송 버퍼 대기 열 등 도 모두 이 데이터 구 조 를 사용 합 니 다.
List 유형 은 주로 대기 열 과 스 택,먼저 나 가 고 나중에 먼저 나 가 는 데 사 용 됩 니 다.
저장 형식:key--LinkList
먼저 레 디 스에 서 List 형식 과 관련 된 API 를 보 여 드 리 겠 습 니 다.
using System;
using System.Collections.Generic;
using ServiceStack.Redis;
namespace TianYa.Redis.Service
{
/// <summary>
/// Redis List , , , ,
/// Redis , 。
/// </summary>
public class RedisListService : RedisBase
{
#region Queue ( )
/// <summary>
///
/// </summary>
/// <param name="listId"> Id</param>
/// <param name="value"> </param>
public void EnqueueItemOnList(string listId, string value)
{
base._redisClient.EnqueueItemOnList(listId, value);
}
/// <summary>
///
/// </summary>
/// <param name="listId"> Id</param>
/// <returns> </returns>
public string DequeueItemFromList(string listId)
{
return base._redisClient.DequeueItemFromList(listId);
}
/// <summary>
/// ( )
/// </summary>
/// <param name="listId"> Id</param>
/// <param name="timeOut"> ( )</param>
/// <returns> </returns>
public string BlockingDequeueItemFromList(string listId, TimeSpan? timeOut)
{
return base._redisClient.BlockingDequeueItemFromList(listId, timeOut);
}
/// <summary>
/// list ( )
/// </summary>
/// <param name="listIds"> Id</param>
/// <param name="timeOut"> ( )</param>
/// <returns> listId & Item</returns>
public ItemRef BlockingDequeueItemFromLists(string[] listIds, TimeSpan? timeOut)
{
return base._redisClient.BlockingDequeueItemFromLists(listIds, timeOut);
}
#endregion Queue ( )
#region Stack ( )
/// <summary>
///
/// </summary>
/// <param name="listId"> Id</param>
/// <param name="value"> </param>
public void PushItemToList(string listId, string value)
{
base._redisClient.PushItemToList(listId, value);
}
/// <summary>
/// ,
/// </summary>
/// <param name="listId"> Id</param>
/// <param name="value"> </param>
/// <param name="expireAt"> </param>
public void PushItemToList(string listId, string value, DateTime expireAt)
{
base._redisClient.PushItemToList(listId, value);
base._redisClient.ExpireEntryAt(listId, expireAt);
}
/// <summary>
/// ,
/// </summary>
/// <param name="listId"> Id</param>
/// <param name="value"> </param>
/// <param name="expireIn"> </param>
public void PushItemToList(string listId, string value, TimeSpan expireIn)
{
base._redisClient.PushItemToList(listId, value);
base._redisClient.ExpireEntryIn(listId, expireIn);
}
/// <summary>
///
/// </summary>
/// <param name="listId"> Id</param>
/// <returns> </returns>
public string PopItemFromList(string listId)
{
return base._redisClient.PopItemFromList(listId);
}
/// <summary>
/// ( )
/// </summary>
/// <param name="listId"> Id</param>
/// <param name="timeOut"> ( )</param>
/// <returns> </returns>
public string BlockingPopItemFromList(string listId, TimeSpan? timeOut)
{
return base._redisClient.BlockingPopItemFromList(listId, timeOut);
}
/// <summary>
/// list ( )
/// </summary>
/// <param name="listIds"> Id</param>
/// <param name="timeOut"> ( )</param>
/// <returns> listId & Item</returns>
public ItemRef BlockingPopItemFromLists(string[] listIds, TimeSpan? timeOut)
{
return base._redisClient.BlockingPopItemFromLists(listIds, timeOut);
}
/// <summary>
/// fromListId toListId
/// </summary>
/// <param name="fromListId"> Id</param>
/// <param name="toListId"> Id</param>
/// <returns> </returns>
public string PopAndPushItemBetweenLists(string fromListId, string toListId)
{
return base._redisClient.PopAndPushItemBetweenLists(fromListId, toListId);
}
/// <summary>
/// fromListId toListId ( )
/// </summary>
/// <param name="fromListId"> Id</param>
/// <param name="toListId"> Id</param>
/// <param name="timeOut"> ( )</param>
/// <returns> </returns>
public string BlockingPopAndPushItemBetweenLists(string fromListId, string toListId, TimeSpan? timeOut)
{
return base._redisClient.BlockingPopAndPushItemBetweenLists(fromListId, toListId, timeOut);
}
#endregion Stack ( )
#region
/// <summary>
/// list value
/// </summary>
public void PrependItemToList(string listId, string value)
{
base._redisClient.PrependItemToList(listId, value);
}
/// <summary>
/// list value ,
/// </summary>
public void PrependItemToList(string listId, string value, DateTime expireAt)
{
base._redisClient.PrependItemToList(listId, value);
base._redisClient.ExpireEntryAt(listId, expireAt);
}
/// <summary>
/// list value ,
/// </summary>
public void PrependItemToList(string listId, string value, TimeSpan expireIn)
{
base._redisClient.PrependItemToList(listId, value);
base._redisClient.ExpireEntryIn(listId, expireIn);
}
/// <summary>
/// list value
/// </summary>
public void AddItemToList(string listId, string value)
{
base._redisClient.AddItemToList(listId, value);
}
/// <summary>
/// list value ,
/// </summary>
public void AddItemToList(string listId, string value, DateTime expireAt)
{
base._redisClient.AddItemToList(listId, value);
base._redisClient.ExpireEntryAt(listId, expireAt);
}
/// <summary>
/// list value ,
/// </summary>
public void AddItemToList(string listId, string value, TimeSpan expireIn)
{
base._redisClient.AddItemToList(listId, value);
base._redisClient.ExpireEntryIn(listId, expireIn);
}
/// <summary>
/// list value
/// </summary>
public void AddRangeToList(string listId, List<string> values)
{
base._redisClient.AddRangeToList(listId, values);
}
/// <summary>
/// list value ,
/// </summary>
public void AddRangeToList(string listId, List<string> values, DateTime expireAt)
{
base._redisClient.AddRangeToList(listId, values);
base._redisClient.ExpireEntryAt(listId, expireAt);
}
/// <summary>
/// list value ,
/// </summary>
public void AddRangeToList(string listId, List<string> values, TimeSpan expireIn)
{
base._redisClient.AddRangeToList(listId, values);
base._redisClient.ExpireEntryIn(listId, expireIn);
}
#endregion
#region
/// <summary>
/// list
/// </summary>
public long GetListCount(string listId)
{
return base._redisClient.GetListCount(listId);
}
/// <summary>
/// list
/// </summary>
public List<string> GetAllItemsFromList(string listId)
{
return base._redisClient.GetAllItemsFromList(listId);
}
/// <summary>
/// list startingFrom endingAt
/// </summary>
public List<string> GetRangeFromList(string listId, int startingFrom, int endingAt)
{
return base._redisClient.GetRangeFromList(listId, startingFrom, endingAt);
}
#endregion
#region
/// <summary>
/// list ,listId/value, ,
/// </summary>
public long RemoveItemFromList(string listId, string value)
{
return base._redisClient.RemoveItemFromList(listId, value);
}
/// <summary>
/// list ,
/// </summary>
public string RemoveEndFromList(string listId)
{
return base._redisClient.RemoveEndFromList(listId);
}
/// <summary>
/// list ,
/// </summary>
public string RemoveStartFromList(string listId)
{
return base._redisClient.RemoveStartFromList(listId);
}
#endregion
#region
/// <summary>
/// , list
/// </summary>
/// <param name="listId"> Id</param>
/// <param name="keepStartingFrom"> </param>
/// <param name="keepEndingAt"> </param>
public void TrimList(string listId, int keepStartingFrom, int keepEndingAt)
{
base._redisClient.TrimList(listId, keepStartingFrom, keepEndingAt);
}
#endregion
#region
/// <summary>
///
/// </summary>
/// <param name="channel"> </param>
/// <param name="message"> </param>
public void Publish(string channel, string message)
{
base._redisClient.PublishMessage(channel, message);
}
/// <summary>
///
/// </summary>
/// <param name="channel"> </param>
/// <param name="actionOnMessage"></param>
public void Subscribe(string channel, Action<string, string, IRedisSubscription> actionOnMessage)
{
var subscription = base._redisClient.CreateSubscription();
subscription.OnSubscribe = c =>
{
Console.WriteLine($" {c}");
Console.WriteLine();
};
//
subscription.OnUnSubscribe = c =>
{
Console.WriteLine($" {c}");
Console.WriteLine();
};
subscription.OnMessage += (c, s) =>
{
actionOnMessage(c, s, subscription);
};
Console.WriteLine($" {channel}");
subscription.SubscribeToChannels(channel); //blocking
}
/// <summary>
///
/// </summary>
/// <param name="channel"> </param>
public void UnSubscribeFromChannels(string channel)
{
var subscription = base._redisClient.CreateSubscription();
subscription.UnSubscribeFromChannels(channel);
}
#endregion
}
}
아래 와 같이 사용:
/// <summary>
/// Redis List , , , ,
/// Redis , 。
/// / / /
/// </summary>
public static void ShowList()
{
using (RedisListService service = new RedisListService())
{
service.FlushAll();
service.AddItemToList("article", " ");
service.AddItemToList("article", " ");
service.AddItemToList("article", " ");
service.PrependItemToList("article", " ");
service.PrependItemToList("article", " ");
var result1 = service.GetAllItemsFromList("article"); //
var result2 = service.GetRangeFromList("article", 0, 3); // ,
Console.WriteLine($"result1={JsonConvert.SerializeObject(result1)}");
Console.WriteLine($"result2={JsonConvert.SerializeObject(result2)}");
Console.WriteLine("=====================================================");
// :
service.FlushAll();
service.PushItemToList("article", " "); //
service.PushItemToList("article", " ");
service.PushItemToList("article", " ");
service.PushItemToList("article", " ");
service.PushItemToList("article", " ");
for (int i = 0; i < 5; i++)
{
Console.WriteLine(service.PopItemFromList("article")); //
}
Console.WriteLine("=====================================================");
// : ,
//MSMQ---RabbitMQ---ZeroMQ---RedisList 、
service.FlushAll();
service.EnqueueItemOnList("article", " "); //
service.EnqueueItemOnList("article", " ");
service.EnqueueItemOnList("article", " ");
service.EnqueueItemOnList("article", " ");
service.EnqueueItemOnList("article", " ");
for (int i = 0; i < 5; i++)
{
Console.WriteLine(service.DequeueItemFromList("article")); //
}
// , , , ,
}
}
실행 결 과 는 다음 과 같다.다음은 위의 API 를 어떻게 사용 하여 구체 적 인 문 제 를 해결 하 는 지 살 펴 보 겠 습 니 다.
1.블 로그 데이터 페이지
응용 필드:
블 로그 사이트 에 매일 새로 추 가 된 수필 과 글 은 수천 만 원 일 수 있 으 며,표 에는 수천 만 원 의 데이터 가 들 어 있다.첫 페이지 에 서 는 최신 수필 을 보 여 주 려 고 하고,20 페이지 전에는 많은 사람들 이 방문 했다.
이런 상황 에서 첫 페이지 의 페이지 데이터 가 매번 데이터 베 이 스 를 조회 하면 매우 큰 성능 문제 가 생 길 수 있다.
해결 방안:
데이터베이스 에 쓸 때마다 ID제목 은 Redis 의 List 에 기록 합 니 다.
이렇게 되면 사용자 가 페이지 를 칠 할 때마다 데이터 베 이 스 를 방문 하지 않 고 Redis 의 데 이 터 를 직접 읽 을 수 있 습 니 다.
첫 페이지(물론 앞의 몇 페이지 일 수도 있 습 니 다)는 총 기록 수 를 나타 내지 않 고 최신 데이터 로 만 보 여 줌 으로 써 데이터 베 이 스 를 방문 하 는 것 을 피 할 수 있 습 니 다.
또 하 나 는 수평 분 표 입 니 다.데이터 가 Redis 에 저 장 될 때 ID 를 저장 할 수 있 습 니 다.표 이름표제
List 를 사용 하 는 것 은 주로 데이터 양 이 많 고 변화 가 빠 른 데이터 페이지 문 제 를 해결 하 는 것 이다.
28 원칙:80%의 방문 은 20%의 데이터 에 집중 되 고 List 에 서 는 대략적인 양 만 저장 하면 충분 합 니 다.
using TianYa.Redis.Service;
namespace MyRedis.Scene
{
/// <summary>
///
///
/// :
/// , 。 , 20 。
/// , 。
///
/// :
/// , ID_ Redis List ( TrimList, 200 )。
/// , Redis 。
/// ( ) , , 。
///
/// , Redis ID_ _
///
/// List , 。
/// :80% 20% ,List 。
/// </summary>
public class BlogPageList
{
public static void Show()
{
using (RedisListService service = new RedisListService())
{
service.AddItemToList("newBlog", "10001_IOC ");
service.AddItemToList("newBlog", "10002_AOP ");
service.AddItemToList("newBlog", "10003_ ");
service.AddItemToList("newBlog", "10004_ ");
service.AddItemToList("newBlog", "10005_ ");
service.AddItemToList("newBlog", "10006_GC ");
service.TrimList("newBlog", 0, 200); // 201 ( List 2 32 -1 )
var result1 = service.GetRangeFromList("newBlog", 0, 9); //
var result2 = service.GetRangeFromList("newBlog", 10, 19); //
var result3 = service.GetRangeFromList("newBlog", 20, 29); //
}
}
}
}
2.생산자 소비자 모델분산 캐 시,다 중 서버 에 접근 할 수 있 습 니 다.여러 생산자,여러 소비자,모든 제품 은 한 번 만 소 비 됩 니 다.(대기 열 사용)
그 중 하나(또는 여러 개)프로그램 이 기록 되 고,다른 하나(또는 여러 개)프로그램 이 소 비 를 읽 습 니 다.시간 순 으로 데이터 가 실 패 했 으 니 다음 에 다시 시도 할 수 있 습 니 다.
다음은 예 를 들 어 보 겠 습 니 다.
데모 에는 생산자 와 소비 자 를 모 의 하 는 콘 솔 프로그램 2 개가 추가 되 었 습 니 다.
using System;
using TianYa.Redis.Service;
namespace TianYa.Producer
{
/// <summary>
///
/// </summary>
class Program
{
static void Main(string[] args)
{
Console.WriteLine(" 。。。");
using (RedisListService service = new RedisListService())
{
Console.WriteLine(" test ");
for (int i = 1; i <= 20; i++)
{
service.EnqueueItemOnList("test", $" test{i}");
}
Console.WriteLine(" task ");
for (int i = 1; i <= 20; i++)
{
service.EnqueueItemOnList("task", $" task{i}");
}
Console.WriteLine(" ");
while (true)
{
Console.WriteLine("************ ************");
string testTask = Console.ReadLine();
service.EnqueueItemOnList("test", testTask);
}
}
}
}
}
using System;
using System.Threading;
using TianYa.Redis.Service;
namespace TianYa.Consumer
{
/// <summary>
///
/// </summary>
class Program
{
static void Main(string[] args)
{
Console.WriteLine(" 。。。");
using (RedisListService service = new RedisListService())
{
while (true)
{
var result = service.BlockingDequeueItemFromLists(new string[] { "test", "task" }, TimeSpan.FromHours(1));
Thread.Sleep(100);
Console.WriteLine($" {result.Id} {result.Item}");
}
}
}
}
}
다음은.NET Core CLI 를 사용 하여 2 개의 소비자 인 스 턴 스 와 1 개의 생산자 인 스 턴 스 를 시작 합 니 다.운영 결 과 는 다음 과 같 습 니 다.이런 비동기 행렬 은 프로젝트 에서 어떤 가치 가 있 습 니까?
PS:이 사 무 는 매우 큰 문제 입 니 다.실제 항목 에 서 는 실제 상황 에 따라 비동기 대기 열 을 사용 할 지 여 부 를 결정 해 야 합 니 다.
3.구독 발표
게시 구독:
데 이 터 를 발표 하면 모든 구독 자 들 이 받 을 수 있 습 니 다.
관찰자,하나의 데이터 소스,여러 수신 자 는 구독 만 하면 받 을 수 있 고 여러 데이터 소스 에 의 해 공유 할 수 있 습 니 다.
관찰자 모드:위 챗 구독 번호-단체 채 팅-데이터 동기 화...
다음은 작은 데 모 를 살 펴 보 겠 습 니 다.
/// <summary>
///
/// , 。
/// , , , , 。
/// : --- --- 。。。
/// </summary>
public static void ShowPublishAndSubscribe()
{
Task.Run(() =>
{
using (RedisListService service = new RedisListService())
{
service.Subscribe("TianYa", (c, message, iRedisSubscription) =>
{
Console.WriteLine($" {1}{c}:{message},Dosomething else");
if (message.Equals("exit"))
iRedisSubscription.UnSubscribeFromChannels("TianYa");
});//blocking
}
});
Task.Run(() =>
{
using (RedisListService service = new RedisListService())
{
service.Subscribe("TianYa", (c, message, iRedisSubscription) =>
{
Console.WriteLine($" {2}{c}:{message},Dosomething else");
if (message.Equals("exit"))
iRedisSubscription.UnSubscribeFromChannels("TianYa");
});//blocking
}
});
Task.Run(() =>
{
using (RedisListService service = new RedisListService())
{
service.Subscribe("Twelve", (c, message, iRedisSubscription) =>
{
Console.WriteLine($" {3}{c}:{message},Dosomething else");
if (message.Equals("exit"))
iRedisSubscription.UnSubscribeFromChannels("Twelve");
});//blocking
}
});
using (RedisListService service = new RedisListService())
{
Thread.Sleep(1000);
service.Publish("TianYa", "TianYa1");
Thread.Sleep(1000);
service.Publish("TianYa", "TianYa2");
Thread.Sleep(1000);
service.Publish("TianYa", "TianYa3");
Thread.Sleep(1000);
service.Publish("Twelve", "Twelve1");
Thread.Sleep(1000);
service.Publish("Twelve", "Twelve2");
Thread.Sleep(1000);
service.Publish("Twelve", "Twelve3");
Thread.Sleep(1000);
Console.WriteLine("**********************************************");
Thread.Sleep(1000);
service.Publish("TianYa", "exit");
Thread.Sleep(1000);
service.Publish("TianYa", "TianYa6");
Thread.Sleep(1000);
service.Publish("TianYa", "TianYa7");
Thread.Sleep(1000);
service.Publish("TianYa", "TianYa8");
Thread.Sleep(1000);
service.Publish("Twelve", "exit");
Thread.Sleep(1000);
service.Publish("Twelve", "Twelve6");
Thread.Sleep(1000);
service.Publish("Twelve", "Twelve7");
Thread.Sleep(1000);
service.Publish("Twelve", "Twelve8");
Thread.Sleep(1000);
Console.WriteLine(" ");
}
}
실행 결 과 는 다음 과 같다.이로써 본 고 는 모두 소개 되 었 습 니 다.당신 에 게 깨 우 침 이 있다 고 생각 되면 좋아요 를 눌 러 주세요!!
데모 소스 코드:
링크:https://pan.baidu.com/s/1_kEMCtbf2iT5pLV7irxR5Q추출 코드:v4sr
이 글 은 블 로 거들 이 심혈 을 기울 여 작성 하여 옮 겨 실 었 습 니 다.이 원문 링크 를 유지 하 십시오.https://www.cnblogs.com/xyh9039/p/14022264.html
레 디 스 의 List 유형 에 대한 상세 한 설명 은 여기까지 입 니 다.더 많은 레 디 스 List 유형 에 관 한 내용 은 예전 의 글 을 검색 하거나 아래 의 관련 글 을 계속 찾 아 보 세 요.앞으로 많은 응원 부 탁 드 리 겠 습 니 다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
그래프 구조를 무상으로 취급할 수 없는 것은 싫기 때문에, redisgraph를 WSL2에 극치고 설치해 보았습니다.제목은 만우절이므로. 그렇다, 역시, 앞으로는 그래프 구조 데이터베이스라고 생각했다. 생각한 것은 몇 년 전인가. 전부터 Neo4j는 시험하고 있지만, 영업 분들로부터 상용 라이센스가 높다고 가르쳐 주었으므로, 전전...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.