导航:首页 > 净水问答 > redis如何实现商品过滤

redis如何实现商品过滤

发布时间:2023-04-17 16:28:35

❶ redis布隆过滤器数据存到那

redis布隆过滤器数据存到那查询数据库一定不存在的数据,那么此类的圆旦查询一般恶意的查询,缓存一不存在该类数据,大量的查询会导致数据库负荷

缓存击穿
针对某个热点数据访问量极高,某个时点热点数据缓存失效,就会导致大量的请求查询数据

缓存歼指雪崩
某个时间点缓存集体失效

不同的问题有不同的解决方案,针对缓存穿透,普遍的解决方案是采用布隆过滤器

什么是布隆过滤器
布隆过滤器,由一串很长的二进制向量组成,可以看作二进制数组,里面存的值 0 或者 1 ,实现的原理,当向数据库添加数据时,通过多个 hash 函数,计算

出不同的值,在二进制数组中对应的未知将值置为 1 ,以此类推

如何判断数据是否存在
通过添加的hash 函数再次计算值橘改扰对应的位置,判断这些位置中的值是否存在 0 (注意:这里判断不是全为1 )

如果存在至少一个0 ,则数据一定不存在于数据库

如果全部的值为 1 ,则无法判断数据是否存在

由于布隆过滤器的存储特性,当数据被删除时,无法重置对应位置的值为0(多个数据互相影响)

Redis 实现布隆过滤器 bigmaps
计算机底层存储的基础单位是字节,一个字节8位,将

❷ 数据需要按条件筛选 怎么设计redis缓存数据表

应用Redis实现数据的读写,同时利用队列处理器定时将数据写入mysql。同并物键时要注意避免冲突,在redis启动时去mysql读取所有表键值存入redis中,往redis写数据时,对redis主键自增并蚂隐进行读取,若mysql更新失败,则需要及时清除缓存及同步redis主键。这样处理,主要是实时读写redis,而mysql数据则通过队列异步处理,缓解mysql压力,不过这种方法应用场景主要基于高并发,而且redis的高可用集群架构相对更复杂绝巧,一般不是很推荐。

❸ Redis - 布隆过滤器

当一个元素加入布隆过滤器中的时候,会进行如下操作:

当我们需要判断一个元素是否存在于布隆过滤器的时候,会进行如下操作:

举个简单的例子:

查询某个变量的时候我们只要看看这些点是不是都是 1 就可以大概率知道集合中有没有它了

pom.xml引入依赖:

Guava 提供的布隆过滤器的实现还是很不错的(想要详细了解的可以看一下它的源码实现),仔橡但是它有一个重大的缺陷就是只能单机使用(另外,容量扩展也不容易),而现在互联网一般都是分布式的场景。为了解决这个问题,我们就需要用到 Redis 中的布隆过滤器了。

Redis v4.0 之猛戚锋后有了 Mole(模块/插件) 功能,Redis Moles 让 Redis 可以使用外部模块扩展其功能 。布隆过滤器就是其中的 Mole。详情可以查看 Redis 官方对 Redis Moles 的介绍 : https://redis.io/moles。
在已安装 Redis 的前提下,安装 RedisBloom,有两种方式:

简单介绍一下每个参数的具体含义:
1. key:布隆过滤器的名称
2. error_rate :误报的期望概率。这应该是介枝晌于0到1之间的十进制值。例如,对于期望的误报率0.1%(1000中为1),error_rate应该设置为0.001。该数字越接近零,则每个项目的内存消耗越大,并且每个操作的CPU使用率越高。
3. capacity: 过滤器的容量。当实际存储的元素个数超过这个值之后,性能将开始下降。实际的降级将取决于超出限制的程度。随着过滤器元素数量呈指数增长,性能将线性下降。

可选参数:
1. expansion:如果创建了一个新的子过滤器,则其大小将是当前过滤器的大小乘以expansion。默认扩展值为2。这意味着每个后续子过滤器将是前一个子过滤器的两倍。

————————————————————
坐标帝都,白天上班族,晚上是知识的分享者
如果读完觉得有收获的话,欢迎点赞加关注

❹ 搜索引擎 Redisearch 入门实战

简介

Redisearch在Redis上面实现了一个搜索引擎,但与其他Redis搜索库不同,它不使用内部数据结构,如排序集。
这也可以实现更高级的功能,如文本查询的完全词组匹配和数字过滤,这对传统的redis搜索几乎是不可能或高效的。

本机 Mac
服务器 CentOS 7.3

1、安装 Redis, 最新版本 ->

2、配置 Redis,编辑 redis.conf,修改渣派三处

3、安装 Redisearch,在 redis-4.0.1 同级目录下执行, 官网 ->隐梁州

4、启动 Redis

1、使用 Maven 安装最新的 Jedis,方便依灶蔽赖

2、使用 Maven 安装最新的 JRedisearch,方便依赖

1、在 IDEA 中新建 Maven 工程,添加如下依赖

2、编写测试程序 Application.java

3、执行结果

速度快,但是对中文搜索支持不好,如上所示,搜索“视频”时,field4中有“视频项目”却没有出现在结果中,需要将“视频项目”隔开成“视频 项目”才行。

❺ Redis的内存优化

一. redisObject对象
二. 缩减键值对象
三. 共享对象池
四. 字符串优化
五. 编码优化
六. 控制key的数量

Redis存储的所有值对象在内部定义为redisObject结构体,内部结构如下图所示。

表示当前对象使用的数据类型,Redis主要支持5种数据类型:string,hash,list,set,zset。可以使用type {key}命令查纯茄答看对象所属类型,type命令返回的是值对象类型,键都是string类型。

表示Redis内部编码类型,encoding在Redis内部使用,代表当前对象内部采用哪种数据结构实现。理解Redis内部编码方式对于优化内存非常重要 ,同一个对象采用不同的编码实现内存占用存在明显差异,具体细节见之后编码优化部分。

记录对象最后一次被访问的时间,当配置了 maxmemory和maxmemory-policy=volatile-lru | allkeys-lru 时, 用于辅助LRU算法删除键数据。可以使用object idletime {key}命令在不更新lru字段情况下查看当前键的空闲时间。

记录当前对象被引用的次数,用于通过引用次数回收内存,当refcount=0时,可以安全回收当前对象空间。使用object refcount {key}获取当前对象引用。当对象为整数且范围在[0-9999]时,Redis可以使用共享对象的方式来节省内存。具体细节见之后共享对象池部分。

与对象的数据内容相关,如果是整数直接存储数据,否则表示指向数据的指针。Redis在3.0之后对值对象是字符纳烂串且长度<=39字节的数据,内部编码为embstr类型,字符串sds和redisObject一起分配,从而只要一次内存操作。

降低Redis内存使用最直接的方式就是缩减键(key)和值(value)的长度。

其中java-built-in-serializer表示JAVA内置序列化方式,更多数据见jvm-serializers项目: https://github.com/eishay/jvm-serializers/wiki,其它语言也有各自对应的高效序列化工具。

值对象除了存储二进制数据之外,通常还会使用通用格式存储数据比如:json,xml等作为字符串存储在Redis中。这种方式优点是方便调试和跨语言,但是同样的数据相比字节数组所需的空间更大,在内存紧张的情况下,可以使用通用压缩算法压缩json,xml后再存入Redis,从而降低内存占用,例如使用GZIP压缩后的json可降低约60%的空间。

对象共享池指Redis内部维护[0-9999]的整数对象池。创建大量的整数类型redisObject存在内存开销,每个redisObject内部结构至少占16字节,甚至超过了整数自身空间消耗。所以Redis内存维护一个[0-9999]的整数对象池,用于节约内存。 除了整数值对象,其他类型如list,hash,set,zset内部元素也可以使用整数对象池。因此开发中在满足需求的前提下,尽量使用整数对象以节省内存。
整数对象池在Redis中通过变量REDIS_SHARED_INTEGERS定义,不能通过配置修改。可以通过object refcount 命令查看对象引用数验证是否启用整数对象池技术,如下:

设置键foo等于100时,直接使用共享池内整数对象,因此引用数是2,再设置键bar等于100时,引用数又变为3,如下图所示。

使用整数对象池究竟做慧能降低多少内存?让我们通过测试来对比对象池的内存优化效果,如下表所示。

使用共享对象池后,相同的数据内存使用降低30%以上。可见当数据大量使用[0-9999]的整数时,共享对象池可以节约大量内存。需要注意的是对象池并不是只要存储[0-9999]的整数就可以工作。当设置maxmemory并启用LRU相关淘汰策略如:volatile-lru,allkeys-lru时,Redis禁止使用共享对象池,测试命令如下:

LRU算法需要获取对象最后被访问时间,以便淘汰最长未访问数据,每个对象最后访问时间存储在redisObject对象的lru字段。对象共享意味着多个引用共享同一个redisObject,这时lru字段也会被共享,导致无法获取每个对象的最后访问时间。如果没有设置maxmemory,直到内存被用尽Redis也不会触发内存回收,所以共享对象池可以正常工作。

综上所述,共享对象池与maxmemory+LRU策略冲突,使用时需要注意。 对于ziplist编码的值对象,即使内部数据为整数也无法使用共享对象池,因为ziplist使用压缩且内存连续的结构,对象共享判断成本过高,ziplist编码细节后面内容详细说明。

首先整数对象池复用的几率最大,其次对象共享的一个关键操作就是判断相等性,Redis之所以只有整数对象池,是因为整数比较算法时间复杂度为O(1),只保留一万个整数为了防止对象池浪费。如果是字符串判断相等性,时间复杂度变为O(n),特别是长字符串更消耗性能(浮点数在Redis内部使用字符串存储)。对于更复杂的数据结构如hash,list等,相等性判断需要O(n2)。对于单线程的Redis来说,这样的开销显然不合理,因此Redis只保留整数共享对象池。

字符串对象是Redis内部最常用的数据类型。所有的键都是字符串类型, 值对象数据除了整数之外都使用字符串存储。比如执行命令:lpush cache:type “redis” “memcache” “tair” “levelDB” ,Redis首先创建”cache:type”键字符串,然后创建链表对象,链表对象内再包含四个字符串对象,排除Redis内部用到的字符串对象之外至少创建5个字符串对象。可见字符串对象在Redis内部使用非常广泛,因此深刻理解Redis字符串对于内存优化非常有帮助:

Redis没有采用原生C语言的字符串类型而是自己实现了字符串结构,内部简单动态字符串(simple dynamic string),简称SDS。结构下图所示。

Redis自身实现的字符串结构有如下特点:

因为字符串(SDS)存在预分配机制,日常开发中要小心预分配带来的内存浪费,例如下表的测试用例。

从测试数据可以看出,同样的数据追加后内存消耗非常严重,下面我们结合图来分析这一现象。阶段1每个字符串对象空间占用如下图所示。

阶段1插入新的字符串后,free字段保留空间为0,总占用空间=实际占用空间+1字节,最后1字节保存‘\0’标示结尾,这里忽略int类型len和free字段消耗的8字节。在阶段1原有字符串上追加60字节数据空间占用如下图所示。

追加操作后字符串对象预分配了一倍容量作为预留空间,而且大量追加操作需要内存重新分配,造成内存碎片率(mem_fragmentation_ratio)上升。直接插入与阶段2相同数据的空间占用,如下图所示。

阶段3直接插入同等数据后,相比阶段2节省了每个字符串对象预分配的空间,同时降低了碎片率。
字符串之所以采用预分配的方式是防止修改操作需要不断重分配内存和字节数据拷贝。但同样也会造成内存的浪费。字符串预分配每次并不都是翻倍扩容,空间预分配规则如下:

字符串重构:指不一定把每份数据作为字符串整体存储,像json这样的数据可以使用hash结构,使用二级结构存储也能帮我们节省内存。同时可以使用hmget,hmset命令支持字段的部分读取修改,而不用每次整体存取。例如下面的json数据:

分别使用字符串和hash结构测试内存表现,如下表所示。

根据测试结构,第一次默认配置下使用hash类型,内存消耗不但没有降低反而比字符串存储多出2倍,而调整hash-max-ziplist-value=66之后内存降低为535.60M。因为json的videoAlbumPic属性长度是65,而hash-max-ziplist-value默认值是64,Redis采用hashtable编码方式,反而消耗了大量内存。调整配置后hash类型内部编码方式变为ziplist,相比字符串更省内存且支持属性的部分操作。下一节将具体介绍ziplist编码优化细节。

Redis对外提供了string,list,hash,set,zet等类型,但是Redis内部针对不同类型存在编码的概念,所谓编码就是具体使用哪种底层数据结构来实现。编码不同将直接影响数据的内存占用和读写效率。使用object encoding {key}命令获取编码类型。如下:

Redis针对每种数据类型(type)可以采用至少两种编码方式来实现,下表表示type和encoding的对应关系。

了解编码和类型对应关系之后,我们不禁疑惑Redis为什么需要对一种数据结构实现多种编码方式?
主要原因是Redis作者想通过不同编码实现效率和空间的平衡。比如当我们的存储只有10个元素的列表,当使用双向链表数据结构时,必然需要维护大量的内部字段如每个元素需要:前置指针,后置指针,数据指针等,造成空间浪费,如果采用连续内存结构的压缩列表(ziplist),将会节省大量内存,而由于数据长度较小,存取操作时间复杂度即使为O(n2)性能也可满足需求。

Redis内存优化

编码类型转换在Redis写入数据时自动完成,这个转换过程是不可逆的,转换规则只能从小内存编码向大内存编码转换。例如:

以上命令体现了list类型编码的转换过程,其中Redis之所以不支持编码回退,主要是数据增删频繁时,数据向压缩编码转换非常消耗CPU,得不偿失。以上示例用到了list-max-ziplist-entries参数,这个参数用来决定列表长度在多少范围内使用ziplist编码。当然还有其它参数控制各种数据类型的编码,如下表所示:

掌握编码转换机制,对我们通过编码来优化内存使用非常有帮助。下面以hash类型为例,介绍编码转换的运行流程,如下图所示。

理解编码转换流程和相关配置之后,可以使用config set命令设置编码相关参数来满足使用压缩编码的条件。对于已经采用非压缩编码类型的数据如hashtable,linkedlist等,设置参数后即使数据满足压缩编码条件,Redis也不会做转换,需要重启Redis重新加载数据才能完成转换。

ziplist编码主要目的是为了节约内存,因此所有数据都是采用线性连续的内存结构。ziplist编码是应用范围最广的一种,可以分别作为hash、list、zset类型的底层数据结构实现。首先从ziplist编码结构开始分析,它的内部结构类似这样:<….>。一个ziplist可以包含多个entry(元素),每个entry保存具体的数据(整数或者字节数组),内部结构如下图所示。

ziplist结构字段含义:

根据以上对ziplist字段说明,可以分析出该数据结构特点如下:

下面通过测试展示ziplist编码在不同类型中内存和速度的表现,如下表所示。

测试数据采用100W个36字节数据,划分为1000个键,每个类型长度统一为1000。从测试结果可以看出:

intset编码是集合(set)类型编码的一种,内部表现为存储有序,不重复的整数集。当集合只包含整数且长度不超过set-max-intset-entries配置时被启用。执行以下命令查看intset表现:

以上命令可以看出intset对写入整数进行排序,通过O(log(n))时间复杂度实现查找和去重操作,intset编码结构如下图所示。

intset的字段结构含义:

根据以上测试结果发现intset表现非常好,同样的数据内存占用只有不到hashtable编码的十分之一。intset数据结构插入命令复杂度为O(n),查询命令为O(log(n)),由于整数占用空间非常小,所以在集合长度可控的基础上,写入命令执行速度也会非常快,因此当使用整数集合时尽量使用intset编码。上表测试第三行把ziplist-hash类型也放入其中,主要因为intset编码必须存储整数,当集合内保存非整数数据时,无法使用intset实现内存优化。这时可以使用ziplist-hash类型对象模拟集合类型,hash的field当作集合中的元素,value设置为1字节占位符即可。使用ziplist编码的hash类型依然比使用hashtable编码的集合节省大量内存。

当使用Redis存储大量数据时,通常会存在大量键,过多的键同样会消耗大量内存。Redis本质是一个数据结构服务器,它为我们提供多种数据结构,如hash,list,set,zset 等结构。使用Redis时不要进入一个误区,大量使用get/set这样的API,把Redis当成Memcached使用。对于存储相同的数据内容利用Redis的数据结构降低外层键的数量,也可以节省大量内存。如下图所示,通过在客户端预估键规模,把大量键分组映射到多个hash结构中降低键的数量。

hash结构降低键数量分析:

通过这个测试数据,可以说明:

关于hash键和field键的设计:

使用hash结构控制键的规模虽然可以大幅降低内存,但同样会带来问题,需要提前做好规避处理。如下:

本文主要讲解Redis内存优化技巧,Redis的数据特性是”ALL IN MEMORY”,优化内存将变得非常重要。对于内存优化建议读者先要掌握Redis内存存储的特性比如字符串,压缩编码,整数集合等,再根据数据规模和所用命令需求去调整,从而达到空间和效率的最佳平衡。建议使用Redis存储大量数据时,把内存优化环节加入到前期设计阶段,否则数据大幅增长后,开发人员需要面对重新优化内存所带来开发和数据迁移的双重成本。当Redis内存不足时,首先考虑的问题不是加机器做水平扩展,应该先尝试做内存优化。当遇到瓶颈时,再去考虑水平扩展。即使对于集群化方案,垂直层面优化也同样重要,避免不必要的资源浪费和集群化后的管理成本。

❻ Redis使用bitmap、zset、hash、list等结构完成骚操作

当同时满足以下条件时,使用ziplist编码:

SpringBoot—实现n秒内出现x个异常报警

思路:
借助Redis的zSet集合,score存储的是异常时的时间戳,获取一定时间范围内的set集合。判断set个数是否满足条件,若满足条件则触发报指清警;

注意点:

相关API:

Redis实现延迟队列方法介绍
基于Redis实现DelayQueue延迟队列设计方案

相关API:

SpringBoot2.x—使用Redis的bitmap实现布隆过滤器(Guava中BF算法)

布隆过滤器: 是专门用来检测集合中是否存在特定元素的数据结构。
存在误差率: 即将不在集合的元素误判在集合中。

所以布隆过滤器适合查询准确度要求没这么苛刻,但是对时间、空间效率比较高的场景。

实现方式:Redis实现布隆过滤器——借鉴Guava的BF算法:

SpringBoot2.x中使用Redis的bitmap结构(工具类)

注意:bitmap使用存在风险,若仅仅计算hash值,会导致bitmap占用空间过大。一般需要对简空hash值进行取余处理。

根据Redis是否存在key,判断锁是否被获取;

锁应该是一个对象,记录持有锁的线程信息、当前重入次数。所以应该使用Redis的Hash结构来存储锁对象。

3.1 网络波动造成释放锁失败怎么解决?

需要为锁加上超时时间;

3.2 任务未执行完毕时,锁由于超时时间被释放?

线程一旦加锁成功,可以启动一个后台线程,每隔多少秒检查一次,如果线程还持有锁,可以不断延长锁的生存时间。

主从切换时,从服务器上没有加锁信息,导致多个客户端同时加锁。

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命令

是对固定窗口计数器的优化,解决的是切换窗口两倍阈值流量的场景。

具体解决方案是:将限流窗口分为多个小的限流窗口,各个限流窗口分别计数。当前时间大于窗口最大时间时,将头部的小窗口数据舍弃,尾部新增小窗口来处理新请求。

优点:本质上是对固定窗口的优化

❼ redis布隆过滤器拆分长度

布隆过滤器是一种类似set的数据结构。

Redis布隆过滤器的基本使用

在Redis中,布隆过滤器有两个基本命令,分别是:

bf.add:添加元素到布隆过滤器中,类似于集合的sadd命令,不过bf.add命令只能一次添加一个元素,如果想一次添加多个元素,可以使用bf.madd命令。

bf.exists:判断某个元素是否在过滤器中,类似于集合的sismember命令,不过bf.exists命令只能一次查询一个元素,如果想一次查询多个元素,可以使用bf.mexists命令。

布隆过滤器的高级使用

上面的例子中使用的布隆过滤器只是默认参数的布隆过滤器,它在我们第一次使用 bf.add 命令时自动创建的。Redis还提供了自定义参数的布隆过滤器,想要尽量减少布隆过滤器的误判,就要设置合理的参数。
在使用 bf.add 命令添加元素之前,使用 bf.reserve 命令创建一个自定义的布隆过滤器。bf.reserve命令有三个参数,分别是:

key:键

error_rate:期望错误率,期望错误率越低,需要的空间就越大。

capacity:初始容量,当实际元素的数量超过这个初始化容量时,误判率上升。

如果对应的key已经存在时,在执行bf.reserve命令就会报错。如果不使用bf.reserve命令创建,而是使用Redis自动创建的布隆过滤器,默认的error_rate是0.01,capacity是 100。

布隆过滤器的 error_rate 越小,需要的存储空间就越大,对于不需要过于精确的场景,error_rate设置稍大一点也可以。布隆过滤器的capacity设置的过大,会浪费存储空间,设置的过小,就会影响准确率,所以在使用之前一定要尽可能地精确估计好元素数量,还需要加上一定的冗余空间以避免实际元素可能会意外高出设置值很多。总之,error_rate和 capacity都需要设置一个合适的数值。

❽ 借助Redis Bitmap实现简单的布隆过滤器

在之前的 一篇文章 中,我们已经深入理解了布隆过滤器的基本原理,并且了解到它在缓存系统中有较多的应用。Redis提供的Bitmap正好能够作为布隆过滤器所需要的位数组的基础,本文先简要介绍Bitmap,然后给出基于它的布隆过滤器实现。

Bitmap在Redis中并不是一个单独的数据类型,而是由字符串类型(Redis内部称Simple Dynamic String,SDS)之上定义的与比特相关的操作实现的,此时SDS就被当做位数组了。下面是在redis-cli中使用getbit和setbit指令的操作示例。

Redis的Bitmap是自动扩容的,亦即get/set到高位时,就会主动填充0。此外,还有bitcount指令用于计算特定字节范围内1的个数,bitop指令用来执行位运算(支持and、or、xor和not)。相应的用法可以查询Redis官方文档等。

下面我们基于Redis(Codis)实现布隆过滤器RedisBloomFilter。根据之前讲解布隆过滤器的文章,要初始化一个布隆过滤器的话,需要两个参数:预估的元素数量,以及可接受的最大误差(即假阳性率)。另外,我们也需要传入Jodis的连接池实例JedisResourcePool,以方便在Redis上操作。RedisBloomFilter类的成员和构造方法如下所示。

为了区分出布隆过滤器对应的Key,在原始Key的前面都加上"bf:"前缀。Bitmap长度bitmapLength和哈希函数个数numHashFunctions则利用Guava版实现中的方法来计算。

然后,我们需要计算一个元素被k个哈希函数散列后,对应到Bitmap的哪些比特上。这里仍然借鉴了Guava的BloomFilterStrategies实现,采用MurmurHash和双重哈希进行散列。为了应用简单,假设所有元素固定为字符串类型,不用泛型。

然后我们就可以通过Jedis的setbit()和getbit()方法来实现向布隆过滤器中插入元素与查询元素是否存在的逻辑了。一个元素会对应多个比特,为了提高效率,流水线就派上用场了。另外,setbit指令不会重置对应Key的过期时间戳。

完毕,写个简单的单元测试吧。假设现在用布隆过滤器来存储已读帖子的ID,Key中包含用户ID和时间。每天预估的每用户最大阅读量是3000篇,最大误差3%。

观察输出。

❾ Redis pipeline以及批量优化

Redis基于Request/Response 协议。通常情滚租况下一次请求的步骤如下

1 客户端通过tcp 协议发送指令到服务端,等待redis服务端返回结果

2 redis服务端执行命令,返回响应到客户端。

客户端发送请求到接受到服务端返回的响应被称为一次RTT(Round Trip Time). 在不考虑redis 服务端处理耗时的情况下,数据传输的耗时是最要的开销。且redis client 必须等待上一次响应结果才能发送下一个指令,会长时间处于阻塞的状态。

为解决提升reids服务端的吞吐量,redis提供了如下几种解决方案。

redis实现了HMGET/HMSET/MSET/MGET等一系列批量指令。区别与普通指大旦兆令如GET, MGET可以一次性发送key数组,然后redis服务端一次性返回结果数组。

很明显这种方式可以使用一次RTT处理完多个指令。这种方式的在性能上是最好的,缺点在于

1. 指令类型必须一致,批量指令依赖于Redis的实现,有些指令如setbit 没有批量实现的,就无法使用这种方案。

2. 不能混合指令发送,需要发送的指令必须在一次请求中确定。灵活性比pipeline差。

pipelining 是Request/迟敬Reponse协议的一种实现方式。客户端连续发送请求,而不用等待上一次的response返回。最终通过一次读取之前所有的Response。Redis服务支持这种实现方式。

我们通过redis-benchmark对比下普通cs模型和pipleline的性能。

从上面测试结果可以看出pipleline的性能远高于普通的请求方式。

1. pipeline的RTT交互次数,从而减少延迟,在网络延迟比较大的环境下。吞吐量提高会特别明显。

2. redis客户端/服务端减少了sys_call调用次数,减少了用户态到内核态的切换开销。

3. redis客户端发送无需等待上一次response请求结果,减少了阻塞时间。

Pipelining is not just a way in order to rece the latency cost e to the round trip time, it actually improves by a huge amount the total operations you can perform per second in a given Redis server. This is the result of the fact that, without using pipelining, serving each command is very cheap from the point of view of accessing the data structures and procing the reply, but it is very costly from the point of view of doing the socket I/O. This involves calling the read() and write() syscall, that means going from user land to kernel land. The context switch is a huge speed penalty.

Redis-Bloomfilter在1.0.0版本时,操作redis是基于标准的request/response模式, 但是Bloomfilter 在精度和预计插入数量大的情况,需要做多次hash操作。这样一次bloomfilter操作需要进行几十次redis setbit/getbit。这种情况下会严重影响Bloomfilter的吞吐量。由于setbit/getbit 不支持批量操作,所以采用pipeline来优化redis的性能开销。具体可以参考 https://github.com/ttting/redis-bloomfilter 的实现方式。 另外增加对于基于redistemplate的支持。

阅读全文

与redis如何实现商品过滤相关的资料

热点内容
谷物制蒸馏酒精饮料 浏览:871
如何降低电镀污水cod 浏览:357
日本净水机怎么使用 浏览:505
废水中铁含量标准 浏览:765
地底污水管风水怎么化解 浏览:987
如何提高环氧树脂固化物的耐热性 浏览:192
室外监控如何防水处理 浏览:21
一体化超滤膜成套设备价格 浏览:976
烟嘴过滤器堵了怎么办 浏览:372
污水处理加二氧化氯 浏览:877
滤芯上的标签如何清除 浏览:449
大众宝来6at变速箱滤芯在哪里 浏览:789
哈尔滨道外污水处理厂 浏览:115
含煤废水的主要成分 浏览:156
为什么污水井喷 浏览:617
广汽传祺为什么一万公里换汽油滤芯 浏览:857
万和净水器提示保养需要换什么 浏览:227
反渗透膜哪个品牌好 浏览:695
练焦工业废水设计回用规范 浏览:212
乙二醇是蒸馏水吗 浏览:320