Redis的key虽然可以自定义,但最好遵循以下几个最佳实践约定:
优点:
BigKey通常以Key的大小和Key中成员的数量来综合判定,例如:
推荐值:
bigkey的危害
如何发现bigkey
略
这里使用redisTemplate,jedis也有pipeline操作,不做展示
SessionCallback & RedisCallback :在同一条连接下执行多个Redis命令。
RedisCallback
需要处理底层的转换规则,如果不考虑改写底层,尽量不使用
redisTemplate.execute(new RedisCallback() {
@Override
public Object doInRedis(RedisConnection redisConnection) throws DataAccessException {
redisConnection.set("key1".getBytes(), "value1".getBytes());
redisConnection.hSet("hash1".getBytes(), "field".getBytes(), "test".getBytes());
return null;
}
});
SessionCallback
高级接口,支持事务
redisTemplate.execute(new SessionCallback() {
@Override
public Object execute(RedisOperations redisOperations) throws DataAccessException {
redisOperations.opsForValue().set("key2", "value2");
redisOperations.opsForHash().put("hash2", "field", "test");
return null;
}
});
如MSET或Pipeline这样的批处理需要在一次请求中携带多条命令,而此时如果Redis是一个集群,那批处理命令的多个key必须落在一个插槽中,否则就会导致执行失败。原因是,redis集群定义了16384个插槽,不同key的slot不同,如果使用传统批处理,批处理中的命令会落在不同的节点,导致批处理失去意义。
故解决问题,需要避免服务端计算slot,由客户端计算slot,实现批处理
而springRedisTemplate实现的集群下的批处理操作正是采用并行slot,推荐使用
stringRedisTemplate.opsForValue( ).multiSet() ;
Redis的持久化虽然可以保证数据安全,但也会带来很多额外的开销,因此持久化请遵循下列建议:
用来做缓存的Redis实例尽量不要开启持久化功能
建议关闭RDB持久化功能,使用AOF持久化
利用脚本定期在slave节点做RDB,实现数据备份
设置合理的rewrite阈值,避免频繁的bgrewrite
当RDB与AOF都在进行io操作时,或者redis进行了AOF的rewrite,可能引起AOF的io阻塞,导致主线程阻塞,因此应配置no-appendfsync-on-rewrite = yes,禁止在rewrite期间做aof,避免因AOF引起的阻塞
在redis执行时耗时超过某个阈值的命令,成为慢查询
慢查询的阈值可以通过配置指定:
为了避免这样的漏洞,这里给出一些建议:
内存缓冲区常见的有三种:
为了保证高可用特性,这里建议将cluster-require-full-coverage配置为false
#当此配置开启时,当集群中有一个插槽不可用(如集群某个节点宕机),那整个集群将不可用
cluster-require-full-coverage yes
集群节点之间会不断的互相Ping来确定集群中其它节点的状态。每次Ping携带的信息至少包括:
集群中节点越多,集群状态信息数据量也越大,10个节点的相关信息可能达到1kb,此时每次集群互通需要的带宽会非常高。
集群虽然具备高可用特性,能实现自动故障恢复,但是如果使用不当,也会存在一些问题:
单体Redis(主从Redis)已经能达到万级别的QPS,并且也具备很强的高可用特性。如果主从能满足业务需求的情况下,尽量不搭建Redis集群
在集群下,它会将数据自动分布到不同的节点(虚拟的16384个slot)
它数据的路由分发,是通过计算key,所以只要key一样,则一定会被分到同一个slot
上面的参数keys的个数为1,肯定存储在一个slot里面,
但是如果是多个key且不存在同一个slot里面则会报错,
redis.clients.jedis.exceptions.JedisDataException: ERR 'EVAL' command keys must in same slot**
解决方案:
设置hashtag,在设置key的时候使用{xxxxx}的方式可以将该数据存在用一个slot里面,
但是,注意如果同一个slot里面的数据过多且同时操作查询频繁的数据就会影响到效率问题(数据倾斜)