Redis集群方案及实现 - yfk的专栏 - 博客频道 - CSDN.NET

 2023-09-05 阅读 141 评论 0

摘要:Redis集群方案及实现 - yfk的专栏 - 博客频道 - CSDN.NET yfk的专栏学习&记录&分享 目录视图 摘要视图 订阅【公告】博客系统优化升级Unity3D学习,离VR开发还有一步博乐招募开始啦虚拟现实,一探究竟 Redis集

Redis集群方案及实现 - yfk的专栏        - 博客频道 - CSDN.NET

         

           

【公告】博客系统优化升级   Unity3D学习,离VR开发还有一步   博乐招募开始啦   虚拟现实,一探究竟   
   

       Redis集群方案及实现                        

           43033人阅读             评论(15)             收藏             举报        
本文章已收录于:        
category_icon.jpg            分类:        
Redis(12)                      arrow_triangle%20_down.jpg                      arrow_triangle_up.jpg                        
作者同类文章X

之前做了一个Redis的集群方案,跑了小半年,线上运行的很稳定
差不多可以跟大家分享下经验,前面写了一篇文章 数据在线服务的一些探索经验,可以做为背景阅读

应用

我们的Redis集群主要承担了以下服务:
1. 实时推荐
2. 用户画像
3. 诚信分值服务

集群状况

集群峰值QPS 1W左右,RW响应时间999线在1ms左右
整个集群:
1. Redis节点: 8台物理机;每台128G内存;每台机器上8个instance
2. Sentienl:3台虚拟机

集群方案


Redis Node由一组Redis Instance组成,一组Redis Instatnce可以有一个Master Instance,多个Slave Instance

Redis官方的cluster还在beta版本,参看Redis cluster tutorial
在做调研的时候,曾经特别关注过KeepAlived+VIP 和 Twemproxy
不过最后还是决定基于Redis Sentinel实现一套,整个项目大概在1人/1个半月



整体设计

1. 数据Hash分布在不同的Redis Instatnce上
2. M/S的切换采用Sentinel
3. 写:只会写master Instance,从sentinel获取当前的master Instane
4. 读:从Redis Node中基于权重选取一个Redis Instance读取,失败/超时则轮询其他Instance
5. 通过RPC服务访问,RPC server端封装了Redis客户端,客户端基于jedis开发
6. 批量写/删除:不保证事务

RedisKey


public class RedisKey implements Serializable{private static final long serialVersionUID = 1L;//每个业务不同的familyprivate String family;private String key;......	//物理保存在Redis上的key为经过MurmurHash之后的值private String makeRedisHashKey(){return String.valueOf(MurmurHash.hash64(makeRedisKeyString()));}//ReidsKey由family.key组成private String makeRedisKeyString(){return family +":"+ key;}//返回用户的经过Hash之后RedisKeypublic String getRedisKey(){return makeRedisHashKey();}.....
}


Family的存在时为了避免多个业务key冲突,给每个业务定义自己独立的Faimily
出于性能考虑,参考Redis存储设计,实际保存在Redis上的key为经过hash之后的值

接口

目前支持的接口包括:
public interface RedisUseInterface{/*** 通过RedisKey获取value* * @param redisKey*           redis中的key* @return *           成功返回value,查询不到返回NULL*/public String get(final RedisKey redisKey) throws Exception;/*** 插入<k,v>数据到Redis* * @param redisKey*           the redis key* @param value*           the redis value* @return *           成功返回"OK",插入失败返回NULL*/public String set(final RedisKey redisKey, final String value) throws Exception;/*** 批量写入数据到Redis* * @param redisKeys*           the redis key list* @param values*           the redis value list* @return *           成功返回"OK",插入失败返回NULL*/public String mset(final ArrayList<RedisKey> redisKeys, final ArrayList<String> values) throws Exception;/*** 从Redis中删除一条数据* * @param redisKey*           the redis key* @return *           an integer greater than 0 if one or more keys were removed 0 if none of the specified key existed*/public Long del(RedisKey redisKey) throws Exception;/*** 从Redis中批量删除数据* * @param redisKey*           the redis key* @return *           返回成功删除的数据条数*/public Long del(ArrayList<RedisKey> redisKeys) throws Exception;/*** 插入<k,v>数据到Redis* * @param redisKey*           the redis key* @param value*           the redis value* @return *           成功返回"OK",插入失败返回NULL*/public String setByte(final RedisKey redisKey, final byte[] value) throws Exception;/*** 插入<k,v>数据到Redis* * @param redisKey*           the redis key* @param value*           the redis value* @return *           成功返回"OK",插入失败返回NULL*/public String setByte(final String redisKey, final byte[] value) throws Exception;/*** 通过RedisKey获取value* * @param redisKey*           redis中的key* @return *           成功返回value,查询不到返回NULL*/public byte[] getByte(final RedisKey redisKey) throws Exception;/*** 在指定key上设置超时时间* * @param redisKey*           the redis key* @param seconds* 			 the expire seconds* @return *           1:success, 0:failed*/public Long expire(RedisKey redisKey, int seconds) throws Exception;
}

写Redis流程

1. 计算Redis Key Hash值
2. 根据Hash值获取Redis Node编号
3. 从sentinel获取Redis Node的Master
4.  写数据到Redis
		//获取写哪个Redis Nodeint slot = getSlot(keyHash);RedisDataNode redisNode =  rdList.get(slot);//写MasterJedisSentinelPool jp = redisNode.getSentinelPool();Jedis je = null;boolean success = true;try {je = jp.getResource();return je.set(key, value);} catch (Exception e) {log.error("Maybe master is down", e);e.printStackTrace();success = false;if (je != null)jp.returnBrokenResource(je);throw e;} finally {if (success && je != null) {jp.returnResource(je);}}



读流程

1. 计算Redis Key Hash值
2. 根据Hash值获取Redis Node编号
3. 根据权重选取一个Redis Instatnce
4.  轮询读
		//获取读哪个Redis Nodeint slot = getSlot(keyHash);RedisDataNode redisNode =  rdList.get(slot);//根据权重选取一个工作Instatnceint rn = redisNode.getWorkInstance();//轮询int cursor = rn;do {			try {JedisPool jp = redisNode.getInstance(cursor).getJp();return getImpl(jp, key);} catch (Exception e) {log.error("Maybe a redis instance is down, slot : [" + slot + "]" + e);e.printStackTrace();cursor = (cursor + 1) % redisNode.getInstanceCount();if(cursor == rn){throw e;}}} while (cursor != rn);



权重计算

初始化的时候,会给每个Redis Instatnce赋一个权重值weight
根据权重获取Redis Instance的代码:
	public int getWorkInstance() {//没有定义weight,则完全随机选取一个redis instanceif(maxWeight == 0){return (int) (Math.random() * RANDOM_SIZE % redisInstanceList.size());}//获取随机数int rand = (int) (Math.random() * RANDOM_SIZE % maxWeight);int sum = 0;//选取Redis Instancefor (int i = 0; i < redisInstanceList.size(); i++) {sum += redisInstanceList.get(i).getWeight();if (rand < sum) {return i;}}return 0;}



  • 14

  • 0

  • 上一篇HBase原子性保证

  • 下一篇Vector Clock理解

我的同类文章

Redis(12)                                
http://blog.csdn.net                        

参考知识库

更多资料请参考:            

猜你在找

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
快速回复                TOP    
  • 个人资料
1_yfkiss.jpg        
   yfkiss
 
2                                                          
  • 访问:956842次

  • 积分:10445

  • 等级:                        

    积分:10445

  • 排名:第1035名

  • 原创:151篇

  • 转载:6篇

  • 译文:2篇

  • 评论:214条

  • 联系方式


新浪微博:周晓敏_yfk

Mail:zxmever@gmail.com

  • 博客专栏
20151123175212599    Hive应用    

文章:23篇

阅读:217029    
20151123175128630    网络编程    

文章:5篇

阅读:20656    
20151123175128567    Hadoop Streaming实战    

文章:14篇

阅读:79933    
  •       阅读排行    
  • Redis集群方案及实现(42960)

  • Linux下多线程查看工具(pstree、ps、pstack)(38544)

  • hive修改表模式(31241)

  • Kafka(二):环境搭建&测试(30631)

  • Hadoop数据传输工具sqoop(28806)

  • Kafka(一):基础(25121)

  • hive数据导入(19647)

  • hive UDF(18999)

  • TcMalloc,A Big Surprise!(18019)

  • Redis Cluster(Redis 3.X)设计要点(17715)

  • 文章分类
  • c/c++(26)

  • hadoop(30)

  • Linux(16)

  • STL(10)

  • Program(22)

  • Design Pattern(14)

  • Architecture(16)

  • 好文转载(5)

  • 开源学习分享(25)

  • 算法&数据结构(11)

  • 工程实践(8)

  • web(4)

  • Redis(13)

  • Android(1)

  • 网络编程(5)

  • 数据仓库(30)

  • 传输(4)

  • 文章存档

2016年07月(1)

2015年12月(1)

2014年10月(2)

2014年08月(1)

2014年07月(1)

2014年06月(1)

2014年05月(2)

2014年04月(1)

2014年03月(3)

2014年01月(2)

2013年12月(5)

2013年11月(1)

2013年10月(1)

2013年09月(2)

2013年08月(1)

2013年07月(1)

2013年06月(1)

2013年05月(1)

2013年04月(1)

2013年03月(2)

2013年02月(2)

2013年01月(2)

2012年12月(2)

2012年11月(2)

2012年10月(5)

2012年09月(2)

2012年08月(7)

2012年07月(6)

2012年06月(1)

2012年05月(3)

2012年04月(6)

2012年03月(3)

2012年02月(13)

2012年01月(5)

2011年12月(5)

2011年11月(9)

2011年10月(10)

2011年09月(8)

2011年08月(7)

2011年07月(6)

2011年06月(10)

2011年05月(16)

2011年04月(2)

  • 推荐文章
    • * 致JavaScript也将征服的物联网世界

    • * 从苏宁电器到卡巴斯基:难忘的三年硕士时光

    • * 作为一名基层管理者如何利用情商管理自己和团队(一)

    • * Android CircleImageView圆形ImageView

    • * 高质量代码的命名法则

转载于:https://www.cnblogs.com/lhdwr/p/5793067.html

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/3/1009.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息