redis

文章目录

安装

bash 复制代码
docker run -p 6379:6379 --name myredis1 --privileged=true -v "C:/Users/tang8/.docker/mydata/redis/redis.conf":"/etc/redis/redis.conf" -v "C:/Users/tang8/.docker/mydata/redis/data":"/data" -d redis:6.2.7 redis-server /etc/redis/redis.conf

集群

如果有上亿条记录(即上亿条k,v)需要存储在redis中,单机比如无法满足存储需求,必须要分布式多个redis分散存储,但是如何均匀分配数据就成了一个问题。

哈希

为了解决均匀分配数据问题,可以使用hash算法,即将key(因为redis中key不可以重复)的hash值,与ip绑定。

具体算法是:hash(key)%N个机器台数

优点

简单,只需要预估好数据规划好节点,例如3台、8台、10台,就能保证一段时间的数据支撑。使用Hash算法让固定的一部分请求落到同一台服务器上,这样每台服务器固定处理一部分请求(并维护这些请求的信息),起到负载均衡+分散存储的作用。

缺点

原来规划好的节点,进行扩容或者缩容时比较麻烦,不管扩容还是缩容,每次数据变动导致节点有变动,映射关系需要重新进行计算,在服务器个数固定不变时没有问题,如果需要弹性扩容或故障停机的情况下,原来的取模公式就会发生变化:Hash(key)/3会变成Hash(key)/?。此时地址经过取余运算的结果将发生很大变化,根据公式获取的服务器也会变得不可控。某个 redis机器宕机了,由于台数数量变化,会导致hash取余全部数据重新洗牌。

一致性哈希

为了在节点数目发生改变时尽可能少的迁移数据,将所有的存储节点排列在收尾相接的Hash环上,每个key在计算Hash后会顺时针找到临近的存储节点存放。而当有节点加入或退出时仅影响该节点在Hash环上顺时针相邻的后续节点。

一致性哈希环

一致性哈希算法必然有个hash函数并按照算法产生hash值,这个算法的所有可能哈希值会构成一个全量集,这个集合可以成为一个hash空间[0~2^432-1],这个是一个线性空间,但是在算法中,我们通过适当的逻辑控制将它首尾相连(0=2^32),这样让它逻辑上形成了一个环形空间。

它也是按照使用取模的方法,前面笔记介绍的节点取模法是对节点(服务器)的数量进行取模。而一致性Has算法是对2^32取模。

简单来说,一致性Hash算法将整个哈希值空间组织成一个虚拟的圆环,如假设某哈希函数H的值空间为0~2^32-1(即哈希值是一个32位无符号整形),整个哈希环如下图:整个空间按顺时针方向组织,圆环的正上方的点代表0,0点右侧的第一个点代表1,以此类推,2、3、4、......直到2^32-1,也就是说0点左侧的第一个点代表2^32-1,0和2^32-1在零点中方向重合,我们把这个由2^32个点组成的圆环称为Hash环。

节点映射

将集群中各个P节点映射到环上的某一个位置。

将各个服务器使用Hash进行一个哈希,具体可以选择服务器的IP或主机名作为关键字进行哈希,这样每台机器就能确定其在哈希环上的位置。假如

4个节点 NodeA、B、C、D,经过IP地址的哈希函数计算(hash(ip)),使用IP地址哈希后在环空间的位置如下:

key落到服务器的落键规则

当我们需要存储一个kv键值对时,首先计算key的hash值,hash(key),将这个key使用相同的函数Hash计算出哈希值并确定此数据在环上的位置,从

此位置沿环顺时针"行走",第一台遇到的服务器就是其应该定位到的服务器,并将该键值对存储在该节点上。

如我们有 Object A、 Object B、 Object C、 Object D四个数据对象,经过哈希计算后,在环空间上的位置如下:根据一致性Hash算法,数据A会被定

为到 Node A上,B被定为到 Node B上,C被定为到 Node C上,D被定为到 Node D上。

优点

加入和删除节点只影响哈希环中顺时针方向的相邻的节点,对其他节点无影响。

一致性哈希算法的容错性

假设 Node C宕机,可以看到此时对象A、B、D不会受到影响,只有C对象被重定位到 Node D。一般的,在一致性Hash算法中,如果一台服务器不可

用,则受影响的数据仅仅是此服务器到其环空间中前一台服务器(即沿着逆时针方向行走遇到的第一台服务器)之间数据,其它不会受到影响。简单

说,就是C挂了,受到影响的只是B、C之间的数据,并且这些数据会转移到D进行存储。

一致性哈希算法的扩展性

数据量增加了,需要增加一台节点odeX,X的位置在A和B之间,那收到影响的也就是A到X之间的数据,重新把A到X的数据录入到X上即可,

不会导致hash取余全部数据重新洗牌。

缺点

数据的分布和节点的位置有关,因为这些节点不是均匀的分布在哈希环上的,所以数据在进行存储时达不到均匀分布

的效果。

一致性哈希算法的数据倾斜问题

一致性Has算法在服务节点太少时,容易因为节点分布不均匀而造成数据倾斜(被缓存的对象大部分集中缓存在某一台服务器上)问题,

例如系统中只有两台服务器:

哈希槽

Redis集群并没有使用一致性hash而是引入了哈希槽的概念,可以解决一致性哈希算法的数据倾斜问题。

Redis集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽,集群的每个节点负责一部分hash槽。

哈希槽实质就是一个数组,数组[0~2^14-1]形成 hash slot空间。

槽解决的是粒度问题,相当于把粒度变大了,这样便于数据移动。

哈希解决的是映射问题,使用key的哈希值来计算所在的槽,便于数据分配。

一个集群只能有16384个槽,编号0-16383(0-2^14-1)。这些槽会分配给集群中的所有主节点,分配策略没有要求。可以指定哪些编号的槽分配给哪个主节点。集群会记录节点和槽的对应关系。解决了节点和槽的关系后,接下来就需要对key求哈希值,然后对16384取余,余数是几key就落入对应的槽里。slot=CRC16(key)%16384。以槽为单位移动数据,因为槽的数目是固定的,处理起来比较容易,这样数据移动问题就解决了。

为什么 redis集群的最大槽数是16384个?

(1)如果槽位为65536,发送心跳信息的消息头达8k,发送的心跳包过于庞大。

在消息头中最占空间的是 myslots[ CLUSTER_ SLOTS/8]。当槽位为65536时,这块的大小是:65536÷8÷1024=8kb

因为每秒钟, redis节点需要发送一定数量的ping消息作为心跳包,如果槽位为65536,这个ping消息的消息头太大了,浪费带宽。

(2) redis的集群主节点数量基本不可能超过1000个。

集群节点越多,心跳包的消息体内携带的数据越多。如果节点过1O00个,也会导致网络拥堵。因此 redis作者不建议 redis cluster节点数量超过

1000个。那么,对于节点数在1000以内的 redis cluster集群,16384个槽位够用了。没有必要拓展到65536个。

(3)槽位越小,节点少的情况下,压缩比高,容易传输

Redis主节点的配置信息中它所负责的哈希槽是通过一张 bitmap的形式来保存的,在传输过程中会对 bitmap进行压缩,但是如果 bitmap的填充率 slots

/N很高的话(N表示节点数), bitmap的压缩率就很低。如果节点数很少,而哈希槽数量很多的话, bitmapl的压缩率就很低。

相关推荐
柯南二号4 小时前
MacOS 用brew 安装、配置、启动Redis
redis
星星点点洲6 小时前
【Redis】RedLock实现原理
redis·缓存
我来整一篇6 小时前
用Redis的List实现消息队列
数据库·redis·list
加什么瓦7 小时前
Redis——数据结构
数据库·redis·缓存
lybugproducer8 小时前
浅谈 Redis 数据类型
java·数据库·redis·后端·链表·缓存
青山是哪个青山8 小时前
Redis 常见数据类型
数据库·redis·bootstrap
杨不易呀8 小时前
Java面试全记录:Spring Cloud+Kafka+Redis实战解析
redis·spring cloud·微服务·kafka·高并发·java面试·面试技巧
郭逍遥8 小时前
[工具]B站缓存工具箱 (By 郭逍遥)
windows·python·缓存·工具
morris1319 小时前
【redis】CacheAside的数据不一致性问题
redis·缓存策略·cache aside·数据不一致性