APP下载
报价宝  ›  科技  › 

Redis基本使用及百亿资料量中的使用技巧分享

报价宝 来源:baojiabao.com 发布时间:2019-11-05 16:02:00 11月14日更新
报价宝综合消息Redis基本使用及百亿资料量中的使用技巧分享

作者:依乐祝

原文:https://www.cnblogs.com/yilezhu/p/9941208.html

今天将会跟大家讨论一些Redis在大资料中的使用,包括一些Redis的使用技巧和其他的一些内容。

首先给大家个地址:

https://github.com/NewLifeX/NewLife.Redis

源代码以及例项都在里面,当然今天的内容也是按照里面的例项来进行的,大家可以先进行下载。

这里也附上Redis的下载地址:

windows:

https://github.com/MicrosoftArchive/redis/releases

http://x.newlifex.com/Redis-x64-3.2.100.msi

Linux:

https://redis.io/download

一、Redis封装架构讲解

实际上NewLife.Redis是一个完整的Redis协议功能的实现,但是Redis的核心功能并没有在这里面,而是在NewLife.Core里面。

这里可以开启看一下,NewLife.Core里面有一个NewLife.Caching的名称空间,里面有一个Redis类,里面实现了Redis的基本功能;另一个类是RedisClient是Redis的客户端。

Redis的核心功能就是有这两个类实现,RedisClient代表着Redis客户端对服务器的一个连线。Redis真正使用的时候有一个Redis连线池,里面存放着很多个RedisClient物件。

所以我们Redis的封装有两层,一层是NewLife.Core里面的Redis以及RedisClient;另一层就是NewLife.Redis。这里面的FullRedis是对Redis的实现了Redis的所有的高阶功能。

这里你也可以认为NewLife.Redis是Redis的一个扩充套件。

二、Test例项讲解Redis的基本使用

1、例项

开启Program.cs看下程式码:

这里XTrace.UseConsole();是向控制台输出日志,方便除错使用检视结果。

接下来看第一个例子Test1,具体的我都在程式码中进行了注释,大家可以看下:

Set的时候,如果是字串或者字元资料的话,Redis会直接储存起来(字串内部机制也是储存二进位制),如果是其他型别,会预设进行json序列化然后再储存起来。Get的时候,如果是字串或者字元资料会直接获取,如果是其他型别会进行json反序列化。Set第三个引数过期时间单位是秒。vs除错小技巧,按F5或者直接工具栏“启动”会编译整个解决方案会很慢(VS预设),可以选中专案然后右键选单选择除错->启动新例项,会只编译将会用到的专案,这样对除错来说会快很多。大家执行除错后可以看到控制台输出的内容:向右的箭头=》是ic.Log=XTrace.Log输出的日志。

字典的使用:物件的话,需要把json全部取出来,然后转换成物件,而字典的话,就可以直接取某个字段。伫列是List结构实现的,上游资料太多,下游处理不过来的时候,就可以使用这个伫列。上游的资料发到伫列,然后下游慢慢的消费。另一个应用,跨语言的协同工作,比方说其他语言实现的程式往伫列里面塞资料,然后另一种语言来进行消费处理。这种方式类似MQ的概念,虽然有点low,但是也很好用。集合,用的比较多的是用在一个需要精确判断的去重功能。像我们每天有三千万订单,这三千万订单可以有重复。这时候我想统计下一共有订单,这时候直接数据库group by是不大可能的,因为数据库中分了十几张表,这里分享个实战经验:比方说揽收,商家发货了,网点要把件收回来,但是收回来之前网点不知道自己有多少货,这时候我们做了一个功能,也就是订单会发送到我们公司来。我们会建一个time_site的key的集合,而且集合本身有去重的功能,而且我们可以很方便的通过set.Count功能来统计数量,当件被揽收以后,我们后台把这个件从集合中Remove掉。然后这个Set中存在的就是网点还没有揽收的件,这时候通过Count就会知道这个网点今天还有多少件没有揽收。实际使用中这个数量比较大,因为有几万个网点。Redis中布隆过滤器,去重的,面试的时候问的比较多。

小经验分享:

数据库中不合法的时间处理:判断时间中的年份是否大于2000年,如果小于2000就认为不合法;习惯大于小于号不习惯用等于号,这样可以处理很多意外的资料;Set的时候最好指定过期时间,防止有些需要删除的资料我们忘记删了;Redis异步尽量不用,因为Redis延迟本身很小,大概在100us-200us,再一个就是Redis本身是单执行绪的,异步任务切换的耗时比网络耗时还要大;List用法:物联网中资料上传,量比较大时,我们可以把这些资料先放在Redis的List中,比如说一秒钟1万条,然后再批量取出来然后批量插入数据库中。这时候要设定好key,可以字首+时间,对已处理的List可以进行remove移除。

2、压力测试

接下来看第四个例子,我们直接做压力测试,程式码如下:

执行的结果如下图所示:

测试就是进行get,set remove,累加等的操作。大家可以看到在我本机上轻轻松松的到了六十万,多执行绪的时候甚至到了一百多万。

为什么会达到这么高的Ops呢?下面给大家说一下:

Bench会分根据执行绪数分多组进行添删改压力测试;rand引数,是否随机产生key/value;batch批大小,分批执行读写操作,借助GetAll/SetAll进行优化。

3、Redis中NB的函式来提升效能

上面的操作如果大家都掌握了就基本算Redis入门了,接下来进行进阶。如果能全然吃透,差不多就会比别人更胜一筹了。

GetAll()与SetAll()

GetAll:比方说我要取十个key,这个时候可以用getall。这时候Redis就执行了一次命令。比方说我要取10个key那么用get的话要取10次,如果用getall的话要用1次。1次getall时间大概是get的一点几倍,但是10次get的话就是10倍的时间,这个账你应该会算吧?强烈推荐大家用getall。

setall跟getall相似,批量设定K-V。

setall与getall效能很恐怖,官方公布的Ops也就10万左右,为什么我们的测试轻轻松松到五十万甚至上百万?因为我们就用了setall,getall。如果get,set两次以上,建议用getall,setall。

Redis管道Pipeline

比如执行10次命令会打包成一个包集体发过去执行,这里实现的方式是StartPipeline()开始,StopPipeline()结束中间的程式码就会以管道的形式执行。

这里推荐使用更强的武器,AutoPipeline自动管道属性。管道操作到一定数量时,自动提交,预设0。使用了AutoPipeline,就不需要StartPipeline,StopPipeline指定管道的开始结束了。

Add与Replace

Add:Redis中没有这个Key就新增,有了就不要新增,返回false;Replace:有则替换,还会返回原来的值,没有则不进行操作。

Add跟Replace就是实现Redis分散式锁的关键。

三、Redis使用技巧,经验分享

在专案的Readme中,这里摘录下:

1、特性

在ZTO大资料实时计算广泛应用,200多个Redis例项稳定工作一年多,每天处理近1亿包裹资料,日均呼叫量80亿次;低延迟,Get/Set操作平均耗时200~600us(含往返网络通讯);大吞吐,自带连线池,最大支援1000并发;高效能,支援二进位制序列化(预设用的json,json很低效,转成二进位制效能会提升很多)。

2、Redis经验分享

在Linux上多例项部署,例项个数等于处理器个数,各例项最大内存直接为本机实体内存,避免单个例项内存撑爆(比方说8核心处理器,那么就部署8个例项)。把海量资料(10亿+)根据key杂凑(Crc16/Crc32)存放在多个例项上,读写效能成倍增长。采用二进位制序列化,而非常见的Json序列化。合理设计每一对Key的Value大小,包括但不限于使用批量获取,原则是让每次网络包控制在1.4k字节附近,减少通讯次数(实际经验几十k,几百k也是没问题的)。Redis客户端的Get/Set操作平均耗时200~600us(含往返网络通讯),以此为参考评估网络环境和Redis客户端元件(达不到就看一下网络,序列化方式等等)。使用管道Pipeline合并一批命令。Redis的主要效能瓶颈是序列化、网络带宽和内存大小,滥用时处理器也会达到瓶颈。其它可查优化技巧。

以上经验,源自于300多个例项4T以上空间一年多稳定工作的经验,并按照重要程度排了先后顺序,可根据场景需要酌情采用。

3、快取Redis的兄弟姐妹

Redis实现ICache界面,它的孪生兄弟MemoryCache,内存快取,千万级吞吐率。

各应用强烈建议使用ICache界面编码设计,小资料时使用MemoryCache实现;资料增大(10万)以后,改用Redis实现,不需要修改业务程式码。

四、关于一些疑问的回复

这一Part我们会来聊聊大资料中Redis使用的经验:

Q1:一条资料多个key怎么设定比较合理?

A1:如果对效能要求不是很高直接用json序列化实体就好,没必要使用字典进行储存。

Q2:伫列跟List有什么区别?左进右出的话用List还是用伫列比较好?

A2:伫列其实就是用List实现的,也是基于List封装的。左进右出的话直接伫列就好。Redis的List结构比较有意思,既可以左进右出,也能右进左出。所以它既可以实现列表结构,也能伫列,还能实现栈。

Q3:存放多个字段的类效能一样吗?

A3:大部分场景都不会有偏差,可能对于大公司资料量比较大的场景会有些偏差。

Q4:大资料写入到数据库之后,比如资料到亿以上的时候,统计分析、查询这块,能不能分享些经验。

A4:分表分库,拆分到一千万以内。

Q5:CPU为何暴涨?

A5:程序员终极理念——CPU达到百分百,然后效能达到最优,尽量不要浪费。最痛恨的是——如果CPU不到百分百,效能没法提升了,说明程式码有问题。

文章标签: 报价宝 降噪耳机价格 耳机价格 红米手机价格 华为手机价格 小米手机价格 电视机价格 笔记本电脑价格 笔记本价格 汽车价格 数码相机价格 手机价格 笔记本电脑价格 电视机价格 华为手机价格