Redis分布式缓存搭建

花了两天时间整理了之前记录的Redis单体与哨兵模式的搭建与使用,又补齐了集群模式的使用和搭建经验,并对集群的一些个原理做了理解。

笔者安装中遇到的一些问题:

如果make报错,可能是没装gcc或者gcc++编辑器,安装之 yum -y install gcc gcc-c++ kernel-devel ,有可能还是提示一些个c文件编译不过,gcc -v查看下版本,如果不到5.3那么升级一下gcc:

在 /etc/profile 追加一行 source /opt/rh/devtoolset-9/enable

scl enable devtoolset-9 bash

重新make clean, make

这回编译通过了,提示让你最好make test一下/

执行make test ,如果提示 You need tcl 8.5 or newer in order to run the Redis test

那就升级tcl, yum install tcl

重新make test,如果还有error就删了目录,重新tar包解压重新make , make test

\o/ All tests passed without errors! ,表示编译成功。

然后make install即可。

直接运行命令: ./redis-server /usr/redis-6.0.3/redis.conf &

redis.conf 配置文件里 bind 0.0.0.0 设置外部访问, requirepass xxxx 设置密码。

redis高可用方案有两种:

常用搭建方案为1主1从或1主2从+3哨兵监控主节点, 以及3主3从6节点集群。

(1)sentinel哨兵

/usr/redis-6.0.3/src/redis-sentinel /usr/redis-6.0.3/sentinel2.conf &

sentinel2.conf配置:

坑1:master节点也会在故障转移后成为从节点,也需要配置masterauth

当kill master进程之后,经过sentinel选举,slave成为了新的master,再次启动原master,提示如下错误:

原因是此时的master再次启动已经是slave了,需要向现在的新master输入密码,所以需要在master.conf
中配置:

坑2:哨兵配置文件要暴露客户端可以访问到的master地址

在 sentinel.conf 配置文件的 sentinel monitor mymaster 122.xx.xxx.xxx 6379 2 中,配置该哨兵对应的master名字、master地址和端口,以及达到多少个哨兵选举通过认为master挂掉。其中master地址要站在redis访问者(也就是客户端)的角度、配置访问者能访问的地址,例如sentinel与master在一台服务器(122.xx.xxx.xxx)上,那么相对sentinel其master在本机也就是127.0.0.1上,这样 sentinel monitor mymaster 127.0.0.1 6379 2 逻辑上没有问题,但是如果另外服务器上的springboot通过lettuce访问这个redis哨兵,则得到的master地址为127.0.0.1,也就是springboot所在服务器本机,这显然就有问题了。

附springboot2.1 redis哨兵配置:

坑3:要注意配置文件.conf会被哨兵修改

redis-cli -h localhost -p 26379 ,可以登到sentinel上用info命令查看一下哨兵的信息。

曾经遇到过这样一个问题,大致的信息如下

slaves莫名其妙多了一个,master的地址也明明改了真实对外的地址,这里又变成127.0.0.1 !
最后,把5个redis进程都停掉,逐个检查配置文件,发现redis的配置文件在主从哨兵模式会被修改,master的配置文件最后边莫名其妙多了一行replicaof 127.0.0.1 7001, 怀疑应该是之前配置错误的时候(见坑2)被哨兵动态加上去的! 总之,实践中一定要多注意配置文件的变化。

(2)集群

当数据量大到一定程度,比如几十上百G,哨兵模式不够用了需要做水平拆分,早些年是使用codis,twemproxy这些第三方中间件来做分片的,即 客户端 -> 中间件 -> Redis server 这样的模式,中间件使用一致性Hash算法来确定key在哪个分片上。后来Redis官方提供了方案,大家就都采用官方的Redis Cluster方案了。

Redis Cluster从逻辑上分16384个hash slot,分片算法是 CRC16(key) mod 16384 得到key应该对应哪个slot,据此判断这个slot属于哪个节点。

每个节点可以设置1或多个从节点,常用的是3主节点3从节点的方案。

reshard,重新分片,可以指定从哪几个节点移动一些hash槽到另一个节点去。重新分片的过程对客户端透明,不影响线上业务。

搭建Redis cluster

redis.conf文件关键的几个配置:

启动6个集群节点

[root@VM_0_11_centos redis-6.0.3]# ps -ef|grep redis
root 5508 1 0 21:25 ? 00:00:00 /usr/redis-6.0.3/src/redis-server 0.0.0.0:7001 [cluster]
root 6903 1 0 21:32 ? 00:00:00 /usr/redis-6.0.3/src/redis-server 0.0.0.0:7002 [cluster]
root 6939 1 0 21:33 ? 00:00:00 /usr/redis-6.0.3/src/redis-server 0.0.0.0:7003 [cluster]
root 6966 1 0 21:33 ? 00:00:00 /usr/redis-6.0.3/src/redis-server 0.0.0.0:7004 [cluster]
root 6993 1 0 21:33 ? 00:00:00 /usr/redis-6.0.3/src/redis-server 0.0.0.0:7005 [cluster]
root 7015 1 0 21:33 ? 00:00:00 /usr/redis-6.0.3/src/redis-server 0.0.0.0:7006 [cluster]

这时候这6个节点还是独立的,要把他们配置成集群:

说明: -a xxxx 是因为笔者在redis.conf中配置了requirepass xxxx密码,然后 --cluster-replicas 1 中的1表示每个master节点有1个从节点。

上述命令执行完以后会有一个询问: Can I set the above configuration? yes同意自动做好的分片即可。

最后 All 16384 slots covered. 表示集群中16384个slot中的每一个都有至少有1个master节点在处理,集群启动成功。

查看集群状态:

坑1:暴露给客户端的节点地址不对

使用lettuce连接发现连不上,查看日志 Connection refused: no further information: /127.0.0.1:7002 ,跟之前哨兵配置文件sentinel.conf里边配置master地址犯的错误一样,集群启动的时候带的地址应该是提供给客户端访问的地址。

我们要重建集群:先把6个redis进程停掉,然后删除 nodes-7001.conf 这些节点配置文件,删除持久化文件 dump.rdb 、 appendonly.aof ,重新启动6个进程,在重新建立集群:

然后,还是连不上,这次报错 connection timed out: /172.xx.0.xx:7004 ,发现连到企鹅云服务器的内网地址上了!

解决办法,修改每个节点的redis.conf配置文件,找到如下说明:

所以增加配置:

然后再重新构建集群,停进程、改配置、删除节点文件和持久化文件、启动进程、配置集群。。。再来一套(累死了)

重新使用Lettuce测试,这次终于连上了!

坑2:Lettuce客户端在master节点故障时没有自动切换到从节点

name这个key在7002上,kill这个进程模拟master下线,然后Lettuce一直重连。我们期望的是应该能自动切换到其slave 7006上去,如下图:

重新启动7002进程,

7006已成为新master,7002成为它的slave,然后Lettuce也能连接上了。
解决办法,修改Lettuce的配置:

笔者用的是springboot 2.1 spring-boot-starter-data-redis 默认的Lettuce客户端,当使用Redis cluster集群模式时,需要配置一下 RedisConnectionFactory 开启自适应刷新来做故障转移时的自动切换从节点进行连接。

重新测试:停掉master 7006,这次Lettuce可以正常切换连到7002slave上去了。(仍然会不断的在日志里报连接错误,因为需要一直尝试重连7006,但因为有7002从节点顶上了、所以应用是可以正常使用的)

Redis不保证数据的强一致性

Redis并不保证数据的强一致性,也就是取CAP定理中的AP

关于一致性Hash算法,可以参考 一致性Hash算法 - (jianshu.com)

Redis cluster使用的是hash slot算法,跟一致性Hash算法不太一样,固定16384个hash槽,然后计算key落在哪个slot里边(计算key的CRC16值再对16384取模),key找的是slot而不是节点,而slot与节点的对应关系可以通过reshard改变并通过gossip协议扩散到集群中的每一个节点、进而可以为客户端获知,这样key的节点寻址就跟具体的节点个数没关系了。也同样解决了普通hash取模算法当节点个数发生变化时,大量key对应的寻址都发生改动导致缓存失效的问题。

比如集群增加了1个节点,这时候如果不做任何操作,那么新增加的这个节点上是没有slot的,所有slot都在原来的节点上且对应关系不变、所以没有因为节点个数变动而缓存失效,当reshard一部分slot到新节点后,客户端获取到新迁移的这部分slot与新节点的对应关系、寻址到新节点,而没迁移的slot仍然寻址到原来的节点。

关于热迁移,猜想,内部应该是先做复制迁移,等迁移完了,再切换slot与节点的对应关系,复制没有完成之前仍按照原来的slot与节点对应关系去原节点访问。复制结束之后,再删除原节点上已经迁移的slot所对应的key。

与哨兵模式比较类似,当1个节点发现某个master节点故障了、会对这个故障节点进行pfail主观宕机,然后会通过gossip协议通知到集群中的其他节点、其他节点也执行判断pfail并gossip扩散广播这一过程,当超过半数节点pfail时那么故障节点就是fail客观宕机。接下来所有的master节点会在故障节点的从节点中选出一个新的主节点,此时所有的master节点中超过半数的都投票选举了故障节点的某个从节点,那么这个从节点当选新的master节点。

所有节点都持有元数据,节点之间通过gossip这种二进制协议进行通信、发送自己的元数据信息给其他节点、故障检测、集群配置更新、故障转移授权等等。

这种去中心化的分布式节点之间内部协调,包括故障识别、故障转移、选主等等,核心在于gossip扩散协议,能够支撑这样的广播协议在于所有的节点都持有一份完整的集群元数据,即所有的节点都知悉当前集群全局的情况。

Redis高可用方案 - (jianshu.com)

面试题:Redis 集群模式的工作原理能说一下么 - 云+社区 - 腾讯云 (tencent.com)

深度图解Redis Cluster原理 - detectiveHLH - 博客园 (cnblogs.com)

Redis学习笔记之集群重启和遇到的坑-阿里云开发者社区 (aliyun.com)

云服务器Redis集群部署及客户端通过公网IP连接问题



  • Redis鏄粈涔,鐢ㄦ潵鍋氫粈涔
    绛旓細鏁版嵁璇诲啓鏄熀浜庡唴瀛橈紝閫熷害闈炲父蹇紝鎵浠ュ父鐢ㄤ簬缂撳瓨锛涜繘鑰屽洜鍏朵负鐙珛閮ㄧ讲鐨勪腑闂翠欢锛屽父鐢ㄤ簬鍒嗗竷寮忕紦瀛鐨勫疄鐜版柟妗堛傚父鐢ㄥ満鏅湁锛氱紦瀛樸佺鏉鎺у埗銆佸垎甯冨紡閿併傝櫧鐒跺叾鏄熀浜庡唴瀛樿鍐欙紝浣嗗簳灞備篃鏈夋寔涔呭寲鏈哄埗锛涘悓鏃跺叿澶囬泦缇ゆā寮忥紱涓嶇敤鎷呭績鍏跺彲鐢ㄦс傚叧浜Redis鐨浣跨敤锛屽彲浠ュ弬鑰冦奟edis鐨勪娇鐢ㄦ柟娉曘佸父瑙佸簲鐢ㄥ満鏅...
  • 闈㈣瘯涓棶鍒Redis鎸佷箙鍖栫殑鍘熺悊,鏈瘒鍦ㄥ仛璇︾粏瑙g瓟
    绛旓細鎴戜滑鐭ラ亾redis鏄竴涓 楂樻晥鐨勫垎甯冨紡鍐呭瓨鏁版嵁搴 锛岀敱浜庢槸鎿嶄綔鍐呭瓨鎵浠ユц兘闈炲父涔嬪揩锛岄氬父鐢ㄥ畠鏉ュ仛鍒嗗竷寮忕紦瀛锛岀敤鏉ユ彁楂樺井鏈嶅姟鐨勯珮鎬ц兘锛屼絾鏄洜涓烘槸鍐呭瓨鎿嶄綔锛屾墍浠ュ綋鍑虹幇鏈嶅姟鍣ㄦ晠闅滐紝鏂數绛夋儏鍐靛氨浼氶犳垚 鍐呭瓨鏁版嵁涓㈠け 锛屼笉鍙仮澶嶏紝鍥犳redis 寮曞叆浜嗘寔涔呭寲鏈哄埗鏉ュ皢鍐呭瓨鏁版嵁鍐欏叆纾佺洏锛屼粠鑰屼繚闅滀簡Redis鐨鏁版嵁涓...
  • 澶у鎵鎺ㄥ磭鐨 Redis 鍒嗗竷寮閿,鐪熺殑鍙互涓囨棤涓澶卞悧?
    绛旓細鐒跺悗鍦ㄦ墽琛屼笟鍔¢昏緫鐨勬椂鍊欒楄垂浜15s锛屾鏃剁嚎绋婣鑾峰彇鐨勯攣鏃╁凡琚玆edis鐨勮繃鏈熸満鍒惰嚜鍔ㄩ噴鏀句簡銆傚湪绾跨▼A鑾峰彇閿佸苟缁忚繃10s涔嬪悗锛屾敼閿佸彲鑳藉凡缁忚鍏跺畠绾跨▼鑾峰彇鍒颁簡銆傚綋绾跨▼A鎵ц瀹屼笟鍔¢昏緫鍑嗗瑙i攣锛圖EL key锛夌殑鏃跺欙紝鏈夊彲鑳藉垹闄ゆ帀鐨勬槸鍏跺畠绾跨▼宸茬粡鑾峰彇鍒扮殑閿侊紝鎬荤殑鏉ヨRedis 鍒嗗竷寮閿佷笉鏄偅涔堜竾鏃犱竴澶辩殑銆
  • redis缂撳瓨鏈哄埗涓鑸細褰卞搷杞欢鐨勫摢浜涘姛鑳?
    绛旓細鍐呭瓨闄愬埗锛Redis鏄熀浜庡唴瀛樼殑瀛樺偍绯荤粺锛屽綋缂撳瓨鏁版嵁閲忚繃澶ф椂锛屽彲鑳戒細娑堣楀ぇ閲忓唴瀛樿祫婧愶紝褰卞搷杞欢鍏朵粬鍔熻兘鐨勬ц兘銆傜紦瀛樼┛閫忋佺紦瀛樺嚮绌垮拰缂撳瓨闆穿锛氳繖浜涚幇璞″彲鑳藉鑷寸紦瀛樼郴缁熸壙鍙楄緝澶у帇鍔涳紝杩涜屽奖鍝嶆暣涓蒋浠剁殑鎬ц兘鍜岀ǔ瀹氭с鍒嗗竷寮鐜锛氬湪鍒嗗竷寮忕幆澧冧笅锛岄渶瑕佽冭檻缂撳瓨鏁版嵁鐨勫悓姝ュ拰涓鑷存ч棶棰橈紝鍚﹀垯鍙兘浼氬鑷磋蒋浠跺姛鑳...
  • 甯哥敤鐨缂撳瓨鎶鏈
    绛旓細鍦ㄤ娇鐢╦sp鐨勬椂鍊欙紝鎴戜滑浼氬皢涓浜涘鏉傜殑椤甸潰浣跨敤Oscache杩涜椤甸潰缂撳瓨锛屼娇鐢ㄩ潪甯哥畝鍗曪紝灏辨槸鍑犱釜鏍囩鐨勪簨鍎匡紱浣嗘槸锛岀幇鍦ㄤ竴鑸殑浼佷笟锛屽墠鍙伴兘浼氫娇鐢╲elocity銆乫reemaker杩欎袱绉嶆ā鏉垮紩鎿庯紝鏈韩閫熷害灏卞凡缁忓緢蹇簡锛岄〉闈㈢紦瀛樹娇鐢ㄧ殑涔熷氨寰堝皯浜嗐傛荤粨锛氬湪瀹為檯鐢熶骇涓紝鎴戜滑閫氬父浼氫娇鐢╣uava cache鍋氭湰鍦扮紦瀛+redis鍋鍒嗗竷寮忕紦瀛+...
  • redis鏄共鍢涚殑
    绛旓細鎵浠ユ湁鐨勬暟鎹細鍦ㄤ竴娈垫椂闂村唴鍙瓨鍦ㄤ簬鍐呭瓨涓俛ppendfsync no/always/everysec锛宎ppendfsync閰嶇疆锛宯o琛ㄧず绛夋搷浣滅郴缁熻繘琛屾暟鎹缂撳瓨鍚屾鍒扮鐩橈紝always琛ㄧず姣忔鏇存柊鎿嶄綔鍚庢墜鍔ㄨ皟鐢╢sync()灏嗘暟鎹啓鍒扮鐩橈紝everysec琛ㄧず姣忕鍚屾涓娆°備互涓婂唴瀹瑰弬鑰冪櫨搴︾櫨绉-Redis ...
  • redis鍒板簳鏄釜浠涔堜笢瑗
    绛旓細1. 浠涔堟槸Redis Redis鏄敱鎰忓ぇ鍒╀汉Salvatore Sanfilippo锛堢綉鍚嶏細antirez锛夊紑鍙戠殑涓娆惧唴瀛橀珮閫缂撳瓨鏁版嵁搴撱俁edis鍏ㄧО涓猴細Remote Dictionary Server锛堣繙绋嬫暟鎹湇鍔★級锛岃杞欢浣跨敤C璇█缂栧啓锛孯edis鏄竴涓猭ey-value瀛樺偍绯荤粺锛屽畠鏀寔涓板瘜鐨勬暟鎹被鍨嬶紝濡傦細string銆乴ist銆乻et銆亃set(sorted set)銆乭ash銆2. Redis鐗圭偣 Re...
  • redis閫傚悎浠涔堝満鏅
    绛旓細4銆鍒嗗竷寮浼氳瘽闆嗙兢妯″紡涓嬶紝鍦ㄥ簲鐢ㄤ笉澶氱殑鎯呭喌涓嬩竴鑸娇鐢ㄥ鍣ㄨ嚜甯︾殑session澶嶅埗鍔熻兘灏辫兘婊¤冻锛屽綋搴旂敤澧炲鐩稿澶嶆潅鐨勭郴缁熶腑锛屼竴鑸兘浼鎼缓浠Redis绛夊唴瀛樻暟鎹簱涓轰腑蹇冪殑session鏈嶅姟锛宻ession涓嶅啀鐢卞鍣ㄧ鐞嗭紝鑰屾槸鐢眘ession鏈嶅姟鍙婂唴瀛樻暟鎹簱绠$悊銆5銆佸垎甯冨紡閿佸湪寰堝浜掕仈缃戝叕鍙镐腑閮戒娇鐢ㄤ簡鍒嗗竷寮忔妧鏈紝鍒嗗竷寮忔妧鏈甫鏉ョ殑鎶鏈...
  • 鍒嗗竷寮閿佺殑涓夌瀹炵幇鏂瑰紡闈㈣瘯
    绛旓細鍒嗗竷寮閿佷笁绉嶅疄鐜版柟寮忥細1銆佸熀浜庢暟鎹簱瀹炵幇鍒嗗竷寮忛攣锛2銆佸熀浜缂撳瓨锛Redis绛夛級瀹炵幇鍒嗗竷寮忛攣锛3銆佸熀浜嶼ookeeper瀹炵幇鍒嗗竷寮忛攣銆備粠鎬ц兘瑙掑害锛堜粠楂樺埌浣庯級鏉ョ湅锛氣滅紦瀛樻柟寮>Zookeeper鏂瑰紡>=鏁版嵁搴撴柟寮忊濄1銆傛偛瑙傞攣锛氬埄鐢╯elect?where?forupdate鎺掍粬閿併傛墍璋撲箰瑙傞攣涓庡墠杈规渶澶у尯鍒湪浜庡熀浜嶤AS鎬濇兂锛屾槸涓嶅叿鏈変簰鏂ユэ紝...
  • 鍥戒骇缂撳瓨鏁版嵁搴?
    绛旓細浠ヤ笅鏄竴浜涘浗浜х殑缂撳瓨鏁版嵁搴撶郴缁燂細1. Redisson锛氳繖鏄竴涓熀浜Redis鍗忚鐨鍒嗗竷寮忕紦瀛鍜屽垎甯冨紡鏁版嵁搴擄紝鎻愪緵浜嗕赴瀵岀殑鍔熻兘鍜屽師鐢烰ava鏀寔銆2. Tair锛氱敱闃块噷宸村反寮鍙戠殑鍒嗗竷寮忕紦瀛樺拰鏁版嵁瀛樺偍绯荤粺锛屽叿鏈夐珮鎬ц兘銆侀珮鍙潬鎬у拰楂樻墿灞曟х殑鐗圭偣銆3. Memcachedb锛氳繖鏄竴涓熀浜嶮emcached鍗忚鐨勯珮鎬ц兘鍐呭瓨鏁版嵁搴擄紝鏀寔鏁版嵁鎸佷箙...
  • 扩展阅读:redis 缓存穿透 击穿 雪崩 ... redis哨兵模式怎么搭建 ... redis面试必会6题经典 ... 集群搭建的三种方式 ... redis分布式锁三种方式 ... 分布式缓存redis 方案 ... 分布式存储三种方式 ... redis分布式事务锁 ... redis分布式锁解决可重入 ...

    本站交流只代表网友个人观点,与本站立场无关
    欢迎反馈与建议,请联系电邮
    2024© 车视网