百亿数据量下,掌握这些Redis技巧你大概就稳住了全场

1、Redis封装架构讲解程序员

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

这里能够打开看一下,NewLife.Core里面有一个NewLife.Caching的命名空间,里面有一个Redis类,里面实现了Redis的基本功能;另外一个类是RedisClient是Redis的客户端。数据库

Redis的核心功能就是有这两个类实现,RedisClient表明着Redis客户端对服务器的一个链接。Redis真正使用的时候有一个Redis链接池,里面存放着不少个RedisClient对象。json

因此咱们Redis的封装有两层,一层是NewLife.Core里面的Redis以及RedisClient;另外一层就是NewLife.Redis。这里面的FullRedis是对Redis的实现了Redis的全部的高级功能。缓存

这里你也能够认为NewLife.Redis是Redis的一个扩展。性能优化

2、Test实例讲解Redis的基本使用服务器

一、实例网络

打开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移除。

二、压力测试

接下来看第四个例子,咱们直接作压力测试,代码以下:

运行的结果以下图所示:

测试就是进行get,set remove,累加等的操做。你们能够看到在我本机上轻轻松松的到了六十万,多线程的时候甚至到了一百多万。

为何会达到这么高的Ops呢?下面给你们说一下:

Bench会分根据线程数分多组进行添删改压力测试;

rand参数,是否随机产生key/value;

batch批大小,分批执行读写操做,借助GetAll/SetAll进行优化。

三、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分布式锁的关键。

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

在项目的Readme中,这里摘录下:

一、特性

在ZTO大数据实时计算普遍应用,200多个Redis实例稳定工做一年多,天天处理近1亿包裹数据,日均调用量80亿次;

低延迟,Get/Set操做平均耗时200~600us(含往返网络通讯);

大吞吐,自带链接池,最大支持1000并发;

高性能,支持二进制序列化(默认用的json,json很低效,转成二进制性能会提高不少)。

二、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以上空间一年多稳定工做的经验,并按照重要程度排了前后顺序,可根据场景须要酌情采用。

三、缓存Redis的兄弟姐妹

Redis实现ICache接口,它的孪生兄弟MemoryCache,内存缓存,千万级吞吐率。

各应用强烈建议使用ICache接口编码设计,小数据时使用MemoryCache实现;数据增大(10万)之后,改用Redis实现,不须要修改业务代码。

4、关于一些疑问的回复

这一Part咱们会来聊聊大数据中Redis使用的经验:

Q1:一条数据多个key怎么设置比较合理?

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

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

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

Q3:存放多个字段的类性能同样吗?

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

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

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

Q5:CPU为什么暴涨?

A5:程序员终极理念——CPU达到百分百,而后性能达到最优,尽可能不要浪费。最痛恨的是——若是CPU不到百分百,性能无法提高了,说明代码有问题。

虽然Redis你们会用,可是咱们可能平时不会有像这样的大数据使用场景。但愿本文可以给你们一些值得借鉴的经验。

最后给你们推荐一个Java架构学习交流群:698581634,进群便可免费获取Java架构学习资料:里面有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化这些成为架构师必备的知识体系,群里必定有你须要的资料,你们赶忙加群吧。