StackExchange.Redis 之 List队列 类型示例
//从第1个开始,依次向左插入值。如果键不存在,先创建再插入值 队列形式 先进后出,后进先出
//插入后形式 <-- 10,9,8,7,6,5,4,3,2,1 <-- 方向向左依次进行
stopwatch.Start();
for (int i = ; i < ; i++)
{
var getobjlist = RedisCacheHelper.Instance.ListLeftPush("leftlistkey", (i + ).ToString());
}
stopwatch.Stop();
Console.WriteLine("在列表头部插入值消耗时间:" + stopwatch.ElapsedMilliseconds.ToString()); //从第1个开始,依次向右插入值。如果键不存在,先创建再插入值 先进先出,后进后出
//插入后形式 1,2,3,4,5,6,7,8,9,10 --> 方向向右依次进行
stopwatch.Start();
for (int i = ; i < ; i++)
{
var getobjlist = RedisCacheHelper.Instance.ListRightPush("rightlistkey", (i + ).ToString());
}
stopwatch.Stop();
Console.WriteLine("在列表尾部插入值消耗时间:" + stopwatch.ElapsedMilliseconds.ToString());


//获取Left列表中的队列元素 从列表头部开始读取
var getleftvalue = RedisCacheHelper.Instance.ListRange("leftlistkey");
Console.WriteLine(string.Join(",", getleftvalue)); //获取Right列表中的队列元素 从列表头部开始读取
var getrightvalue = RedisCacheHelper.Instance.ListRange("rightlistkey");
Console.WriteLine(string.Join(",", getrightvalue));

//从左边第一个元素开始 循环移除并返回该移除的值
Console.WriteLine("从左边开始");
while (true)
{
var getleftvalue = RedisCacheHelper.Instance.ListLeftPop("leftlistkey");
if (!string.IsNullOrEmpty(getleftvalue))
{
Console.WriteLine("移除:" + getleftvalue);
}
else
{
break;
}
} //从右边第一个元素开始 循环移除并返回该移除的值
Console.WriteLine("从右边开始");
while (true)
{
var getrightvalue = RedisCacheHelper.Instance.ListRightPop("rightlistkey");
if (!string.IsNullOrEmpty(getrightvalue))
{
Console.WriteLine("移除:" + getrightvalue);
}
else
{
break;
}
}

//从左边第一个元素开始 循环移除并返回该移除的值 替换一下Key后
Console.WriteLine("从左边开始");
while (true)
{
var getleftvalue = RedisCacheHelper.Instance.ListLeftPop("rightlistkey");
if (!string.IsNullOrEmpty(getleftvalue))
{
Console.WriteLine("移除:" + getleftvalue);
}
else
{
break;
}
} //从右边第一个元素开始 循环移除并返回该移除的值 替换一下Key后
Console.WriteLine("从右边开始");
while (true)
{
var getrightvalue = RedisCacheHelper.Instance.ListRightPop("leftlistkey");
if (!string.IsNullOrEmpty(getrightvalue))
{
Console.WriteLine("移除:" + getrightvalue);
}
else
{
break;
}
}

//列表长度 不存在则返回0
var getlength = RedisCacheHelper.Instance.ListLength("leftlistkey");
Console.WriteLine("列表长度:" + getlength); //删除List中的元素 并返回删除的个数 不存在则返回0
var getlong = RedisCacheHelper.Instance.ListDelRange("leftlistkey", "");
Console.WriteLine("删除List中的元素,并返回删除的个数:" + getlong); //清空列表
RedisCacheHelper.Instance.ListClear("leftlistkey");
使用List类型 模拟用户并发抢购商品
//模拟数据 想List类型表中加入一定数量的库存 50个商品
for (int i = ; i <= ; i++)
{
var getvalue = RedisCacheHelper.Instance.ListRightPush("orderlist", i.ToString());
//Console.WriteLine("返回结果:" + getvalue);
} //模拟创建多个用户 100个用户
List<TestRedis> testlist = new List<TestRedis>();
for (int i = ; i < ; i++)
{
testlist.Add(new TestRedis() { Uid = (i + ) });
} //先清空
RedisCacheHelper.Instance.ListClear("orderSuccessList"); //使用List类型模拟并发情况 不用担心库存为负的情况
//模拟多个用户抢购限时商品 100个用户抢50个商品
stopwatch.Start();
List<Task> taskList = new List<Task>();
foreach (var item in testlist)
{
var task = Task.Run(() =>
{
try
{
//先自减,获取自减后的值
long order_Num = -;
long.TryParse(RedisCacheHelper.Instance.ListRightPop("orderlist"), out order_Num);
if (order_Num > )
{
//下面执行订单逻辑(这里不考虑业务出错的情况) RedisCacheHelper.Instance.ListLeftPush("orderSuccessList", item.Uid.ToString()); //记录下单成功的用户 //操作数据库相关逻辑 可以使用“消息队列”或“服务”进行数据库同步操作 Console.WriteLine("用户:" + item.Uid + ",抢到了商品:" + order_Num);
}
else
{
Console.WriteLine("商品已经被抢光了,用户" + item.Uid + "未抢到");
} }
catch (Exception ex)
{
Console.WriteLine(ex.Message);
throw;
}
});
taskList.Add(task);
}
Task.WaitAll(taskList.ToArray());
stopwatch.Stop();
Console.WriteLine("模拟并发场景消耗时间:" + stopwatch.ElapsedMilliseconds.ToString());


应用场景:
Redis list 的应用场景非常多,也是 Redis 最重要的数据结构之一,比如 twitter 的关注列表,粉丝列表等都可以用 Redis 的 list 结构来实现,比较好理解,这里不再重复。
实现方式:
Redis list 的实现为一个双向链表,即可以支持反向查找和遍历,更方便操作,不过带来了部分额外的内存开销,Redis 内部的很多实现,包括发送缓冲队列等也都是用的这个数据结构。
最后附上Helper
/// <summary>
/// 在列表头部插入值。如果键不存在,先创建再插入值
/// </summary>
/// <param name="redisKey"></param>
/// <param name="redisValue"></param>
/// <returns></returns>
public long ListLeftPush(string redisKey, string redisValue, int db = -)
{
var _db = GetDatabase(db);
return _db.ListLeftPush(redisKey, redisValue);
}
/// <summary>
/// 在列表尾部插入值。如果键不存在,先创建再插入值
/// </summary>
/// <param name="redisKey"></param>
/// <param name="redisValue"></param>
/// <returns></returns>
public long ListRightPush(string redisKey, string redisValue, int db = -)
{
var _db = GetDatabase(db);
return _db.ListRightPush(redisKey, redisValue);
} /// <summary>
/// 在列表尾部插入数组集合。如果键不存在,先创建再插入值
/// </summary>
/// <param name="redisKey"></param>
/// <param name="redisValue"></param>
/// <returns></returns>
public long ListRightPush(string redisKey, IEnumerable<string> redisValue, int db = -)
{
var _db = GetDatabase(db);
var redislist = new List<RedisValue>();
foreach (var item in redisValue)
{
redislist.Add(item);
}
return _db.ListRightPush(redisKey, redislist.ToArray());
} /// <summary>
/// 移除并返回存储在该键列表的第一个元素 反序列化
/// </summary>
/// <param name="redisKey"></param>
/// <returns></returns>
public T ListLeftPop<T>(string redisKey, int db = -) where T : class
{
var _db = GetDatabase(db);
return JsonConvert.DeserializeObject<T>(_db.ListLeftPop(redisKey));
} /// <summary>
/// 移除并返回存储在该键列表的最后一个元素 反序列化
/// 只能是对象集合
/// </summary>
/// <param name="redisKey"></param>
/// <returns></returns>
public T ListRightPop<T>(string redisKey, int db = -) where T : class
{
var _db = GetDatabase(db);
return JsonConvert.DeserializeObject<T>(_db.ListRightPop(redisKey));
} /// <summary>
/// 移除并返回存储在该键列表的第一个元素
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="redisKey"></param>
/// <param name="db"></param>
/// <returns></returns>
public string ListLeftPop(string redisKey, int db = -)
{
var _db = GetDatabase(db);
return _db.ListLeftPop(redisKey);
} /// <summary>
/// 移除并返回存储在该键列表的最后一个元素
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="redisKey"></param>
/// <param name="db"></param>
/// <returns></returns>
public string ListRightPop(string redisKey, int db = -)
{
var _db = GetDatabase(db);
return _db.ListRightPop(redisKey);
} /// <summary>
/// 列表长度
/// </summary>
/// <param name="redisKey"></param>
/// <param name="db"></param>
/// <returns></returns>
public long ListLength(string redisKey, int db = -)
{
var _db = GetDatabase(db);
return _db.ListLength(redisKey);
} /// <summary>
/// 返回在该列表上键所对应的元素
/// </summary>
/// <param name="redisKey"></param>
/// <returns></returns>
public IEnumerable<string> ListRange(string redisKey, int db = -)
{
var _db = GetDatabase(db);
var result = _db.ListRange(redisKey);
return result.Select(o => o.ToString());
} /// <summary>
/// 根据索引获取指定位置数据
/// </summary>
/// <param name="redisKey"></param>
/// <param name="start"></param>
/// <param name="stop"></param>
/// <param name="db"></param>
/// <returns></returns>
public IEnumerable<string> ListRange(string redisKey, int start, int stop, int db = -)
{
var _db = GetDatabase(db);
var result = _db.ListRange(redisKey, start, stop);
return result.Select(o => o.ToString());
} /// <summary>
/// 删除List中的元素 并返回删除的个数
/// </summary>
/// <param name="redisKey">key</param>
/// <param name="redisValue">元素</param>
/// <param name="type">大于零 : 从表头开始向表尾搜索,小于零 : 从表尾开始向表头搜索,等于零:移除表中所有与 VALUE 相等的值</param>
/// <param name="db"></param>
/// <returns></returns>
public long ListDelRange(string redisKey, string redisValue, long type = , int db = -)
{
var _db = GetDatabase(db);
return _db.ListRemove(redisKey, redisValue, type);
} /// <summary>
/// 清空List
/// </summary>
/// <param name="redisKey"></param>
/// <param name="db"></param>
public void ListClear(string redisKey, int db = -)
{
var _db = GetDatabase(db);
_db.ListTrim(redisKey, , );
}
StackExchange.Redis 之 List队列 类型示例的更多相关文章
- StackExchange.Redis 之 Set集合 类型示例
话不多说直接上代码: // set添加单个元素 stopwatch.Start(); "); stopwatch.Stop(); Console.WriteLine("set添加单 ...
- StackExchange.Redis 之 hash 类型示例
StackExchange.Redis 的组件封装示例网上有很多,自行百度搜索即可. 这里只演示如何使用Hash类型操作数据: // 在 hash 中存入或修改一个值 并设置order_hashkey ...
- 怎样在Redis通过StackExchange.Redis 存储集合类型List
StackExchange 是由StackOverFlow出品, 是对Redis的.NET封装,被越来越多的.NET开发者使用在项目中. 绝大部分原先使用ServiceStack的开发者逐渐都转了过来 ...
- 利用StackExchange.Redis和Log4Net构建日志队列
简介:本文是一个简单的demo用于展示利用StackExchange.Redis和Log4Net构建日志队列,为高并发日志处理提供一些思路. 0.先下载安装Redis服务,然后再服务列表里启动服务(R ...
- StackExchange.Redis帮助类解决方案RedisRepository封装(字符串类型数据操作)
本文版权归博客园和作者本人共同所有,转载和爬虫请注明原文链接 http://www.cnblogs.com/tdws/tag/NoSql/ 目录 一.基础配置封装 二.String字符串类型数据操作封 ...
- .NetCore使用Redis,StackExchange.Redis队列,发布与订阅,分布式锁的简单使用
环境:之前一直是使用serverStack.Redis的客服端,今天来使用一下StackExchange.Redis(个人感觉更加的人性化一些,也是免费的,性能也不会差太多),版本为StackExch ...
- 深入理解MVC C#+HtmlAgilityPack+Dapper走一波爬虫 StackExchange.Redis 二次封装 C# WPF 用MediaElement控件实现视频循环播放 net 异步与同步
深入理解MVC MVC无人不知,可很多程序员对MVC的概念的理解似乎有误,换言之他们一直在错用MVC,尽管即使如此软件也能被写出来,然而软件内部代码的组织方式却是不科学的,这会影响到软件的可维护性 ...
- StackExchange.Redis 使用资料
在StackExchange.Redis中最重要的对象是ConnectionMultiplexer类, 它存在于StackExchange.redis命名空间中.这个类隐藏了Redis服务的操作细节, ...
- Redis 详解 (一) StackExchange.Redis Client
这期我们来看StackExchange.Redis,这是redis 的.net客户端之一.Redis是一个开源的内存数据存储,可以用来做数据库,缓存或者消息代理服务.目前有不少人在使用ServiceS ...
随机推荐
- Hystrix 监控数据聚合 Turbine【Finchley 版】
原文地址:https://windmt.com/2018/04/17/spring-cloud-6-turbine/ 上一篇我们介绍了使用 Hystrix Dashboard 来展示 Hystrix ...
- 英语学习app——Alpha发布2
英语学习app--Alpha发布1 这个作业属这个作业属于哪个课程 https://edu.cnblogs.com/campus/xnsy/GeographicInformationScience/ ...
- Ceph 之RGW Cache
Overview 缓存是为达到系统快速响应的一项关键技术,Ceph 作为一个复杂的分布式存储系统,有多种.多级缓存存在.缓存按照位置分为: 客户端缓存 服务端缓存 网络中缓存 按照部署方式分为: 单体 ...
- [校内训练19_09_10]sort
题意 给一个非负整数序列,每次问能否异或上一个正整数使得所有的数单调不减.如果能,输出最小的x,否则输出-1.单点修改.多测.要求最多一个log. 思考 只要考虑相邻的两个数.找到这两个数最高的不同的 ...
- CF572_Div2_F
题意 http://codeforces.com/contest/1189/problem/F 思考 由于是子序列,答案只跟选法有关,与顺序无关,先排序. 直接计算答案比较困难.联想到期望的无穷级数计 ...
- Guava中强大的排序器Ordering使用
一 创建排序器 排序器:可以用来为构建复杂的比较器,以完成集合排序的功能: 本质上来说,Ordering 实例无非就是一个特殊的Comparator 实例. Ordering把很多基于Comparat ...
- java刷题(1-5)
第一题:在一个数组中找出三个数相加之和为0,且不重复的集合 import java.lang.reflect.Array; import java.security.PublicKey; import ...
- Ceph 存储集群-低级运维
低级集群运维包括启动.停止.重启集群内的某个具体守护进程:更改某守护进程或子系统配置:增加或拆除守护进程.低级运维还经常遇到扩展.缩减 Ceph 集群,以及更换老旧.或损坏的硬件. 一.增加/删除 O ...
- 文件类练习题(FileInputStream类)
应用FileInputStream类,编写应用程序,从磁盘上读取一个Java程序,并将源程序代码显示在屏幕上.(被读取的文件路径为:d:/myjava/Hello.java 内容自己决定): pack ...
- LUA学习笔记(第18-20章)
数学库 print(math.pi)-->π print(math.huge)-->Lua中表示的最大数字 --[[ 3.1415926535898 1.#INF ]] print(mat ...