Redis常见问题汇总

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: Redis常见问题汇总

问题1:懂Redis事务和Pipeline吗?

Redis中,如果一个事务被提交,那么事务中的所有操作将会被顺序执行,且在事务执行期间,其他client的操作将会被阻塞;Redis采取了这种简单而“粗鲁”的方式来确保事务的执行更加的快速和更少的外部干扰因素。

Redis Cluster集群架构,不同的key是有可能分配在不同的Redis节点上的,在这种情况下Redis的事务机制是不生效的。 Redis的事务功能较弱(不支持回滚),而且集群版本(自研和官方)要求一次事务操作的key必须在一个slot上(可以使用 hashtag 功能解决)

管道(pipeline)可以一次性发送多条命令并在执行完后一次性将结果返回,pipeline通过减少客户端与redis的通信次数来实现降低往返延时时间,而且Pipeline 实现的原理是队列,而队列的原理是时先进先出,这样就保证数据的顺序性Pipeline 的默认的同步的个数为53个,也就是说arges中累加到53条数据时会把数据提交

 

问题2:Redis的多数据库机制,了解多少?

Redis支持多个数据库,并且每个数据库的数据是隔离的不能共享,单机下的redis可以支持16个数据库(db0 ~ db15)

在Redis Cluster集群架构下只有一个数据库空间,即db0。因此,我们没有使用Redis的多数据库功能!

 

问题3:Redis集群机制中,你觉得有什么不足的地方吗?

Redis因为是要提升性能,所以直接采用的异步复制,当在Master上写入数据后直接返回,然后把数据快照广播给

Slave,让所有的Slaves去执行操作,数据通过异步复制,不保证数据的强一致性

假设有一个key,对应的value是Hash类型的。如果Hash对象非常大,是不支持映射到不同节点的!只能映射到集

群中的一个节点上!还有就是做批量操作比较麻烦!

问题4:懂Redis的批量操作么?

我们在生产上采用的是Redis Cluster集群架构,不同的key会划分到不同的slot中,因此直接使用mset或者mget等操作是行不通的。

 

问题5:那在Redis集群模式下,如何进行批量操作的优化?

redis引入cluster模式后,如果存在的节点异常多的时候,IO的代价已经超过数据传输,在这种情况下再增加节点已经没法再提高效率了。例如批量获取操作mget,RedisCluster将数据按key哈希到16384个slot上,每个redis node负责一部分的slot。mget需要执行的操作就是从redis node获取所有的key-value值,然后进行merge然后返回。

①串行命令:由于n个key是比较均匀地分布在Redis Cluster的各个节点上,因此无法使用mget命令一次性获取,所以通常来讲要获取n个key的值,最简单的方法就是逐次执行n个get命令,这种操作时间复杂度较高,它的操作时间=n次网络时间+n次命令时间,网络次数是n。很显然这种方案不是最优的,但是实现起来比较简单。

②串行IO:Redis Cluster使用CRC16算法计算出散列值,再取对16383的余数就可以算出slot值,同时Smart客户端会保存slot和节点的对应关系,有了这两个数据就可以将属于同一个节点的key进行归档,得到每个节点的key子列表,之后对每个节点执行mget或者Pipeline操作,它的操作时间=node次网络时间+n次命令时间,网络次数是node的个数,很明显这种方案比第一种要好很多,但是如果节点数太多,还是有一定的性能问题。

Map<String, String> serialIOMget (List<String> keys) {
        //结果集
        Map<String, String> keyValueMap = new HashMap<>();
        //属于各个节点的key列表,JedisPool要提供基于ip和port的hashcode方法
        Map<JedisPool, List<String>> nodeKeyListMap= new HashMap<>();
        //遍历所有的key
        for (String key : keys) {
            //使用CRC16本地计算每个key的slot
            int slot = JedisClusterCRC16.getSlot(key);
            //通过iediscluster本地slot->node映射获取slot对应的node
            JedisPool jedisPool = jedisCluster.getConnectionHandler().getJedisPoolFromSlot(slot);
            //归档
            if (nodeKeyListMap.containsKey(jedisPool)) {
                nodeKeyListMap.get(jedisPool).add(key);
            } else {
                List<String> list = new ArrayList<String>();
                list.add(key);
                nodeKeyListMap.put(jedisPool, list);
            }
        }
        //从每个节点上批量获取,这里使用mget也可以使用pipeline
        for (Map.Entry<JedisPool, List<String>> entry : nodeKeyListMap.entrySet()) {
            JedisPool jedisPool = entry.getKey();
            List<String> nodeKeyList = entry.getValue();
            //列表变为数组
            String[] nodeKeyArray = nodeKeyList.toArray(new String[nodeKeyList.size()]);
            //批量获取,可以使用mget或者Pipeline
            List<String> nodeValueList = jedisPool.getResource().mget(nodeKeyArray);
            //归档
            for (int i = 0; i < nodeKeyList.size(); i++) {
                keyValueMap.put(nodeKeyList.get(i), nodeValueList.get(i));
            }
        }
        return keyValueMap;
    }

串行IO

③并行IO:此方案是将方案2中的最后一步改为多线程执行,网络次数虽然还是节点个数,但由于使用多线程网络时间变为O(1),这种方案会增加编程的复杂度。

④hash_tag实现:Redis Cluster的hash_tag功能,它可以将多个key强制分配到一个节点上,它的操作时间=1次网络时间+n次命令时间。hashtag的解决方案:可以使用twitter的 twemproxy

四种批量操作解决方案对比

 

使用Redis Cluster时,pipelining、事务和LUA Script功能涉及的key必须在同一个数据分片上,否则将会返
回错误
。如要在Redis Cluster中使用上述功能,就必须通过hash tags来确保一个pipeline或一个事务中操作

的所有key都位于同一个Slot中。

有一些客户端(如Redisson)实现了集群化的pipelining操作,可以自动将一个pipeline里的命令按key所在的

分片进行分组,分别发到不同的分片上执行。但是Redis不支持跨分片的事务,事务和LUA Script还是必须遵循所

有key在一个分片上的规则要求。

 

问题6:你们有对Redis做读写分离么?

不做读写分离。我们用的是Redis Cluster的架构,是属于分片集群的架构。而Redis本身在内存上操作,不会涉及IO吞吐,即使读写分离也不会提升太多性能,Redis在生产上的主要问题是考虑容量,单机最多10-20G,key太多降低Redis性能.因此采用分片集群结构,已经能保证了我们的性能。其次,用上了读写分离后,还要考虑主从一致性,主从延迟等问题,徒增业务复杂度。

 

问题7:Redis 序列化方式有哪些?

当我们的数据存储到Redis的时候,我们的键(key)和值(value)都是通过Spring提供的Serializer序列化到数据库的。RedisTemplate默认使用的是JdkSerializationRedisSerializer,StringRedisTemplate默认使用的是StringRedisSerializer

Spring Data JPA为我们提供了下面的Serializer:GenericToStringSerializer、Jackson2JsonRedisSerializer、JacksonJsonRedisSerializer、JdkSerializationRedisSerializer、OxmSerializer、StringRedisSerializer。

序列化方式对比:

JdkSerializationRedisSerializer: 使用JDK提供的序列化功能。 优点是反序列化时不需要提供类型信息(class),但缺点是需要实现Serializable接口,还有序列化后的结果非常庞大,是JSON格式的5倍左右,这样就会消耗redis服务器的大量内存。

Jackson2JsonRedisSerializer: 使用Jackson库将对象序列化为JSON字符串。优点是速度快,序列化后的字符串短小精悍,不需要实现Serializable接口。但缺点也非常致命,那就是此类的构造函数中有一个类型参数,必须提供要序列化对象的类型信息(.class对象)。 通过查看源代码,发现其只在反序列化过程中用到了类型信息。

 

问题8:Redis 如何做异步队列?

一般使用list结构作为队列,rpush生产消息,lpop消费消息。当lpop没有消息的时候,要适当sleep一会再重试。

如果不用sleep呢?list还有个指令叫blpop,在没有消息的时候,它会阻塞住直到消息到来。

能不能生产一次消费多次呢?

使用pub/sub主题订阅者模式,可以实现1:N的消息队列。pub/sub有什么缺点?在消费者下线的情况下,生产的消息会丢失,得使用专业的消息队列如rabbitmq等。

redis如何实现延时队列?使用sortedset,拿时间戳作为score,消息内容作为key调用zadd来生产消息,消费者用zrangebyscore指令获取N秒之前的数据轮询进行处理

 


相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
6月前
|
NoSQL 关系型数据库 Redis
DMS产品常见问题之dms登录redis实例时报错如何解决
DMS(数据管理服务,Data Management Service)是阿里云提供的一种数据库管理和维护工具,它支持数据的查询、编辑、分析及安全管控;本汇总集中了DMS产品在实际使用中用户常遇到的问题及其相应的解答,目的是为使用者提供快速参考,帮助他们有效地解决在数据管理过程中所面临的挑战。
|
4月前
|
存储 缓存 NoSQL
Redis 缓存常见问题
Redis 缓存常见问题
52 3
|
6月前
|
Cloud Native NoSQL 数据管理
Serverless 应用引擎常见问题之首次启动获取不到redis连接如何解决
Serverless 应用引擎(Serverless Application Engine, SAE)是一种完全托管的应用平台,它允许开发者无需管理服务器即可构建和部署应用。以下是Serverless 应用引擎使用过程中的一些常见问题及其答案的汇总:
Serverless 应用引擎常见问题之首次启动获取不到redis连接如何解决
|
6月前
|
存储 缓存 NoSQL
Redis 常见问题解决方案
Redis 常见问题解决方案
43 0
|
6月前
|
缓存 NoSQL 关系型数据库
Redis系列-7.Redis缓存常见问题之预热、雪崩、击穿、穿透
Redis系列-7.Redis缓存常见问题之预热、雪崩、击穿、穿透
118 0
|
缓存 监控 NoSQL
Redis常见问题企业级解决方案
Redis常见问题企业级解决方案
166 1
|
存储 缓存 NoSQL
Redis常见问题及解决方案
Redis常见问题及解决方案
209 0
|
NoSQL Java Linux
Redis-02Redis在linux下的安装及常见问题
Redis-02Redis在linux下的安装及常见问题
139 0
|
存储 缓存 运维
Redis 的开发规范和常见问题 | 学习笔记
快速学习 Redis 的开发规范和常见问题
Redis 的开发规范和常见问题 | 学习笔记
|
NoSQL Redis