最近继续学习Mongodb的根本原因,是为了解决今天的问题。
项目中用到了Hbase,生产环境服务器用了3台,但是不够稳定,每2天左右,就连不上了。
重启就好了,当然,这是一个历史遗留问题。
我在想,是不是连接没有关闭,每次都是建立新的连接?
瞅瞅Java访问Hbase的代码,都close了额。

原来的Hbase,用Java访问,有add/update、get、getList3个接口。
现在要加上Mongodb存储,尽可能保证Hbase和Mongodb数据同步。
优先使用Mongodb中的数据,其次才使用HBase中的数据。

今后有可能不再使用Hbase。

在项目刚刚启动的时候,需要同步HBase中的数据到Mongodb。
简化代码如下
public class ProjectDetailClient {
private ProjectDetailHbaseClient hbase = new ProjectDetailHbaseClient();
private ProjectDetailMongodbClient mongodb = new ProjectDetailMongodbClient();

// 2个都增加
public void add(ProjectDetail projectDetail) {
}


可以这么理解,原来直接使用ProjectDetailHbaseClient,方法名称都一样。
后台增加了ProjectDetailMongodbClient,方法的实现也一样,可以看作是一套接口的2套实现。
ProjectDetailClient的add等具体方法中,会处理2个接口的调用、数据同步等逻辑问题。

完整代码如下

  1. package com.hanhai.zrb.api.mongodb;
  2.  
  3. import java.util.List;
  4.  
  5. import org.apache.log4j.Logger;
  6.  
  7. import casia.isiteam.zrb.hbase.client.ProjectDetailHbaseClient;
  8.  
  9. import com.hanhai.zrb.model.project.ProjectDetail;
  10.  
  11. public class ProjectDetailClient {
  12. private ProjectDetailHbaseClient hbase = new ProjectDetailHbaseClient();
  13. private ProjectDetailMongodbClient mongodb = new ProjectDetailMongodbClient();
  14. private Logger log = Logger.getLogger(getClass());
  15.  
  16. // 2个都增加
  17. public void add(ProjectDetail projectDetail) {
  18. log.info("Add ProjectDetail for hbase.");
  19. hbase.insertProjectDetail(projectDetail);
  20. log.info("Add ProjectDetail for mongodb.");
  21. mongodb.add(projectDetail);
  22. }
  23.  
  24. // 2个都更新
  25. public void update(ProjectDetail projectDetail) {
  26. if (projectDetail.getId() == null) {
  27. log.error("ProjectDetail is is null,Cantnot update~");
  28. return;
  29. }
  30. Long id = projectDetail.getId();
  31.  
  32. ProjectDetail one = mongodb.get(id);
  33. // Mongodb,如果存在,更新
  34. if (one != null) {
  35. log.info("Update ProjectDetail,Mongodb exists,id="+id);
  36. mongodb.update(projectDetail);
  37. }
  38. // 不存在,就增加
  39. else {
  40. log.info("Update ProjectDetail,Mongodb not exists,id="+id);
  41. mongodb.add(projectDetail);
  42. }
  43.  
  44. // hbase增加和更新是同一个接口
  45. log.info("Update ProjectDetail for hbase,id="+id);
  46. hbase.insertProjectDetail(projectDetail);
  47. }
  48.  
  49. // 2个都查询,优先使用Mongodb
  50. public ProjectDetail get(long id) {
  51. ProjectDetail one = null;
  52. ProjectDetail hbaseOne = hbase.getProjectDetail(id);
  53. ProjectDetail mongodbOne = mongodb.get(id);
  54. if (mongodbOne != null) {
  55. one = mongodbOne;
  56. log.info("Project Detail,Mongodb exists,Use Mongodb," + one);
  57. } else if (hbaseOne != null) {
  58. one = hbaseOne;
  59. log.info("Project Detail,Mongodb not exists,Use Hbase," + one);
  60. log.info("Add Project Detail To Mongodb");
  61. // 同步Hbase中的数据到Mongodb
  62. mongodb.add(hbaseOne);
  63. }
  64. return one;
  65. }
  66.  
  67. // 2个都查询,优先使用Mongodb
  68. public List<ProjectDetail> getProjectInfoBasic(List<Long> idList) {
  69. List<ProjectDetail> list = null;
  70. List<ProjectDetail> hbaseList = hbase.getProjectInfoBasic(idList);
  71. List<ProjectDetail> mongodbList = mongodb.getProjectInfoBasic(idList);
  72. // 优先使用Mongodb中的,条件,Mongodb中的个数不小于hbase中的
  73. if (mongodbList != null) {
  74. int size = mongodbList.size();
  75. if (hbaseList == null || hbaseList.size() <= size) {
  76. list = mongodbList;
  77. log.info("ProjectDetail list,Use MongodbList,size=" + size);
  78. }else{
  79. list = hbaseList;
  80. log.info("ProjectDetail list,Use HbaseList,size=" + hbaseList.size()+",mongodb count "+size+" < hbase count "+hbaseList.size());
  81. }
  82. }
  83. // 其次使用Hbase中的,不会同步hbase中的数据到Mongodb
  84. else if (hbaseList != null) {
  85. list = hbaseList;
  86. log.info("ProjectDetail list,Use HbaseList,size=" + hbaseList.size());
  87. }
  88. return list;
  89. }
  90. }

  1. package com.hanhai.zrb.api.mongodb;
  2.  
  3. import java.util.ArrayList;
  4. import java.util.List;
  5.  
  6. import org.apache.log4j.Logger;
  7.  
  8. import com.hanhai.zrb.model.project.ProjectDetail;
  9. import com.mongodb.BasicDBList;
  10. import com.mongodb.BasicDBObject;
  11. import com.mongodb.CommandResult;
  12. import com.mongodb.DB;
  13. import com.mongodb.DBCollection;
  14. import com.mongodb.DBCursor;
  15. import com.mongodb.DBObject;
  16. import com.mongodb.WriteResult;
  17.  
  18. public class ProjectDetailMongodbClient {
  19.  
  20. public static final String CON_NAME = "projectDetail";
  21.  
  22. private Logger log = Logger.getLogger(getClass());
  23.  
  24. public void add(ProjectDetail projectDetail) {
  25. DBCollection con = getCon();
  26. add(con, projectDetail);
  27. }
  28.  
  29. private DBCollection getCon() {
  30. DB db = MongoUtil.db();
  31. DBCollection con = db.getCollection(CON_NAME);
  32. return con;
  33. }
  34.  
  35. // 增加
  36. private DBCollection add(DBCollection projectDetailCollection,
  37. ProjectDetail projectDetail) {
  38. DBObject object = BeanUtil.bean2DBObject(projectDetail);
  39. WriteResult wr = projectDetailCollection.insert(object);
  40. CommandResult cr = wr.getLastError();
  41. log.info("Add new projectDetail,result:" + cr);
  42. return projectDetailCollection;
  43. }
  44.  
  45. public void update(ProjectDetail projectDetail) {
  46. DBCollection con = getCon();
  47. update(con, projectDetail);
  48. }
  49.  
  50. // 修改
  51. private void update(DBCollection collection, ProjectDetail projectDetail) {
  52. if (projectDetail.getId() == null) {
  53. log.error("Update projectDetail,must have a unique id");
  54. return;
  55. }
  56.  
  57. BasicDBObject updateCondition = new BasicDBObject();
  58. updateCondition.append("id", projectDetail.getId());
  59.  
  60. DBObject newObject = BeanUtil.bean2DBObject(projectDetail);
  61.  
  62. DBObject updateSetValue = new BasicDBObject("$set", newObject);
  63. WriteResult wr = collection.update(updateCondition, updateSetValue);
  64. log.info("Update new projectDetail,result:" + wr);
  65. }
  66.  
  67. public ProjectDetail get(long id) {
  68. DBCollection con = getCon();
  69. ProjectDetail projectDetail = findById(con, id);
  70. return projectDetail;
  71. }
  72.  
  73. // 从集合中,根据ID查找
  74. private ProjectDetail findById(DBCollection collection, Long id) {
  75. BasicDBObject searchProjectDetailById = new BasicDBObject();
  76. searchProjectDetailById.append("id", id);
  77. ProjectDetail projectDetailBefore = null;
  78. // findOne方法更简单一些
  79. DBCursor cursor = collection.find(searchProjectDetailById);
  80. while (cursor.hasNext()) {
  81. DBObject articleObject = cursor.next();
  82. if (articleObject != null) {
  83. projectDetailBefore = objectToArticle(articleObject);
  84. String internalId = articleObject.get("_id").toString();
  85. projectDetailBefore.setMongoId(internalId);
  86. }
  87. }
  88. cursor.close();
  89. return projectDetailBefore;
  90. }
  91.  
  92. // 对象转换
  93. private ProjectDetail objectToArticle(DBObject object) {
  94. ProjectDetail projectDetail = new ProjectDetail();
  95. // 用工具方法转换,手动转换,需要判断类型,比较麻烦
  96. projectDetail = BeanUtil.dbObject2Bean(object, projectDetail);
  97. return projectDetail;
  98. }
  99.  
  100. public List<ProjectDetail> getProjectInfoBasic(List<Long> idList) {
  101. DBCollection con = getCon();
  102. List<ProjectDetail> list = findByIdList(con, idList);
  103. return list;
  104. }
  105.  
  106. // 根据ID集合查找
  107. private List<ProjectDetail> findByIdList(DBCollection collection,
  108. List<Long> idList) {
  109. BasicDBList values = new BasicDBList();
  110. values.addAll(idList);
  111.  
  112. DBObject inQuery = new BasicDBObject("$in", values);
  113.  
  114. DBObject con = new BasicDBObject();
  115. con.put("id", inQuery);
  116. DBCursor cursorIdArray = collection.find(con);
  117.  
  118. List<ProjectDetail> projectDetailList = new ArrayList<ProjectDetail>();
  119. while (cursorIdArray.hasNext()) {
  120. DBObject articleObject = cursorIdArray.next();
  121. ProjectDetail projectDetail = new ProjectDetail();
  122. BeanUtil.dbObject2Bean(articleObject, projectDetail);
  123. String mongoId = articleObject.get("_id").toString();
  124. projectDetail.setMongoId(mongoId);
  125.  
  126. projectDetailList.add(projectDetail);
  127. }
  128. return projectDetailList;
  129. }
  130.  
  131. }

ProjectDetailHbaseClient代码较为复杂,和ProjectDetailMongodbClient类似,不再贴了。

Mongodb总结5-通过装饰模式,用Mongodb解决Hbase的不稳定问题的更多相关文章

  1. mongoDb CPU利用率100%的分析和解决

    在公司的项目中,突然出现过一个情况,mongodb 的CPU利用率到达100%,导致服务器这边卡死了,请求了半天无响应,提示请求超时. 因为,当时APP用户可能会在某一个时间段集中的使用,所以,请求量 ...

  2. MongoDB学习:(二)MongoDB简单使用

    MongoDB学习:(二)MongoDB简单使用 MongoDB使用: 执行mongodb的操作之前,我们需要运行命令,来进入操作命令界面 >mongo 提示该错误,说明我们系统缺少一个补丁,该 ...

  3. MongoDB学习:(一)MongoDB安装

    MongoDB学习:(一)MongoDB安装 MongoDB介绍:     直接百科了: MongoDB安装: 1:下载安装: MongoDB安装:https://www.mongodb.com/do ...

  4. 基于C#的MongoDB数据库开发应用(1)--MongoDB数据库的基础知识和使用

    在花了不少时间研究学习了MongoDB数据库的相关知识,以及利用C#对MongoDB数据库的封装.测试应用后,决定花一些时间来总结一下最近的研究心得,把这个数据库的应用单独作为一个系列来介绍,希望从各 ...

  5. Mongodb 笔记09 备份、部署MongoDB

    备份 1. 只有在有信心能在紧急情况下完成迅速部署的情况下,备份才是有用的.所以,无论选择了哪种备份技术,一定要对备份及恢复备份的操作进行练习,知道了然于心. 2. 通常情况下,应对副本集的非主节点( ...

  6. MongoDB(索引及C#如何操作MongoDB)(转载)

    MongoDB(索引及C如何操作MongoDB) 索引总概况 db.test.ensureIndex({"username":1})//创建索引 db.test.ensureInd ...

  7. window服务器上mongodb的安装与如何将mongodb设置为服务,为mongodb设置管理用户,mongodb连接字符串配置

    最近公司有一个项目模块让用nosql-mongodb替换了,故,对mongodb做了一点研究,然后分享一下! 1.首先说一下安装时的坑 下载mongodb,如果你从官网下载,将会是一件很慢的事情,在公 ...

  8. 孤荷凌寒自学python第五十六天通过compass客户端和mongodb shell 命令来连接远端MongoDb数据库

    孤荷凌寒自学python第五十六天通过compass客户端和mongodb shell 命令来连接远端MongoDb数据库 (完整学习过程屏幕记录视频地址在文末) 今天是学习mongoDB数据库的第二 ...

  9. 搭建高可用mongodb集群(一)——mongodb配置主从模式

    转载自:LANCEYAN.COM 在大数据的时代,传统的关系型数据库要能更高的服务必须要解决高并发读写.海量数据高效存储.高可扩展性和高可用性这些难题.不过就是因为这些问题Nosql诞生了. NOSQ ...

随机推荐

  1. 在Ubuntu14.04中配置mysql远程连接教程

    上一篇文章,小编带大家学会了在Ubuntu14.04中安装MySQL,没有来得及上课的小伙伴们可以戳这篇文章:如何在Ubuntu14.04中安装mysql,今天给大家分享一下,如何简单的配置MySQL ...

  2. 紫书 习题 10-16 UVa 1647 (高精度+递推)

    这道题我已经推出00和1过两步变成00了,可我没有继续做下去-- 后来看了博客发现自己已经做了90%了-- 可惜了,以后不要轻易放弃. 1的个数有个规律,就是每次都乘以2,因为0和1下一步都会变出1 ...

  3. Swift实战(2)--在工程中添加object-C的类或者第三方框架(附翻译)

    原文地址:http://stackoverflow.com/questions/24002369/how-to-call-objective-c-code-from-swift Using Objec ...

  4. UINavigationController导航栏按钮设置

    UINavigationController常见属性 1.一般情况下,导航栏上面显示什么内容,由当前栈顶控制器的navigationItem属性决定 * navigationItem.title : ...

  5. C# textBox控件只允许为数字和小数点并且提取出这个数字

    一. textBox控件实现只允许为数字和小数点 如下图所示,在textBox控件框内输入只能是 要在textBox控件属性设置按键按下的事件触发,如下图所示: 二.源代码 textBox控件只允许为 ...

  6. 洛谷 P1900 自我数

    P1900 自我数 题目描述 在1949年印度数学家D. R. Daprekar发现了一类称作Self-Numbers的数.对于每一个正整数n,我们定义d(n)为n加上它每一位数字的和.例如,d(75 ...

  7. Android基础新手教程——1.2.1 使用Eclipse + ADT + SDK开发Android APP

    Android基础新手教程--1.2.1 使用Eclipse + ADT + SDK开发Android APP 标签(空格分隔): Android基础新手教程 1.前言 这里我们有两条路能够选,直接使 ...

  8. C++反射机制:可变参数模板实现C++反射(使用C++11的新特性--可变模版参数,只根据类的名字(字符串)创建类的实例。在Nebula高性能网络框架中大量应用)

    1. 概要   本文描述一个通过C++可变参数模板实现C++反射机制的方法.该方法非常实用,在Nebula高性能网络框架中大量应用,实现了非常强大的动态加载动态创建功能.Nebula框架在码云的仓库地 ...

  9. uva725(除法)

    Description Write a program that finds and displays all pairs of 5-digit numbers that between them u ...

  10. 强悍的 vim —— 删除空行、删除注释以及加注释解注释

    强悍的 vim -- 删除空行.删除注释以及加注释解注释 原文 https://blog.csdn.net/lanchunhui/article/details/51588198 1. 删除空行空行的 ...