
在 Redis 中查看数据可以使用以下命令:
keys pattern 命令可以列出匹配给定模式的所有键名。例如,执行 keys 可以列出所有的键名。
type key 命令可以查看指定键的数据类型。例如,执行 type mykey 可以查看键 mykey 的数据类型。
get key 命令可以获取指定键的值。例如,执行 get mykey 可以获取键 mykey 的值。
hgetall key 命令可以获取指定哈希表的所有键值对。例如,执行 hgetall myhash 可以获取哈希表 myhash 的所有键值对。
lrange key start stop 命令可以获取指定列表的一部分元素。例如,执行 lrange mylist 0 -1 可以获取列表 mylist 的所有元素。
smembers key 命令可以获取指定集合的所有成员。例如,执行 smembers myset 可以获取集合 myset 的所有成员。
zrange key start stop 命令可以获取指定有序集合的一部分成员。例如,执行 zrange myzset 0 -1 可以获取有序集合 myzset 的所有成员。
以上是 Redis 中一些基本的数据查看命令,具体使用取决于你想要查看的数据类型和数据结构。
解决方案
如果你仅仅为了缓存存一批量的 List<Customer> 数据, 那么自己封装一个ListGet() 和 ListSet()方法吧。
我对比过使用 List 和 String 两种类型存储。
Redis 的List类型和 NET领域还有所不同,实际上,它是一个双向队列,可以左右插入值。
所以如果是批量数据插入 那么必须一个个插入, 代码比较简单如下:
//封装的ListSet
public void ListSet<T>(string key, List<T> value){
//下面的database 是redis的数据库对象
foreach (var single in value)
{
var s = ConvertJson(single); //序列化
databaseListRightPush(key, s); //要一个个的插入
}
}
//封装的ListGet
public void ListGet<T>(string key)
{
//ListRange返回的是一组字符串对象
//需要逐个反序列化成实体
var vList = databaseListRange(key) ;
List<T> result = new List<T>();
foreach (var item in vList)
{
var model = ConvertObj<T>(item); //反序列化
resultAdd(model);
}
return result;
}
当然测试了一下性能,取20W条数据平均时间
上一篇文章写了 redis客户端的各种list *** 作 ,这篇文章用python客户端来复现一下。(建议结合上篇文章看,效果更佳)
brpop / blpop / brpoplpush 没在这里实现,详细可查看上篇文章(上面超链接)
当同时满足以下条件时,使用ziplist编码:
SpringBoot—实现n秒内出现x个异常报警
思路:
借助Redis的zSet集合,score存储的是异常时的时间戳,获取一定时间范围内的set集合。判断set个数是否满足条件,若满足条件则触发报警;
注意点:
相关API:
Redis实现延迟队列方法介绍
基于Redis实现DelayQueue延迟队列设计方案
相关API:
SpringBoot2x—使用Redis的bitmap实现布隆过滤器(Guava中BF算法)
布隆过滤器: 是专门用来检测集合中是否存在特定元素的数据结构。
存在误差率: 即将不在集合的元素误判在集合中。
所以布隆过滤器适合查询准确度要求没这么苛刻,但是对时间、空间效率比较高的场景。
实现方式:Redis实现布隆过滤器——借鉴Guava的BF算法:
SpringBoot2x中使用Redis的bitmap结构(工具类)
注意:bitmap使用存在风险,若仅仅计算hash值,会导致bitmap占用空间过大。一般需要对hash值进行取余处理。
根据Redis是否存在key,判断锁是否被获取;
锁应该是一个对象,记录持有锁的线程信息、当前重入次数。所以应该使用Redis的Hash结构来存储锁对象。
31 网络波动造成释放锁失败怎么解决?
需要为锁加上超时时间;
32 任务未执行完毕时,锁由于超时时间被释放?
线程一旦加锁成功,可以启动一个后台线程,每隔多少秒检查一次,如果线程还持有锁,可以不断延长锁的生存时间。
主从切换时,从服务器上没有加锁信息,导致多个客户端同时加锁。
list结构底层是ziplist/quicklist(可看着一个双端队列)。常用命令:
使用list作为对象的缓存池。通过rpush放入对象,通过lpop取出对象。
若是阻塞取,可以使用blpop命令实现。
Redis和Lua脚本(实现令牌桶限流)
数据结构选择hash。
hash里面维护:最后放入令牌时间、当前桶内令牌量、桶内最大数量、令牌放置速度(元数据)。
被动式维护:
命令:incr原子累加;
对一段固定时间窗口内的请求进行计数,如果请求数超过了阈值,则舍弃该请求;如果没有达到设定的阈值,则接受该请求,且计数加1。当窗口时间结束,重置计数器为0。
优点:实现简单,容易理解;
缺点:流量曲线可能不够平滑,有“突刺现象”。
1 一段时间内(不超过时间窗口)系统服务不可用。 比如窗口大小1s,限流为100,恰好某个窗口第1ms来了100个请求,然后2ms-999ms请求都会被拒绝。这段时间用户会感觉系统服务不可用(即不够平滑)。
2 窗口切换时可能会出现两倍于阈值流量的请求。 比如窗口大小1s,限流大小100,然后在某个窗口的第999ms有100个请求,窗口前期没有请求。所以这100个请求都会通过。然后下一个窗口的第1ms又来100个请求,然后全部通过。其实也是1ms内通过的200个请求。
命令:Redis的incr命令
是对固定窗口计数器的优化,解决的是切换窗口两倍阈值流量的场景。
具体解决方案是:将限流窗口分为多个小的限流窗口,各个限流窗口分别计数。当前时间大于窗口最大时间时,将头部的小窗口数据舍弃,尾部新增小窗口来处理新请求。
优点:本质上是对固定窗口的优化
StackExchange 是由StackOverFlow出品, 是对Redis的NET封装,被越来越多的NET开发者使用在项目中。
绝大部分原先使用ServiceStack的开发者逐渐都转了过来,由于SS在其新版中不再开源,并对免费版本有所限制。
实际问题
那么用NET的开发者会发现,其根本没有对List类型的存储封装,那么要实现一个类似如下需求:
假如我有一个Customer的模型。
public class Customer{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Address1 { get; set; }
public string City { get; set; }
public string State { get; set; }
}
var customers = new List<Customer>();
怎样将List<customer> customers 存入Redis中呢?
来龙去脉
是由于StackExchangeRedis是一个纯客户端的代理,他仅仅实现了Redis自由的功能,并不额外封装其它功能。 也不具备像ORM那样的自动类型匹配。
他仅仅存储键值对 像string 或者
byte[]。所以你明白了吧,必须序列化存储,用类似Json格式一样。像用第三方NewtonSoft或者是Google公司流行的Protocol Buffers
序列化格式的Protobuf-Net 也是不错的选择。
Redis支持存储的类型有五种String ,Hash ,List ,Set ,和 Sorted Set, 正如上面说的,这些存储类型全部由字符串构成。
其中Set类型是没有顺序的,并且值必须唯一, List类型有顺序且允许重复。
解决方案
如果你仅仅为了缓存存一批量的 List<Customer> 数据, 那么自己封装一个ListGet() 和 ListSet()方法吧。
我对比过使用 List 和 String 两种类型存储。
Redis 的List类型和 NET领域还有所不同,实际上,它是一个双向队列,可以左右插入值。
所以如果是批量数据插入 那么必须一个个插入, 代码比较简单如下:
//封装的ListSetpublic void ListSet<T>(string key, List<T> value)
{
//下面的database 是redis的数据库对象
foreach (var single in value)
{
var s = ConvertJson(single); //序列化
databaseListRightPush(key, s); //要一个个的插入
}
}
//封装的ListGet
public void ListGet<T>(string key)
{
//ListRange返回的是一组字符串对象
//需要逐个反序列化成实体
var vList = databaseListRange(key) ;
List<T> result = new List<T>();
foreach (var item in vList)
{
var model = ConvertObj<T>(item); //反序列化
resultAdd(model);
}
return result;
}
当然测试了一下性能,取20W条数据平均时间
Redis中,并不是所有的数据都一直存储在内存中的,这是和Memcached相比一个最大的区别。
2 Redis在很多方面具备数据库的特征,或者说就是一个数据库系统,而Memcached只是简单的K/V缓存。
3 他们的扩展都需要做集群;实现方式:master-slave、Hash。
4 在100k以上的数据中,Memcached性能要高于Redis。
在之前的文章中我们有提及string类型是通过底层的SDS(简单动态字符串)实现的,那么其他呢?
除了String类型外,list,set,sorted set,hash这四种都有两种底层实现结构,通常情况我们称这四种类型为集合类型, 特点是一个键对应了一个集合的数据 :
list由双向链表和压缩列表实现
hash由压缩列表和哈希表实现
sorted set由跳表和压缩列表实现
set 由整数数组和哈希表实现
·1压缩列表在查找和更新的时间复杂度方面没有很大的优势,为什么redis要把他作为底层数据结构
2集合数据的 *** 作效率
list由双向链表和压缩列表实现
阅读src/ziplisth和src/ziplistc我们惊奇的发现一件事情:
redis竟没有提供一个结构体保存压缩列表的信息,而是提供了一组宏来定义每个成员的地址
压缩列表是一系列 特殊编码的连续内存块 组成的顺序序列数据结构,可以包含任意多个节点(entry),每一个节点可以保存一个字节数组或者一个整数值。
这个数据结构是不是乍一看很像数组,每一个元素entry保存了一个数据,和数组不同的是表头有三个字段:
1zlbytes标识整个压缩列表长度
2zltail标识列表的偏移量,表尾点entryN距离压缩列表起始地址的字节数
3zllen标识列表中entry个数
列表表尾还有一个zlend标识结束
那么我们就可以快速定位第一个元素(zlbytes-10)和最后一个元素(zlbytes-1)了
ziplist的每个节点由3个部分组成:
1prevlen表示前一个节点的长度
2encoding表示节点的编码格式
3entry-data:压缩后的数据
zpilist格式
<zlbytes> <zltail> <zllen> <entry> <entry> <entry> <zlend>
zlbytes:ziplist占总字节数
zltail:最后一个元素的偏移量,相当于ziplist的尾指针。
zllen:entry元素个数
zlend :ziplist结束标志位
entry:ziplist的各个节点
ziplist的entry 的格式:
<prevlen> <encoding><len> <entry-data>
prevlen :前一个元素的长度,相当于节点保存前一个元素的指针。
encoding: 记录了当前节点保存的数据的类型以及当前节点长度,相当于节点保存后一个元素的指针。
len:自身长度
entry-data :经过压缩后的数据
quciklist结构实现
其中节点实现
我们阅读结构体发现虽然是quicklist但却出现了很多关于ziplist的身影
首先ziplist的插入和删除 *** 作时间复杂度非常高(参考数组需要重新生成一个ziplist来作为更新后的list),当一个list非常大的且更新平凡就会带来非常大的开销。
所谓的quicklist就是把ziplist和普通的双向链表解和,每个双向节点保存一个ziplist,每个ziplist中存一批list数据,这样可以避免大量链表指针 *** 作带来的内存开销(即化整为零思想)
Redis对外暴露的list数据结构,其底层实现所依赖的内部数据结构就是quicklist。quicklist就是一个块状的双向压缩链表。
考虑到双向链表在保存大量数据时需要更多额外内存保存指针并容易产生大量内存碎片,以及ziplist的插入删除的高时间复杂度,两个数据结构的缺陷会导致在数据量很大或插入删除 *** 作频繁的极端情况时,性能极其低下。
Redis为了避免数据结构在极端情况下的低性能,将双向链表和ziplist综合起来,成为了较双向链表及ziplist性能更加稳定的quicklist
1压缩列表在查找和更新的时间复杂度方面没有很大的优势,为什么redis要把他作为底层数据结构
list底层使用压缩列表本质上是将所有元素紧挨着存储,能节省空间避免内存碎片(内存空间不是硬盘空间是很昂贵的)
有序列表查找元素,只能遍历查找,于是就出现了跳表
skiplist节点结构体
也就是说跳表在链表的基础上增加了多级索引,通过索引位置的几个跳转,实现数据的快速定位
其中索引可以持续累加
整数数组是集合的底层实现之一,当一个集合只包含整数元素且数量不多,就会用该方式实现
2集合数据的 *** 作效率
以上就是关于redis里面的数据怎么查看全部的内容,包括:redis里面的数据怎么查看、如何在Redis通过StackExchange.Redis 存储集合类型List、python *** 作redis list等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)