public class DayInterval implements ServletContextListener{ private static SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); public static void showDayTime() { Timer dTimer = new Timer(); dTimer.schedule(new TimerTask() { @Override public void run() { System.out.println("每日任务执行:"+simpleDateFormat.format(new Date())); LogTableCreate logTableCreate = new LogTableCreate(); Thread thread=new Thread(logTableCreate); thread.start(); } }, 1000 , 24* 60* 60 * 1000);//24* 60* 60 * 1000(第一次一秒后执行,以后每次一天后执行) } @Override public void contextDestroyed(ServletContextEvent arg0) { // showDayTime(); } @Override public void contextInitialized(ServletContextEvent arg0) { showDayTime(); } }
LogTableCreate 用来做表分表是否已经创建,如现在是9月在启动时检查是否存在当月表记录,不存在则创建存在则不创建,另外检查是否存在10月份表记录,不存在则创建(提前创建一个也空表,以此类推)。
拷贝代码修改createsql(建表sql),URL (数据库地址),USER (数据库连接用户),PASSWORD(数据库连接密码)
public class LogTableCreate extends TimerTask { private static final Log log = LogFactory.getLog(LogTableCreate.class); public static final String TBASENAME="tb_log"; private String createsql = " (\r\n" + " `ID` varchar(64) NOT NULL COMMENT '主键id',\r\n" + " `userid` varchar(255) DEFAULT NULL COMMENT '用户id',\r\n" + " `username` varchar(255) DEFAULT NULL COMMENT '用户姓名',\r\n" + " `useridcard` varchar(255) DEFAULT NULL COMMENT '用户身份证号码',\r\n" + " `realname` varchar(64) DEFAULT NULL COMMENT '真实姓名',\r\n" + " `logintime` varchar(255) DEFAULT NULL COMMENT '登录时间',\r\n" + " `exittime` varchar(64) DEFAULT NULL COMMENT '退出时间',\r\n" + " `ippath` varchar(255) DEFAULT NULL COMMENT 'ip地址',\r\n" + " `macpath` varchar(255) DEFAULT NULL COMMENT 'mac地址',\r\n" + " `usercreatedtime` varchar(255) DEFAULT NULL COMMENT '用户创建时间',\r\n" + " `userbusidaddress` varchar(255) DEFAULT NULL COMMENT '用户钱包地址',\r\n" + " `member` int(11) DEFAULT NULL COMMENT '是否是会员',\r\n" + " `membertype` int(11) DEFAULT NULL COMMENT '会员类型',\r\n" + " `spare1` varchar(255) DEFAULT NULL,\r\n" + " `spare2` varchar(255) DEFAULT NULL,\r\n" + " `spare3` varchar(255) DEFAULT NULL,\r\n" + " PRIMARY KEY (`ID`)\r\n" + ")"; private SimpleDateFormat sdyyyy = new SimpleDateFormat("yyyy"); private SimpleDateFormat sdmm = new SimpleDateFormat("MM"); private static final String URL = ""; private static final String USER = ""; private static final String PASSWORD = ""; //得到表名 public static String gettable() { Date date = new Date(); LogTableCreate logTableCreate=new LogTableCreate(); String yyyy = logTableCreate.sdyyyy.format(date); String mm = logTableCreate.sdmm.format(date); String nmm = logTableCreate.getNextMM(mm); return TBASENAME+yyyy+mm; } //得到下一个月 private String getNextMM(String mm){ String nmm = ""; int imm = Integer.parseInt(mm); if(imm>=12){ nmm = "01"; }else{ imm++; if(imm>9) nmm = ""+imm; else nmm = "0"+imm; } return nmm; } @Override public void run() { Date date = new Date(); String yyyy = sdyyyy.format(date); String mm = sdmm.format(date); String nmm = getNextMM(mm); String nyyyy = ""; if("01".equals(nmm)){ nyyyy = ""+(Integer.parseInt(yyyy)+1); }else{ nyyyy = yyyy; } log.info("日志表检查及创建:"+yyyy+" - "+mm+" | "+nyyyy+"-"+nmm); String temp = TBASENAME+yyyy+mm; //日志表名称 boolean has = false; try{ has = hasTable(temp); }catch(Exception e){ log.error("当前操作日志表是否存在判断时发生错误:"+e.getMessage()); return; } if(!has){ try{ createTable(temp); }catch(Exception e){ log.error("当前操作日志表创建时发生错误:"+e.getMessage()); return; } } temp = TBASENAME+nyyyy+nmm; has = false; try{ has = hasTable(temp); }catch(Exception e){ log.error("待用日志表是否存在判断时发生错误:"+e.getMessage()); return; } if(!has){ try{ createTable(temp); }catch(Exception e){ log.error("待用日志表创建时发生错误:"+e.getMessage()); return; } } log.info("日志表检查及创建结束"); } public boolean hasTable(String table) throws Exception{ Class.forName("com.mysql.jdbc.Driver"); //2. 获得数据库连接 Connection conn = DriverManager.getConnection(URL, USER, PASSWORD); boolean state = false; DatabaseMetaData meta = conn.getMetaData(); ResultSet set; set = meta.getTables(null, null, table.toLowerCase(), null); while (set.next()) { state = true; break; } Statement stmt = null; try{ stmt = conn.createStatement(); }catch(Exception e){ log.error("检查日志表是否存在时发生错误:"+e.getMessage()); throw e; }finally{ if(stmt!=null) try { stmt.close(); } catch (Exception e) { //e.printStackTrace(); } } conn.close(); return state; } public void createTable(String table)throws Exception{ try{ Class.forName("com.mysql.jdbc.Driver"); //2. 获得数据库连接 Connection conn = DriverManager.getConnection(URL, USER, PASSWORD); String sql = "create table "+table+createsql; Statement stmt = null; stmt = conn.createStatement(); stmt.execute(sql); }catch(Exception e){ log.error("初始化日志表时发生错误:"+e.getMessage()); throw e; } } }
补充:java水平分表_Java开发分库分表需要解决的问题及mycat是怎样实现分库分表的
从字面上简单理解,就是把原本存储于一个库的数据分块存储到多个库上,把原本存储于一个表的数据分块存储到多个表上。
数据库中的数据量不一定是可控的,在未进行分库分表的情况下,随着时间和业务的发展,库中的表会越来越多,表中的数据量也会越来越大,相应地,数据操作,增删改查的开销也会越来越大;
另外,由于无法进行分布式式部署,而一台服务器的资源(CPU、磁盘、内存、IO等)是有限的,最终数据库所能承载的数据量、数据处理能力都将遭遇瓶颈。
首先我们来了解一下为什么要做分库分表。在我们的业务(web应用)中,关系型数据库本身比较容易成为系统性能瓶颈,单机存储容量、连接数、处理能力等都很有限,数据库本身的“有状态性”导致了它并不像Web和应用服务器那么容易扩展。那么在我们的业务中,是否真的有必要进行分库分表,就可以从上面几个条件来考虑。
单机储存容量。您的数据量是否在单机储存中碰到瓶颈。比如饿了么一天产生的用户行为数据就有24T,那么在传统的单机储存中肯定是不够的。
连接数、处理能力。在我们的用户量达到一定程度时,特定时间的并发量又成了一个大问题,在一个高并发的网站中秒级数十万的并发量都是很正常的。在普通的单机数据库中秒级千次的操作问题都很大。
所以在我们进行分库分表之前我们最好考虑一下,我们的数据量是不是够大,并发量是不是够大。如果您的回答是肯定的,那我们就开始做吧。
解决事务问题目前有两种可行的方案:分布式事务和通过应用程序与数据库共同控制实现事务下面对两套方案进行一个简单的对比。
优点:交由数据库管理,简单有效
缺点:性能代价高,特别是shard越来越多时
原理:将一个跨多个数据库的分布式事务分拆成多个仅处 于单个数据库上面的小事务,并通过应用程序来总控 各个小事务。
优点:性能上有优势
缺点:需要应用程序在事务控制上做灵活设计。如果使用 了spring的事务管理,改动起来会面临一定的困难。
分库分表的实施策略。
分库分表有垂直切分和水平切分两种。
3.1 何谓垂直切分,即将表按照功能模块、关系密切程度划分出来,部署到不同的库上。
例如,我们会建立定义数据库workDB、商品数据库payDB、用户数据库userDB、日志数据库logDB等,分别用于存储项目数据定义表、商品定义表、用户数据表、日志数据表等。
3.2 何谓水平切分,当一个表中的数据量过大时,我们可以把该表的数据按照某种规则,例如userID散列,进行划分,然后存储到多个结构相同的表,和不同的库上。
例如,我们的userDB中的用户数据表中,每一个表的数据量都很大,就可以把userDB切分为结构相同的多个userDB:part0DB、part1DB等,再将userDB上的用户数据表userTable,切分为很多userTable:userTable0、userTable1等,然后将这些表按照一定的规则存储到多个userDB上。
3.3 应该使用哪一种方式来实施数据库分库分表,这要看数据库中数据量的瓶颈所在,并综合项目的业务类型进行考虑。
如果数据库是因为表太多而造成海量数据,并且项目的各项业务逻辑划分清晰、低耦合,那么规则简单明了、容易实施的垂直切分必是首选。
而如果数据库中的表并不多,但单表的数据量很大、或数据热度很高,这种情况之下就应该选择水平切分,水平切分比垂直切分要复杂一些,它将原本逻辑上属于一体的数据进行了物理分割,除了在分割时要对分割的粒度做好评估,考虑数据平均和负载平均,后期也将对项目人员及应用程序产生额外的数据管理负担。
在现实项目中,往往是这两种情况兼而有之,这就需要做出权衡,甚至既需要垂直切分,又需要水平切分。我们的游戏项目便综合使用了垂直与水平切分,我们首先对数据库进行垂直切分,然后,再针对一部分表,通常是用户数据表,进行水平切分。
mycat是怎样实现分库分表的?mycat里面通过定义路由规则来实现分片表(路由规则里面会定义分片字段,以及分片算法)。分片算法有多种,你所说的hash是其中一种,还有取模、按范围分片等等。在mycat里面,会对所有传递的sql语句做路由处理(路由处理的依据就是表是否分片,如果分片,那么需要依据分片字段和对应的分片算法来判断sql应该传递到哪一个、或者哪几个、又或者全部节点去执行)
以上就是我对Java开发分库分表需要解决的问题及mycat是怎样实现分库分表的 问题及其优化总结,如有错误或未考虑完全的地方,望不吝赐教。
本文向大家介绍Java 数据结构链表操作实现代码,包括了Java 数据结构链表操作实现代码的使用技巧和注意事项,需要的朋友参考一下 链表是一种复杂的数据结构,其数据之间的相互关系使链表分成三种:单链表、循环链表、双向链表,下面将逐一介绍。链表在数据结构中是基础,也是重要的知识点,这里讲下Java 中链表的实现, JAVA 链表操作:单链表和双链表 主要讲述几点: 一、链表的简介 二、链表实现原理
本文向大家介绍hibernate多表操作实例代码,包括了hibernate多表操作实例代码的使用技巧和注意事项,需要的朋友参考一下 多表操作之多对多关系简介 思路就是: 在数据库底层通过添加中间表来指定关联关系。 在双方的实体中添加一个保存对方的集合 在双方的配置文件中使用set标签和many-to-many标签来进行关联关系的配置。即可完成! 调用Hibernate的相关的API,操作就行了。
本文向大家介绍Java实现操作excel表格,包括了Java实现操作excel表格的使用技巧和注意事项,需要的朋友参考一下 最近老师布置了个任务,用Java对excel后缀名为xlsx的文件进行简单的增,删,改,查操作;虽说是个简单的程序,可作为刚接触的我来说还是有些磕磕碰碰。不过好在还是完成了,进行一个简单的总结。 首先导入了一个poi.jar 网上有很多这个资源可以下载 XSSFShe
本文向大家介绍Java实现用Mysql存取图片操作实例,包括了Java实现用Mysql存取图片操作实例的使用技巧和注意事项,需要的朋友参考一下 1.MySQL中的BLOB类型 Mysql中可以存储大文件数据,一般使用的BLOB对象。如图片,视频等等。 BLOB是一个二进制大对象,可以容纳可变数量的数据。因为是二进制对象,所以与编码方式无关。有4种BLOB类型:TINYBLOB、BLOB、M
本文向大家介绍Python操作使用MySQL数据库的实例代码,包括了Python操作使用MySQL数据库的实例代码的使用技巧和注意事项,需要的朋友参考一下 Python 操作 MySQL 配置 win_64 Ubuntu14.04 Python3.x pip安装pymysql模块 直接使用pip安装 pip install pymysql win64上直接在cmd中执行 连接本地数据库 使用模块p
本文向大家介绍C#代码实现PDF文档操作类,包括了C#代码实现PDF文档操作类的使用技巧和注意事项,需要的朋友参考一下 本文纯干货,贴上PDF文档操作类C#代码,需要添加iTextSharp.dll引用才可以正常通过编译。 废话不多说了,直接给大家贴代码了。 代码如下: 呐喊教程友情提醒需要注意点:需要添加iTextSharp.dll引用才可以正常通过编译。