Redis在大数据中的使用技巧
今天将会跟大家讨论一些Redis在大数据中的使用,包括一些Redis的使用技巧和其他的一些内容。
一、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,具体的我都在代码中进行了注释,大家可以看下:
小经验分享:
数据库中不合法的时间处理:判断时间中的年份是否大于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不到***,性能没法提升了,说明代码有问题。
虽然Redis大家会用,但是我们可能平时不会有像这样的大数据使用场景。希望本文能够给大家一些值得借鉴的经验。
扫一扫,关注我们