天天看点

redis的这些使用规范,你知道吗?

redis是一款数据结构丰富,性能出色的缓存系统,广泛使用于各种软件服务中。加上redis提供了多种语言的sdk和简单易用的api,大大降低了redis学习和使用的门槛,即使对redis内部原理不甚了解,也能轻松使用,虽然redis好用,但是却不能乱用,它就像一把瑞士军刀一样,十分锋利,如果使用不当,却会"伤害"到自己。再加上redis是一个公共资源,自己的不当操作可能会"伤害"到同事。为了减少在使用redis过程中,由于使用不当,造成的不必要"伤害",这里笔者总结了一些,在日常开发中使用redis的一些规范。

redis使用规范主要分为以下三类:键值对使用规范,数据保存规范,redis命令使用规范。

一、键值对使用规范

1) 键命名规范

规范键的命名,只有命名规范,才能提供可读性强,可维护性好的key,方便日常的管理,针对不同的业务对key进行设置不同的前缀,对不同业务进行区分。防止不同业务使用了相同名称的键,导致数据的污染,产生不必要的业务损失。除此之外,前缀不宜过长,要注意key的长度,否则key很长的话,会消耗较多的空间,而且字符串的长度还会影响元数据的大小。

2)禁止使用bigValue

尽量不要让value值过大,这里的过大包含两方面的含义:

1.占用的空间大。例如一个string类型的value,占用空间大小是几十甚至上百MB。

2.包含众多元素的集合。

因为redis在处理数据的过程中,使用的是单线程,当处理的数据很大时,该数据的处理会消耗较多时间,进而阻塞的其他请求的处理。通常我们在使用string类型的数据时,可以将value的大小控制到10kb左右,使用集合的时候,元素的个数控制到1w以下。

但是,有时候因为业务场景的需要,string类型的数据需要存储一个占用空间很大的值,那么为了避免占用过多的空间,产生bigkey的现象,我们可以在将数据保存到redis前,对数据进行压缩,将压缩后的数据,在redis中进行保存,在查询这个数据时,将数据取出后,在进行解压缩。这种做法对于redis来说,感知不到bigkey的存在,也不再有bigkey的影响,只不过数据压缩、解压缩需要在业务端进行处理,增加了业务逻辑的复杂度。

而对于集合中需要保存大量元素的业务场景来说,我们可以在业务层的支持下,将大集合拆分成多个小集合,避免包含大量元素的集合出现。

3)数据序列化

使用高效的序列化工具来减小保存到redis中value的大小。不过序列化和反序列化的过程中,都会存在这样一个规律:序列化后的结果,占用的空间越小,序列化的过程就越耗时,序列化后的结果数据可读性就越差。所以市面上存在的多种序列化和反序列化工具,都是在权衡两者。因此在使用redis的过程中,选择何种序列化工具,要权衡占用的空间和序列化性能。并结合​业务场景进行选择。​

二、数据保存规范

1) 保存热点数据

redis的核心作用是用来加速数据的访问,但是缓存的存储容量是有限的,所以在保存数据时,尽量保存频繁访问的热点数据,不要把redis当成数据库使用。正所谓:"好钢用在刀刃上"。

2) 不同业务分实例保存

在使用分片集群时,尽量让不同的业务数据存储到不同实例上,减少不同业务之间的数据干扰和影响。避免因为某个业务数据量大,或者访问频繁,导致改业务数据所在redis实例负载过重,使在该实例上的其他业务,受到影响。除了业务间的相互影响,分实例存储业务数据,还可以避免某一个实例的内存空间被过多的占用,导致整个集群资源使用不均衡,产生数据倾斜。

3) 数据尽量设置过期时间 

对于redis来说,数据是存储在内存中的,内存资源相对来说是比较宝贵的,而且redis中保存的热点数据,也是有时效性的,所以在使用redis保存数据时,没有特殊情况的话,都要设置过期时间,只不过过期时间的长短取决于业务。防止业务上不在使用的数据,长时间滞留在缓存中,导致缓存资源的浪费。

4) 控制redis实例容量

redis单实例内存大小不要设置过大,过大的内存,无论是rdb快照,还是主从集群进行数据同步,都会耗费大量的时间,影响正常请求的处理。

三、redis命令使用规范

1) 线上禁用的部分命令

keys命令,对全局的哈希表进行全表扫描,返回满足匹配规则的所有key,如果redis中key比较多的话,会严重阻塞redis主线程。导致其他请求被阻塞,长时间得不到返回,影响其他业务请求的正常处理。对于keys,可以使用scan命令进行替换。

在主线程中删除redis实例上所有数据的操作,如果数量很大的话,也会严重阻塞主线程,使其他请求得不到及时处理。如果业务上的确有删除全部数据的需求,可以使用 flushall async让所有数据从引用树上摘除,然后将flushall操作封装成一个任务,放到任务队列里,然后由后台线程进行处理,而主线程所做的工作仅仅是将任务放到异步队列,然后立即返回。

和flushall删除数据类似的还有一个操作,就是flushdb。只不过flushdb 删除数据的范围相对相对小一些,flushall是删除整个redis实例中的数据,而flushdb是删除指定库中的数据,当库中的数据很多的时候,也会使主线程阻塞,flushdb的异步执行方案:flushdb async。

2) monitor命令

monitor命令的作用是启动一个进程,来检测redis server中执行的每个一个命令,并收集命令参数,执行耗时等信息,并将这些信息输出到控制台。通常在运维过程中,使用这个命令来查看当前命令的执行情况。该命令的具体执行过程是:redis server将执行命令的信息,发送的输出缓冲区中,然后monitor从这个缓冲区中将数据读取出来,输出到控制台。

redis的这些使用规范,你知道吗?

但是如果当前redis中请求比较频繁,而monitor命令无法及时的将缓存区中的数据取出,那么有可能导致输出缓冲区溢出,使整个redis实例宕机。这个命令风险性比较高,轻易不要使用。

3) 全量操作命令

全量操作命令,主要针对的是集合类型数据的操作,通常是获取集合中全量的数据,如果被查询的集合中数据元素特别多的话,那么这个全量命令的执行,就会阻塞redis主线程。

对于全量类型的操作,可以使用对应的scan命令,对于Hash类型的数据可以使用HSCAN命令,代替HGETALL。对于Set类型的数据可以使用SSCAN命令,代替SMEMBERS。

除了在命令上对全量操作的优化,还可以在业务层面来优化,采用化整为零的方式,将一个大集合拆分成多个小集合来存储,从根本上来避免,大集合的产生。

以上这些是在使用redis过程中的一些重要规范,也是一些使用redis过程中,容易踩坑的地方,希望对你有帮助。