Redis分布式缓存学习总结6(list数据类型)

1.简介

Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边),可以使用list的push操作将任务存到List,

然后使用pop操作将任务取出执行,在列表头部或者末尾操作数据非常高效,不受队列长度的影响。

列表最多可存储 232- 1 元素 (4294967295, 每个列表可存储40多亿)。

2.使用场景

redis 的 list 数据类型对于大部分使用者来说,是实现队列服务的最经济,最简单的方式。

另外,因为 list 结构的数据查询两端附近的数据性能非常好,所以适合一些需要获取最新数据的场景,比如新闻类应用的 “最近新闻”,获取前N个用户列表等。

3.list数据结构示意图

list类型在存储数据时,是以key-LinkList<value>格式存储的,如下图所示:

 

如下是对list封装后的api方法,RedisListService.cs,代码如下: 

 

using MyRedis.Redis.Interface;
using ServiceStack.Redis;
using System;
using System.Collections.Generic;

namespace MyRedis.Redis.Service
{
    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.iClient.EnqueueItemOnList(listId, value);
        }

        /// <summary>
        /// 出队
        /// </summary>
        /// <param name="listId">集合Id</param>
        /// <returns>出队的值</returns>
        public string DequeueItemFromList(string listId)
        {
            return base.iClient.DequeueItemFromList(listId);
        }

        /// <summary>
        /// 出队(阻塞)
        /// </summary>
        /// <param name="listId">集合Id</param>
        /// <param name="timeOut">阻塞时间(超时时间)</param>
        /// <returns>出队的值</returns>
        public string BlockingDequeueItemFromList(string listId, TimeSpan? timeOut)
        {
            return base.iClient.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.iClient.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.iClient.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.iClient.PushItemToList(listId, value);
            base.iClient.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.iClient.PushItemToList(listId, value);
            base.iClient.ExpireEntryIn(listId, expireIn);
        }

        /// <summary>
        /// 出栈
        /// </summary>
        /// <param name="listId">集合Id</param>
        /// <returns>出栈的值</returns>
        public string PopItemFromList(string listId)
        {
            return base.iClient.PopItemFromList(listId);
        }

        /// <summary>
        /// 出栈(阻塞)
        /// </summary>
        /// <param name="listId">集合Id</param>
        /// <param name="timeOut">阻塞时间(超时时间)</param>
        /// <returns>出栈的值</returns>
        public string BlockingPopItemFromList(string listId, TimeSpan? timeOut)
        {
            return base.iClient.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.iClient.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.iClient.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.iClient.BlockingPopAndPushItemBetweenLists(fromListId, toListId, timeOut);
        }

        #endregion Stack栈(后进先出)

        #region 赋值

        /// <summary>
        /// 向list头部添加value值
        /// </summary>
        public void PrependItemToList(string listId, string value)
        {
            base.iClient.PrependItemToList(listId, value);
        }

        /// <summary>
        /// 向list头部添加value值,并设置过期时间
        /// </summary>    
        public void PrependItemToList(string listId, string value, DateTime expireAt)
        {
            base.iClient.PrependItemToList(listId, value);
            base.iClient.ExpireEntryAt(listId, expireAt);
        }

        /// <summary>
        /// 向list头部添加value值,并设置过期时间
        /// </summary>        
        public void PrependItemToList(string listId, string value, TimeSpan expireIn)
        {
            base.iClient.PrependItemToList(listId, value);
            base.iClient.ExpireEntryIn(listId, expireIn);
        }

        /// <summary>
        /// 向list中添加value值
        /// </summary>     
        public void AddItemToList(string listId, string value)
        {
            base.iClient.AddItemToList(listId, value);
        }

        /// <summary>
        /// 向list中添加value值,并设置过期时间
        /// </summary>  
        public void AddItemToList(string listId, string value, DateTime expireAt)
        {
            base.iClient.AddItemToList(listId, value);
            base.iClient.ExpireEntryAt(listId, expireAt);
        }

        /// <summary>
        /// 向list中添加value值,并设置过期时间
        /// </summary>  
        public void AddItemToList(string listId, string value, TimeSpan expireIn)
        {
            base.iClient.AddItemToList(listId, value);
            base.iClient.ExpireEntryIn(listId, expireIn);
        }

        /// <summary>
        /// 向list中添加多个value值
        /// </summary>  
        public void AddRangeToList(string listId, List<string> values)
        {
            base.iClient.AddRangeToList(listId, values);
        }

        /// <summary>
        /// 向list中添加多个value值,并设置过期时间
        /// </summary>  
        public void AddRangeToList(string listId, List<string> values, DateTime expireAt)
        {
            base.iClient.AddRangeToList(listId, values);
            base.iClient.ExpireEntryAt(listId, expireAt);
        }

        /// <summary>
        /// 向list中添加多个value值,并设置过期时间
        /// </summary>  
        public void AddRangeToList(string listId, List<string> values, TimeSpan expireIn)
        {
            base.iClient.AddRangeToList(listId, values);
            base.iClient.ExpireEntryIn(listId, expireIn);
        }

        #endregion 赋值

        #region 获取值

        /// <summary>
        /// 获取指定list中包含的数据数量
        /// </summary>  
        public long GetListCount(string listId)
        {
            return base.iClient.GetListCount(listId);
        }

        /// <summary>
        /// 获取指定list中包含的所有数据集合
        /// </summary>  
        public List<string> GetAllItemsFromList(string listId)
        {
            return base.iClient.GetAllItemsFromList(listId);
        }

        /// <summary>
        /// 获取指定list中下标从startingFrom到endingAt的值集合
        /// </summary>  
        public List<string> GetRangeFromList(string listId, int startingFrom, int endingAt)
        {
            return base.iClient.GetRangeFromList(listId, startingFrom, endingAt);
        }

        #endregion 获取值

        #region 删除

        /// <summary>
        /// 移除指定list中,listId/value,与参数相同的值,并返回移除的数量
        /// </summary>  
        public long RemoveItemFromList(string listId, string value)
        {
            return base.iClient.RemoveItemFromList(listId, value);
        }

        /// <summary>
        /// 从指定list的尾部移除一个数据,并返回移除的数据
        /// </summary>  
        public string RemoveEndFromList(string listId)
        {
            return base.iClient.RemoveEndFromList(listId);
        }

        /// <summary>
        /// 从指定list的头部移除一个数据,并返回移除的数据
        /// </summary>  
        public string RemoveStartFromList(string listId)
        {
            return base.iClient.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.iClient.TrimList(listId, keepStartingFrom, keepEndingAt);
        }

        #endregion 其它

        #region 发布订阅

        /// <summary>
        /// 发布
        /// </summary>
        /// <param name="channel">频道</param>
        /// <param name="message">消息</param>
        public void Publish(string channel, string message)
        {
            base.iClient.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.iClient.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.iClient.CreateSubscription();
            subscription.UnSubscribeFromChannels(channel);
        }

        #endregion 发布订阅
    }
}

上面的代码创建完成后,项目的基础就构建完成了,下面开始学习list数据类型常用api的使用。

在控制台应用程序中的ServiceStackTest.cs类中,调用Redis的api方法。代码如下:

using MyRedis.Redis.Service;
using System;
using System.Collections.Generic;
using System.Threading;

namespace MyRedis
{
    /// <summary>
    /// ServiceStackTest api 封装测试
    /// </summary>
    public class ServiceStackTest
    {
        public static void Show()
        {
            #region RedisListService
            using (RedisListService listService = new RedisListService())
            {
                #region List队列操作
                listService.EnqueueItemOnList("QueueList", "打印任务1"); //入队
                listService.EnqueueItemOnList("QueueList", "打印任务2");
                listService.EnqueueItemOnList("QueueList", "打印任务3");
                listService.EnqueueItemOnList("QueueList", "打印任务4");
                long q = listService.GetListCount("QueueList");
                Console.WriteLine("打印任务按照顺序打印开始");
                for (int i = 0; i < q; i++)
                {
                    Console.WriteLine("QueueList出队值:{0}", listService.DequeueItemFromList("QueueList"));
                }
                Console.WriteLine("打印任务按照顺序打印完成");
                #endregion

                #region 栈操作
                listService.PushItemToList("StackList", "入栈操作1"); //入栈
                listService.PushItemToList("StackList", "入栈操作2");
                listService.PushItemToList("StackList", "入栈操作3");
                listService.PushItemToList("StackList", "入栈操作4");
                Console.WriteLine("开始出栈");
                long p = listService.GetListCount("StackList");
                for (int i = 0; i < p; i++)
                {
                    Console.WriteLine("StackList出栈值:{0}", listService.PopItemFromList("StackList"));
                }
                Console.WriteLine("出栈完成");
                #endregion
            }
            #endregion


        }
    }
}

执行结果:

上面代码中包含两个实例,队列的使用和栈的使用。

对于队列的使用,有多个客户端需要打印机打印任务,那么使用队列进行任务的排队,然后按照排队顺序开始打印。

对于栈的使用,实现了入栈和出栈,先进后出的顺序完成。

总结:队列是先进先出操作,栈是先进后出操作,并且操作完成后,数据被删除。 

使用list可以实现数据分页和发布订阅等待功能。

更多关于list数据类型的说明,可以参考文章:https://www.cnblogs.com/xyh9039/p/14022264.html

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值