Redis学习系列六ZSet(有序列表)及Redis数据结构的过期
一、简介
ZSet可以说是Redis中最有趣的数据结构了,因为他兼具了Hash集合和Set的双重特性,也是用的最多的,保证了value值的唯一性的同时,,同时又保证了高性能,最主要的是还可以给每个Value设置Source(权重),那么我们就可以通过权重进行排序,这在业务上是非常常见的,比如很多地方需要,比如我们需要对所有用户的数学成绩进行排序.对英语等等地例子比比皆是,那么通过ZSet,你将会得到一个响应速度非常快的过程.下面会介绍.
ZSet的内部原理是通过跳跃列表来实现的,这里还是不想说太多关于算法的东西.
二、ZSet(有序列表)实战
下面就通过一个列子来讲解,主要是给所有用户的数学成绩进行排序的例子.代码开始在前面的随笔上进行扩展.
C#控制台:
给RedisClient.cs扩展如下几个方法:
/// <summary>
/// 异步不带权重的向有序列表批量插入数据
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public static async Task<long> SortedSetAddAsync(RedisKey key, SortedSetEntry[] entries)
{
var db = GetDatabase();
return await db.SortedSetAddAsync(key, entries);
} /// <summary>
/// 异步带权重的向有序列表插入单个元素,不管是否存在已有元素,都执行插入操作
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public static async Task<RedisValue> SortedSetAddAsync(RedisKey key, RedisValue value,double source)
{
var db = GetDatabase();
return await db.SortedSetAddAsync(key, value, source);
} /// <summary>
/// 异步按权重(范围为负无穷大到正无穷大排序)得到所有的元素,返回的元素(不包含权重)集合默认的排序时按权重从低到高,可指定权重
/// </summary>
/// <param name="key"></param>
/// <param name="start">权重下限</param>
/// <param name="stop">权重上限</param>
/// <returns></returns>
public static async Task<RedisValue[]> SortedSetRangeByScoreAsync(RedisKey key, double start = double.NegativeInfinity, double stop = double.PositiveInfinity)
{
var db = GetDatabase();
return await db.SortedSetRangeByScoreAsync(key, start, stop);
} /// <summary>
/// 异步按权重(范围为负无穷大到正无穷大排序)得到所有的元素,返回的元素(包含权重)集合默认的排序时按权重从低到高,可指定权重
/// </summary>
/// <param name="key"></param>
/// <param name="start"></param>
/// <param name="stop"></param>
/// <returns></returns>
public static async Task<SortedSetEntry[]> SortedSetRangeByScoreWithScoresAsync(RedisKey key, double start = double.NegativeInfinity, double stop = double.PositiveInfinity)
{
var db = GetDatabase();
return await db.SortedSetRangeByScoreWithScoresAsync(key, start,stop);
} /// <summary>
/// 异步按权重(范围为负无穷大到正无穷大排序)得到所有的元素,返回的元素(包含权重)集合默认的排序时按权重从高到低,可指定权重
/// </summary>
/// <param name="key"></param>
/// <param name="start"></param>
/// <param name="stop"></param>
/// <returns></returns>
public static async Task<SortedSetEntry[]> SortedSetRangeByScoreWithScoresDescendingAsync(RedisKey key, double start = double.NegativeInfinity, double stop = double.PositiveInfinity)
{
var db = GetDatabase();
return await db.SortedSetRangeByScoreWithScoresAsync(key, start, stop,Exclude.None, Order.Descending);
} /// <summary>
/// 异步按权重范围,删除对应键下的所有元素
/// </summary>
/// <param name="key"></param>
/// <param name="start"></param>
/// <param name="stop"></param>
/// <returns></returns>
public static async Task<long> SortedSetRemoveRangeByScoreAsync(RedisKey key, double start = double.NegativeInfinity, double stop = double.PositiveInfinity)
{
var db = GetDatabase();
return await db.SortedSetRemoveRangeByScoreAsync(key, start, stop);
} /// <summary>
/// 异步删除指定键下的指定值
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
/// <returns></returns>
public static async Task<bool> SortedSetRemoveAsync(RedisKey key, RedisValue value)
{
var db = GetDatabase();
return await db.SortedSetRemoveAsync(key, value);
}
还可以继续扩展,个人觉得其它方法没什么用,就没有继续扩展了.
Program.cs代码如下:
class Program
{
static Program()
{
//链式配置Redis
AppConfiguration.Current.ConfigureRedis<RedisConfig>();
} static void Main(string[] args)
{
StringSetGetAsync();
Console.ReadKey();
} static async void StringSetGetAsync()
{
var key = "math";
var computer = new KeyValuePair<RedisValue, double>("小超的用户Id", 9.0);
var english = new KeyValuePair<RedisValue, double>("大超的用户Id", 8.0);
var math = new KeyValuePair<RedisValue, double>("中超的用户Id", 7.0);
var chinese = new KeyValuePair<RedisValue, double>("大大超的用户Id", 10.0);
try
{
await RedisClient.SortedSetAddAsync(key, new SortedSetEntry[] { computer, math, english, chinese }); //模拟重复插入,不会发现插入没有效果,因为Zset自带去重功能是Set和Hash的组合体
await RedisClient.SortedSetAddAsync(key, new SortedSetEntry[] { computer, math, english }); Console.WriteLine("输出指定键的所有元素(不包含权重),默认按权重从小到大排序");
//输出指定键的所有元素(不包含权重),默认按权重从小到大排序
var values =await RedisClient.SortedSetRangeByScoreAsync(key);
foreach (var val in values)
{
Console.WriteLine("值为:{0}",val);
}
Console.WriteLine("输出指定键的所有元素(包含权重),默认按权重从小到大排序");
//输出指定键的所有元素(包含权重),默认按权重从小到大排序
var oValues= await RedisClient.SortedSetRangeByScoreWithScoresAsync(key);
foreach (var oVal in oValues)
{
Console.WriteLine("值为:{0},权重为:{1}",oVal.Element,oVal.Score);
} Console.WriteLine("输出指定键的所有元素(包含权重),按权重从大到小排序");
//输出指定键的所有元素(包含权重),按权重从大到小排序,权重范围为7~8
var lValues = await RedisClient.SortedSetRangeByScoreWithScoresDescendingAsync(key,,);
foreach (var lVal in lValues)
{
Console.WriteLine("值为:{0},权重为:{1}", lVal.Element, lVal.Score);
}
try
{
await RedisClient.SortedSetRemoveRangeByScoreAsync(key, , );
Console.WriteLine("删除key为:{0}下权重为7~8之间的所有元素成功!", key);
}
catch (Exception ex)
{
Console.WriteLine("删除元素发生了异常,信息为{0}", ex.Message);
}
var extraValues = await RedisClient.SortedSetRangeByScoreWithScoresAsync(key);
foreach (var eVal in extraValues)
{
Console.WriteLine("值为:{0},权重为:{1}", eVal.Element, eVal.Score);
} //输出一个指定键下的指定值
try
{
var value = "大大超的用户Id";
await RedisClient.SortedSetRemoveAsync(key, value);
Console.WriteLine("删除key为:{0}下值为:{1}的元素成功!", key, value);
}
catch (Exception ex)
{
Console.WriteLine("删除元素发生了异常,信息为{0}", ex.Message);
} var exValues = await RedisClient.SortedSetRangeByScoreWithScoresAsync(key);
foreach (var exVal in exValues)
{
Console.WriteLine("值为:{0},权重为:{1}", exVal.Element, exVal.Score);
} }
catch (Exception ex)
{
//记录日志
Console.WriteLine(ex.Message);
}
}
}

上面的权重就是实际的分数,ok,是不是很强大!
三、给Redis数据结构设置过期时间
到这里Redis的5大基本数据结构算介绍完了,该讲讲过期的知识,Redis的所有数据结构都可以设置过期时间,时间一到,Redis会自动删除相应的对象,注意:Redis的5大基本数据结构基本都是键值对的关系,最外部有个键来指定整个对象,所以Redis的删除是争对该键对应的对象的.但是Hash结构中,除了指定外部的键还可以指定内部的键.向下面这样:

但是Redis的过期是争对最外部的键的.就是整个数据结构.
注:关于String结构也有点特殊,因为它本身也可以设置过期时间,如果你已经给一个字符串设置了过期时间,然后调用了过期Api修改它,它原先的过期时间会消失.
给RedisClient.cs扩展如下方法:
/// <summary>
/// 异步给指定的键的对象设置过期时间
/// </summary>
/// <param name="key"></param>
/// <param name="timeSpan"></param>
/// <returns></returns>
public static async Task<bool> KeyExpireAsync(RedisKey key,TimeSpan timeSpan)
{
var db = GetDatabase();
return await db.KeyExpireAsync(key, timeSpan);
}
Program.cs代码如下:
class Program
{
static Program()
{
//链式配置Redis
AppConfiguration.Current.ConfigureRedis<RedisConfig>();
} static void Main(string[] args)
{
StringSetGetAsync();
Console.ReadKey();
} static async void StringSetGetAsync()
{
var key = "math";
try
{
await RedisClient.KeyExpireAsync(key, TimeSpan.FromMilliseconds());
Console.WriteLine("给指定的键设置过期时间异常成功.");
}
catch (Exception ex)
{
Console.WriteLine("给指定的键设置过期时间异常,信息为:{0}.", ex.Message);
} }
}


对应键为math的ZSet结构对象消失了.其余数据结构自行测试.最好在设置前判断对应的对象存不存在,虽然我试过了,消失了还可以继续设置
Redis学习系列六ZSet(有序列表)及Redis数据结构的过期的更多相关文章
- 分布式缓存技术redis学习系列(二)——详细讲解redis数据结构(内存模型)以及常用命令
Redis数据类型 与Memcached仅支持简单的key-value结构的数据记录不同,Redis支持的数据类型要丰富得多,常用的数据类型主要有五种:String.List.Hash.Set和Sor ...
- 分布式缓存技术redis学习系列
分布式缓存技术redis学习系列(一)--redis简介以及linux上的安装以及操作redis问题整理 分布式缓存技术redis学习系列(二)--详细讲解redis数据结构(内存模型)以及常用命令 ...
- Python操作redis学习系列之(集合)set,redis set详解 (六)
# -*- coding: utf-8 -*- import redis r = redis.Redis(host=") 1. Sadd 命令将一个或多个成员元素加入到集合中,已经存在于集合 ...
- 分布式缓存技术redis学习系列(五)——redis实战(redis与spring整合,分布式锁实现)
本文是redis学习系列的第五篇,点击下面链接可回看系列文章 <redis简介以及linux上的安装> <详细讲解redis数据结构(内存模型)以及常用命令> <redi ...
- 分布式缓存技术redis学习系列(四)——redis高级应用(集群搭建、集群分区原理、集群操作)
本文是redis学习系列的第四篇,前面我们学习了redis的数据结构和一些高级特性,点击下面链接可回看 <详细讲解redis数据结构(内存模型)以及常用命令> <redis高级应用( ...
- Python学习系列(四)(列表及其函数)
Python学习系列(四)(列表及其函数) Python学习系列(一)(基础入门) Python学习系列(二)(基础知识) Python学习系列(三)(字符串) 一.基本概念 1,列表是什么? ...
- redis学习系列
redis学习系列 基本看完 最近在看redis的代码,简单记录下自己认为重要的点,自己写比较费时间的,我会把查到的资料贴出来方便查看 淘宝的redis内存分析 http://www.searchtb ...
- C# Redis学习系列三:Redis配置主从
Redis配置主从 主IP :端口 192.168.0.103 6666 从IP:端口 192.168.0.108 3333 配置从库 (1)安装服务: redis-server ...
- Redis学习笔记六:持久化实验(AOF,RDB)
作者:Grey 原文地址:Redis学习笔记六:持久化实验(AOF,RDB) Redis几种持久化方案介绍和对比 AOF方式:https://blog.csdn.net/ctwctw/article/ ...
随机推荐
- Linux系统各发行版镜像下载(借阅)
Linux各个版本资源下载 Linux系统各发行版镜像下载(持续更新) == Linux系统各发行版镜像下载(2014年10月更新),如果直接下载不了,请使用迅雷下载.并且注意,我的下载地址,在 迅 ...
- 【慕课网实战】Spark Streaming实时流处理项目实战笔记七之铭文升级版
铭文一级: 第五章:实战环境搭建 Spark源码编译命令:./dev/make-distribution.sh \--name 2.6.0-cdh5.7.0 \--tgz \-Pyarn -Phado ...
- winSocket编程(一)WSAStartup
/******************************************************************** 更新日期:2017-11-07 10:33:08* 进度:完 ...
- 【1】ASP.NET异步(1)
图标说明了异步的基础认识. 1.如果没有Ajax,提交之后整个页会刷新(左图).右图所示的虚线范围区域加入了ajax技术,提交之后只更新了虚线区域的内容,这样看比较直白. <form>①& ...
- 位图bitbucket
问题:假设有500w条数据,数据是在2^32-1的范围内,数据重复,如何减少内存对数字进行统计呢? 如果用字典来标记数字是否已经统计过来,数字做为key, value仅为0 or1,那么这样需要消耗 ...
- bash多进程
#!/bin/bashCMD_PATH=`dirname $0`#echo $CMD_PATH > /home/wubin/testjava -jar $CMD_PATH/Server.jar ...
- 谈谈HashMap线程不安全的体现
原文出处: Hosee HashMap的原理以及如何实现,之前在JDK7与JDK8中HashMap的实现中已经说明了. 那么,为什么说HashMap是线程不安全的呢?它在多线程环境下,会发生什么情况呢 ...
- 第80讲:List的泛型分析以及::类和Nil对象
今天我们学习一下scala中的列表,List. 通过源码,我们可以发现,List类型是协变的,所以我们可以把Int类型的List赋值给Any型的List. 我们可以看到,List定义下有3个比较重要的 ...
- 学习stm32 让我们一起回顾一下C语言吧
ODR 是一个端口输出数据寄存器,也只用了低 16 位.该寄存器为可读写,从该寄存器读出来的数据可以用于判断当前 IO 口的输出状态.而向该寄存器写数据,则可以控制某个 IO 口的输出电平.该寄存器的 ...
- Git和SourceTree配合使用
Git介绍 git是当今最强大的本地的分布式代码版本管理工具. git的核心概念与操作:开发环境,本地仓库,远程仓库.他们的关系如下图: 与CVS及SVN的比较: CVS及SVN都是集中式的版本控制系 ...