Vertx 接入Redis (八)
项目github地址:https://github.com/fotocj007/VertxWebApi
web服务器经典的mysql+redis模式,这里介绍redis的接入。
一:导入gradle
1 compile group: 'io.vertx', name: 'vertx-redis-client', version: '3.9.8'
二:添加配置文件
1 { 2 "sources": [ 3 {"connectionString": "redis://:foto_CJ123@10.0.201.215:6379/0", "maxPoolSize":6}, 4 {"connectionString": "redis://:foto_CJ123@10.0.201.215:6379/1", "maxPoolSize":6}, 5 {"connectionString": "redis://:foto_CJ123@10.0.201.215:6379/2", "maxPoolSize":6}, 6 {"connectionString": "redis://:foto_CJ123@10.0.201.215:6379/3", "maxPoolSize":6} 7 ], 8 "poolSize": 8 9 }
三:添加json文件加载 RedisConfig
1 public class RedisConfig extends JsonObjectConfig { 2 private ArrayList<RedisOptions> sources; 3 4 private int poolSize; 5 6 public RedisConfig(Vertx vertx, String path){ 7 super(vertx,path); 8 } 9 10 @Override 11 public void parse(JsonObject jsonObject) { 12 poolSize = jsonObject.getInteger("poolSize"); 13 sources = new ArrayList<>(); 14 JsonArray sourcesJa = jsonObject.getJsonArray("sources"); 15 for (int i = 0; i < sourcesJa.size();i++) { 16 JsonObject jo = sourcesJa.getJsonObject(i); 17 18 RedisOptions redisOpt = new RedisOptions(jo); 19 20 sources.add(redisOpt); 21 } 22 } 23 24 public ArrayList<RedisOptions> getSources() { 25 return sources; 26 } 27 28 public int getPoolSize() { 29 return poolSize; 30 } 31 }
四:添加RedisPool
1 public class ConsistentHashWithNode { 2 private static final String VIR_NODE_NAME_SEPARATOR = "@VirNode"; 3 4 private static final List<String> instanceInfo = new LinkedList<>(); 5 6 /** 7 * 初始化虚拟节点 key表示服务器虚拟节点的hash值,value表示服务器虚拟节点的名称 8 */ 9 private static final SortedMap<Integer, String> serverHashMap = new TreeMap<>(); 10 /** 11 * 设置每台服务器需要的虚拟节点 12 */ 13 private static final int VIRTUAL_NODES = 1000; 14 15 /** 16 * 构建hash环 17 * @param servers 18 */ 19 public ConsistentHashWithNode(List<String> servers) { 20 //首先本地缓存一份实例信息 21 instanceInfo.addAll(servers); 22 instanceInfo.forEach(instance -> { 23 for (int i = 0; i < VIRTUAL_NODES; i++) { 24 //构建虚拟节点 25 String virNodeName = instance + VIR_NODE_NAME_SEPARATOR + i; 26 serverHashMap.put(hash(virNodeName), virNodeName); 27 } 28 }); 29 } 30 31 public static void addNode(String server) { 32 //首先本地缓存一份实例信息 33 instanceInfo.add(server); 34 for (int i = 0; i < VIRTUAL_NODES; i++) { 35 //构建虚拟节点 36 String virNodeName = server + VIR_NODE_NAME_SEPARATOR + i; 37 serverHashMap.put(hash(virNodeName), virNodeName); 38 } 39 } 40 41 /** 42 * 根据数据获取真实存储服务节点 43 * @param data 44 * @return 45 */ 46 public static String getServer(String data) { 47 Integer firstKey; 48 SortedMap<Integer, String> subSortedMap = serverHashMap.tailMap(hash(data)); 49 if (subSortedMap.isEmpty()){ 50 firstKey = serverHashMap.firstKey(); 51 }else{ 52 firstKey = subSortedMap.firstKey(); 53 } 54 55 String virNodeName = serverHashMap.get(firstKey); 56 return virNodeName.substring(0, virNodeName.indexOf(VIR_NODE_NAME_SEPARATOR)); 57 } 58 59 /** 60 * FNV1_32_HASH 百度 61 * @param str 62 * @return 63 */ 64 public static int hash(String str) { 65 final int p = 16777619; 66 int hash = (int)2166136261L; 67 for (int i = 0; i < str.length(); i++) { 68 hash = (hash ^ str.charAt(i)) * p; 69 } 70 hash += hash << 13; 71 hash ^= hash >> 7; 72 hash += hash << 3; 73 hash ^= hash >> 17; 74 hash += hash << 5; 75 if (hash < 0) 76 hash = Math.abs(hash); 77 return Math.abs(hash); 78 } 79 }
1 public class RedisPool { 2 private int poolSize; 3 4 private final Vertx vertx; 5 6 private final List<RedisOptions> dataSources; 7 8 private final Map<String,List<RedisAPI>> pools; 9 10 /************************* 11 * Redis连接池参数配置和初始化 12 */ 13 public RedisPool(Vertx vertx, RedisConfig redisConfig){ 14 this.vertx = vertx; 15 this.poolSize = redisConfig.getPoolSize(); 16 this.dataSources = redisConfig.getSources(); 17 pools = new HashMap<>(); 18 initPool(); 19 } 20 21 private void initPool(){ 22 for (RedisOptions dataSource : dataSources) { 23 String server = dataSource.getEndpoint(); 24 25 List<RedisAPI> list = new ArrayList<>(); 26 for (int j = 1; j <= poolSize; j++) { 27 RedisClient client = new RedisClient(vertx,dataSource); 28 29 list.add(RedisAPI.api(client)); 30 } 31 pools.put(server, list); 32 ConsistentHashWithNode.addNode(server); 33 } 34 } 35 36 /************************* 37 * 根据下标获取也给链接 38 */ 39 public RedisAPI getClientByIndex(int dbId){ 40 RedisOptions options = dataSources.get(dbId); 41 String server = options.getEndpoint(); 42 return pools.get(server).get(ThreadLocalRandom.current().nextInt(poolSize)); 43 } 44 45 /************************* 46 * 根据hashKey获取一个链接 47 */ 48 public RedisAPI getClient(String key){ 49 String server = ConsistentHashWithNode.getServer(key); 50 return pools.get(server).get(ThreadLocalRandom.current().nextInt(poolSize)); 51 } 52 53 /************************* 54 * 关闭连接 55 */ 56 public void close(){ 57 for(List<RedisAPI> list : pools.values()){ 58 for(RedisAPI client : list){ 59 client.close(); 60 } 61 } 62 } 63 }
五:Redis帮助类
1 public class RedisUtil { 2 private final Logger logger = LoggerFactory.getLogger(RedisUtil.class); 3 4 private final RedisPool redisPool; 5 6 public RedisUtil(RedisPool redisPool){ 7 this.redisPool = redisPool; 8 } 9 10 /** 11 * db = 0 12 * 数据格式 key-value 13 */ 14 public void setConfigValue(String rKey, String value,long ex){ 15 redisPool.getClientByIndex(0).setex(rKey,String.valueOf(ex),value,res -> { 16 if(!res.succeeded()) { 17 logger.error("setConfigValue key="+rKey,res.cause()); 18 } 19 }); 20 } 21 22 public void getConfigValue(String rKey, Handler<AsyncResult<Response>> handler){ 23 redisPool.getClientByIndex(0).get(rKey,res -> { 24 if(res.succeeded()) { 25 handler.handle(Future.succeededFuture(res.result())); 26 }else { 27 handler.handle(Future.failedFuture(res.cause())); 28 logger.error("getConfigValue key="+rKey,res.cause()); 29 } 30 }); 31 } 32 33 /** 34 * 分库 35 * 数据格式 key-value 36 */ 37 public void setValueStrById(String passportId,String rKey, String value,long ex){ 38 redisPool.getClient(passportId).setex(rKey,String.valueOf(ex),value,res -> { 39 if(!res.succeeded()) { 40 logger.error("setPlayerValue key="+rKey,res.cause()); 41 } 42 }); 43 } 44 45 public void getValueStrById(String passportId,String rKey,Handler<AsyncResult<Response>> handler){ 46 redisPool.getClient(passportId).get(rKey,res -> { 47 if(res.succeeded()) { 48 handler.handle(Future.succeededFuture(res.result())); 49 }else { 50 handler.handle(Future.failedFuture(res.cause())); 51 logger.error("getValueStrById key="+rKey,res.cause()); 52 } 53 }); 54 } 55 56 }
六:初始化,修改Config
1 public class Configure { 2 private static final Configure ourInstance = new Configure(); 3 4 public static Configure getInstance() { 5 return ourInstance; 6 } 7 8 protected Vertx vertx; 9 10 public MysqlConfig mysqlConfig; 11 private MySQLUtil mySQLPool; 12 public DaoManager daoManager; 13 14 private RedisConfig redisConfig; 15 private RedisPool redisPool; 16 public RedisUtil redisUtil; 17 18 public void init(Vertx vertx){ 19 this.vertx = vertx; 20 21 initHandler(); 22 23 loadConfig(); 24 25 initDb(); 26 initRedis(); 27 } 28 29 private void initHandler(){ 30 HandlerManager.getInstance().addHandler(new DemoHandler()); 31 } 32 33 /** 34 * 加载db和Redis配置文件 35 */ 36 protected void loadConfig(){ 37 mysqlConfig = new MysqlConfig(vertx, "res/mysql.json"); 38 redisConfig = new RedisConfig(vertx, "res/redis.json"); 39 } 40 41 protected void initDb(){ 42 List<JsonObject> list = new ArrayList<>(); 43 for(int i = 0; i< mysqlConfig.configs.size();i++){ 44 list.add(mysqlConfig.configs.getJsonObject(i)); 45 } 46 mySQLPool = new MySQLUtil(vertx,2,list); 47 48 daoManager = new DaoManager(mysqlConfig,mySQLPool); 49 } 50 51 /** 52 * 初始化Redis 53 */ 54 protected void initRedis(){ 55 redisPool = new RedisPool(vertx,redisConfig); 56 redisUtil = new RedisUtil(redisPool); 57 } 58 }
七:测试一下,修改DemoHandler
PlayerInfo info = new PlayerInfo(); info.setUserName("kkkkkdd"); info.setAge(100); // PlayerDao client = Configure.getInstance().daoManager.getPlayerDao(); // client.saveBaseEntity(info,res -> { // // }); String key = "demo_test_key"; Configure.getInstance().redisUtil.setConfigValue(key, JsonObject.mapFrom(info).toString(),300); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } Configure.getInstance().redisUtil.getConfigValue(key,res -> { System.out.println(res.result().toString()); PlayerInfo rInfo = new JsonObject(res.result().toString()).mapTo(PlayerInfo.class); System.out.println(rInfo.getUserName()); });
发起请求:
项目结构: