redis常用知识汇总( 九 )


Redis集群会有写操作丢失吗?为什么?
Redis并不能保证数据的强一致性 , 这意味这在实际中集群在特定的条件下可能会丢失写操作 。
Redis集群之间是如何复制的?
异步复制
Redis集群最大节点个数是多少?
16384个
Redis集群如何选择数据库?
Redis集群目前无法做数据库选择 , 默认在0数据库 。
 
分区
Redis是单线程的 , 如何提高多核CPU的利用率?
可以在同一个服务器部署多个Redis的实例 , 并把他们当作不同的服务器来使用 , 在某些时候 , 无论如何一个服务器是不够的 ,  所以 , 如果你想使用多个CPU , 你可以考虑一下分片(shard) 。
为什么要做Redis分区?
分区可以让Redis管理更大的内存 , Redis将可以使用所有机器的内存 。如果没有分区 , 你最多只能使用一台机器的内存 。分区使Redis的计算能力通过简单地增加计算机得到成倍提升 , Redis的网络带宽也会随着计算机和网卡的增加而成倍增长 。
你知道有哪些Redis分区实现方案?
1、客户端分区就是在客户端就已经决定数据会被存储到哪个redis节点或者从哪个redis节点读取 。大多数客户端已经实现了客户端分区 。
2、代理分区 意味着客户端将请求发送给代理 , 然后代理决定去哪个节点写数据或者读数据 。代理根据分区规则决定请求哪些Redis实例 , 然后根据Redis的响应结果返回给客户端 。redis和memcached的一种代理实现就是Twemproxy
3、查询路由(Query routing) 的意思是客户端随机地请求任意一个redis实例 , 然后由Redis将请求转发给正确的Redis节点 。Redis Cluster实现了一种混合形式的查询路由 , 但并不是直接将请求从一个redis节点转发到另一个redis节点 , 而是在客户端的帮助下直接redirected到正确的redis节点 。
 
Redis分区有什么缺点?
1、涉及多个key的操作通常不会被支持 。例如你不能对两个集合求交集 , 因为他们可能被存储到不同的Redis实例(实际上这种情况也有办法 , 但是不能直接使用交集指令) 。
2、同时操作多个key,则不能使用Redis事务.
3、分区使用的粒度是key , 不能使用一个非常长的排序key存储一个数据集(The partitioning granularity is the key, so it is not possible to shard a dataset with a single huge key like a very big sorted set)
4、当使用分区的时候 , 数据处理会非常复杂 , 例如为了备份你必须从不同的Redis实例和主机同时收集RDB / AOF文件 。
5、分区时动态扩容或缩容可能非常复杂 。Redis集群在运行时增加或者删除Redis节点 , 能做到最大程度对用户透明地数据再平衡 , 但其他一些客户端分区或者代理分区方法则不支持这种特性 。然而 , 有一种预分片的技术也可以较好的解决这个问题 。
 
分布式问题
Redis实现分布式锁
Redis为单进程单线程模式 , 采用队列模式将并发访问变成串行访问 , 且多客户端对Redis的连接并不存在竞争关系Redis中可以使用SETNX命令实现分布式锁 。
当且仅当 key 不存在 , 将 key 的值设为 value 。若给定的 key 已经存在 , 则 SETNX 不做任何动作
SETNX 是『SET if Not eXists』(如果不存在 , 则 SET)的简写 。
返回值:设置成功 , 返回 1。设置失败 , 返回 0。

redis常用知识汇总

文章插图
 
使用SETNX完成同步锁的流程及事项如下:
使用SETNX命令获取锁 , 若返回0(key已存在 , 锁已存在)则获取失败 , 反之获取成功
为了防止获取锁后程序出现异常 , 导致其他线程/进程调用SETNX命令总是返回0而进入死锁状态 , 需要为该key设置一个“合理”的过期时间
释放锁 , 使用DEL命令将锁数据删除
如何解决 Redis 的并发竞争 Key 问题
所谓 Redis 的并发竞争 Key 的问题也就是多个系统同时对一个 key 进行操作 , 但是最后执行的顺序和我们期望的顺序不同 , 这样也就导致了结果的不同!
推荐一种方案:分布式锁(zookeeper 和 redis 都可以实现分布式锁) 。(如果不存在 Redis 的并发竞争 Key 问题 , 不要使用分布式锁 , 这样会影响性能)


推荐阅读