分布式切换历史库总结
1要有三个类分别是dubbo自定义filter,DataSource,存放的常量DataSoursePro
service层
1DubboProviderContextFilter
@Activate(group = Constants.PROVIDER)
public class DubboProviderContextFilter implements Filter {private Logger logger = LoggerFactory.getLogger(this.getClass());@Overridepublic Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {Result result = null;getAttachment(invoker, invocation);//执行业务逻辑result = invoker.invoke(invocation);return result;}private void getAttachment(Invoker<?> invoker, Invocation invocation) {try {Map<String, String> attachments = RpcContext.getContext().setInvoker(invoker).setInvocation(invocation).getAttachments();String username = attachments.get("db_username");String password = attachments.get("db_password");//设置动态数据源用户名密码ProviderDataSoursePro.getInstance().setUserName(username);ProviderDataSoursePro.getInstance().setPassWord(password);} catch (Exception e) {e.printStackTrace();}}
}
2DynamicDataSource
public class DynamicDataSource implements DataSource {private static final Map dataSources = new HashMap();private DataSource defaultDataSource = null;private DataSource dataSource = null;public Connection getConnection() throws SQLException {return getDataSource().getConnection();}public Connection getConnection(String arg0, String arg1) throws SQLException {return getDataSource().getConnection(arg0, arg1);}public PrintWriter getLogWriter() throws SQLException {return getDataSource().getLogWriter();}public int getLoginTimeout() throws SQLException {return getDataSource().getLoginTimeout();}public void setLogWriter(PrintWriter arg0) throws SQLException {getDataSource().setLogWriter(arg0);}public void setLoginTimeout(int arg0) throws SQLException {getDataSource().setLoginTimeout(arg0);}public DataSource getDataSource(String dataSourceName) {System.out.println("service.getDataSource("+dataSourceName+")");if ((dataSourceName == null) || (dataSourceName.equals(""))) {return this.dataSource;}if (dataSources.get(dataSourceName) != null) {return (DataSource) dataSources.get(dataSourceName);}return createDataSource(ProviderDataSoursePro.getInstance().getUserName(),ProviderDataSoursePro.getInstance().getPassWord());}public void setDataSource(DataSource dataSource) {this.dataSource = dataSource;}public DataSource getDataSource() {System.out.println("service.getDataSource()");String sp = ProviderDataSoursePro.getInstance().getUserName();return getDataSource(sp);}public DataSource createDataSource(String userName, String password) {System.out.println("service.createDataSource:userName="+userName+";password="+password);DruidDataSource s = new DruidDataSource();DruidDataSource ts = (DruidDataSource) this.defaultDataSource;s.setUsername(userName);s.setPassword(password);s.setUrl(ts.getUrl());s.setDriverClassName(ts.getDriverClassName());dataSources.put(userName, s);return s;}public DataSource getDefaultDataSource() {return this.defaultDataSource;}public void setDefaultDataSource(DataSource defaultDataSource) {this.defaultDataSource = defaultDataSource;}public boolean isWrapperFor(Class<?> iface) throws SQLException {return false;}public <T> T unwrap(Class<T> iface) throws SQLException {return null;}@Overridepublic Logger getParentLogger() throws SQLFeatureNotSupportedException {return null;} }
3ProviderDataSoursePro
public class ProviderDataSoursePro {private String userName;private String passWord;private static ProviderDataSoursePro instance = null;public static ProviderDataSoursePro getInstance() {if (instance == null) {instance = new ProviderDataSoursePro();}return instance;}public String getUserName() {return userName;}public void setUserName(String userName) {this.userName = userName;}public String getPassWord() {return passWord;}public void setPassWord(String passWord) {this.passWord = passWord;} }
4数据源连接池xml配置(利用DruidDataSource连接)
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dynamicDataSource"></property></bean><!-- 一、使用druid数据库连接池注册数据源 --><bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"><!-- 基础配置 --><property name="url" value="${jdbc.url}"></property><property name="driverClassName" value="${jdbc.driverClassName}"></property><property name="username" value="${jdbc.username}"></property><property name="password" value="${jdbc.password}"></property><!-- 关键配置 --><!-- 初始化时建立物理连接的个数。初始化发生在显示调用init方法,或者第一次getConnection时 --><property name="initialSize" value="${jdbc.initialSize}"/><!-- 最小连接池数量 --><property name="minIdle" value="${jdbc.minIdle}"/><!-- 最大连接池数量 --><property name="maxActive" value="${jdbc.maxActive}"/><!-- 配置获取连接等待超时的时间 --><property name="maxWait" value="${jdbc.maxWait}"/><!-- 性能配置 --><!-- 打开PSCache,并且指定每个连接上PSCache的大小 --><property name="poolPreparedStatements" value="true"/><property name="maxPoolPreparedStatementPerConnectionSize" value="20"/></bean><bean id="dynamicDataSource_template" class="com.alibaba.druid.pool.DruidDataSource"><!-- 基础配置 --><property name="url" value="${jdbc.url}"></property><property name="driverClassName" value="${jdbc.driverClassName}"></property><property name="username" value="${jdbc.username}"></property><property name="password" value="${jdbc.password}"></property><!-- 关键配置 --><!-- 初始化时建立物理连接的个数。初始化发生在显示调用init方法,或者第一次getConnection时 --><property name="initialSize" value="${jdbc.initialSize}"/><!-- 最小连接池数量 --><property name="minIdle" value="${jdbc.minIdle}"/><!-- 最大连接池数量 --><property name="maxActive" value="${jdbc.maxActive}"/><!-- 配置获取连接等待超时的时间 --><property name="maxWait" value="${jdbc.maxWait}"/><!-- 性能配置 --><!-- 打开PSCache,并且指定每个连接上PSCache的大小 --><property name="poolPreparedStatements" value="true"/><property name="maxPoolPreparedStatementPerConnectionSize" value="20"/></bean><bean id="dynamicDataSource" class="com.itsv.gbp.core.ds.DynamicDataSource"><property name="dataSource"><ref bean="dataSource" /></property><property name="defaultDataSource"><ref bean="dynamicDataSource_template" /></property></bean>
5jdbc.properties文件
jdbc.driverClassName=oracle.jdbc.driver.OracleDriver
jdbc.url=jdbc:oracle:thin:@192.168.1.250:1521:orcl
jdbc.username=jgbzsmz_qinghai
jdbc.password=1jdbc.maxActive=30
jdbc.initialSize=5
jdbc.minIdle=1
jdbc.maxWait=10000
6层级自定义过滤器dubboProviderContextFilter的xml配置(附带分布式的配置
<dubbo:application name="jgbzsmz_qinghai_service"/><dubbo:registry address="zookeeper://127.0.0.1:2181" check="false" timeout="600000"/><dubbo:protocol name="dubbo" port="20880"/><dubbo:annotation package="com.itsv"/><dubbo:provider filter="dubboProviderContextFilter" />
7maven检索resources下的META-INF.dubbo的配置
<resource><targetPath>${project.build.directory}/classes</targetPath><directory>src/main/resources</directory><filtering>true</filtering><includes><include>**/*.*</include></includes></resource>
web层
1DubboConsumerContextFilter
@Activate(group = Constants.CONSUMER)
public class DubboConsumerContextFilter implements Filter {@Overridepublic Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {Result result = null;setAttachment(invoker, invocation);try {//执行业务逻辑result = invoker.invoke(invocation);} catch (RpcException e) {throw e;} finally {//清理RpcContext.getContext().clearAttachments();}return result;}private void setAttachment(Invoker<?> invoker, Invocation invocation) {//获取动态数据源用户名密码String username = ConsumerDataSoursePro.getInstance().getUserName();String password = ConsumerDataSoursePro.getInstance().getPassWord();try {RpcContext.getContext().setInvoker(invoker).setInvocation(invocation).setAttachment("db_username", username).setAttachment("db_password", password);} catch (Exception e) {e.printStackTrace();}}
}
2 DynamicDataSource
public class DynamicDataSource implements DataSource {private static final Map dataSources = new HashMap();private DataSource defaultDataSource = null;private DataSource dataSource = null;public Connection getConnection() throws SQLException {return getDataSource().getConnection();}public Connection getConnection(String arg0, String arg1) throws SQLException {return getDataSource().getConnection(arg0, arg1);}public PrintWriter getLogWriter() throws SQLException {return getDataSource().getLogWriter();}public int getLoginTimeout() throws SQLException {return getDataSource().getLoginTimeout();}public void setLogWriter(PrintWriter arg0) throws SQLException {getDataSource().setLogWriter(arg0);}public void setLoginTimeout(int arg0) throws SQLException {getDataSource().setLoginTimeout(arg0);}public DataSource getDataSource(String dataSourceName) {System.out.println("service.getDataSource("+dataSourceName+")");if ((dataSourceName == null) || (dataSourceName.equals(""))) {return this.dataSource;}if (dataSources.get(dataSourceName) != null) {return (DataSource) dataSources.get(dataSourceName);}return createDataSource(ConsumerDataSoursePro.getInstance().getUserName(),ConsumerDataSoursePro.getInstance().getPassWord());}public void setDataSource(DataSource dataSource) {this.dataSource = dataSource;}public DataSource getDataSource() {System.out.println("service.getDataSource()");String sp = ConsumerDataSoursePro.getInstance().getUserName();return getDataSource(sp);}public DataSource createDataSource(String userName, String password) {System.out.println("service.createDataSource:userName="+userName+";password="+password);DruidDataSource s = new DruidDataSource();DruidDataSource ts = (DruidDataSource) this.defaultDataSource;s.setUsername(userName);s.setPassword(password);s.setUrl(ts.getUrl());s.setDriverClassName(ts.getDriverClassName());dataSources.put(userName, s);return s;}public DataSource getDefaultDataSource() {return this.defaultDataSource;}public void setDefaultDataSource(DataSource defaultDataSource) {this.defaultDataSource = defaultDataSource;}public boolean isWrapperFor(Class<?> iface) throws SQLException {return false;}public <T> T unwrap(Class<T> iface) throws SQLException {return null;}@Overridepublic Logger getParentLogger() throws SQLFeatureNotSupportedException {return null;}
}
3ConsumerDataSoursePro
public class ConsumerDataSoursePro {private String userName;private String passWord;private static ConsumerDataSoursePro instance = null;public static ConsumerDataSoursePro getInstance() {if (instance == null) {instance = new ConsumerDataSoursePro();}return instance;}public String getUserName() {return userName;}public void setUserName(String userName) {this.userName = userName;}public String getPassWord() {return passWord;}public void setPassWord(String passWord) {this.passWord = passWord;}
}
4数据源连接池xml配置(利用DruidDataSource连接)
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dynamicDataSource"></property></bean><!-- 一、使用druid数据库连接池注册数据源 --><bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"><!-- 基础配置 --><property name="url" value="${jdbc.url}"></property><property name="driverClassName" value="${jdbc.driverClassName}"></property><property name="username" value="${jdbc.username}"></property><property name="password" value="${jdbc.password}"></property><!-- 关键配置 --><!-- 初始化时建立物理连接的个数。初始化发生在显示调用init方法,或者第一次getConnection时 --><property name="initialSize" value="${jdbc.initialSize}"/><!-- 最小连接池数量 --><property name="minIdle" value="${jdbc.minIdle}"/><!-- 最大连接池数量 --><property name="maxActive" value="${jdbc.maxActive}"/><!-- 配置获取连接等待超时的时间 --><property name="maxWait" value="${jdbc.maxWait}"/><!-- 性能配置 --><!-- 打开PSCache,并且指定每个连接上PSCache的大小 --><property name="poolPreparedStatements" value="true"/><property name="maxPoolPreparedStatementPerConnectionSize" value="20"/></bean><bean id="dynamicDataSource_template" class="com.alibaba.druid.pool.DruidDataSource"><!-- 基础配置 --><property name="url" value="${jdbc.url}"></property><property name="driverClassName" value="${jdbc.driverClassName}"></property><property name="username" value="${jdbc.username}"></property><property name="password" value="${jdbc.password}"></property><!-- 关键配置 --><!-- 初始化时建立物理连接的个数。初始化发生在显示调用init方法,或者第一次getConnection时 --><property name="initialSize" value="${jdbc.initialSize}"/><!-- 最小连接池数量 --><property name="minIdle" value="${jdbc.minIdle}"/><!-- 最大连接池数量 --><property name="maxActive" value="${jdbc.maxActive}"/><!-- 配置获取连接等待超时的时间 --><property name="maxWait" value="${jdbc.maxWait}"/><!-- 性能配置 --><!-- 打开PSCache,并且指定每个连接上PSCache的大小 --><property name="poolPreparedStatements" value="true"/><property name="maxPoolPreparedStatementPerConnectionSize" value="20"/></bean><bean id="dynamicDataSource" class="com.itsv.gbp.core.ds.DynamicDataSource"><property name="dataSource"><ref bean="dataSource" /></property><property name="defaultDataSource"><ref bean="dynamicDataSource_template" /></property></bean>
5jdbc.properties文件
jdbc.driverClassName=oracle.jdbc.driver.OracleDriver
jdbc.url=jdbc:oracle:thin:@192.168.1.250:1521:orcl
jdbc.username=jgbzsmz_qinghai
jdbc.password=1jdbc.maxActive=30
jdbc.initialSize=5
jdbc.minIdle=1
jdbc.maxWait=10000
6层级自定义过滤器dubboProviderContextFilter的xml配置(附带分布式的配置)
<dubbo:application name="jgbzsmz_qinghai_web"/><dubbo:registry address="zookeeper://127.0.0.1:2181" check="false"/><dubbo:consumer check="false" retries="0" timeout="600000" filter="dubboConsumerContextFilter"/>
7maven检索resources下的META-INF.dubbo的配置
<resource><targetPath>${project.build.directory}/classes</targetPath><directory>src/main/resources</directory><filtering>true</filtering><includes><include>**/*.*</include></includes></resource>
2模拟登陆
通过获取已经在缓存中username来找到他对应的password
在重新创建的jdbc的配置文件中获取url_lsk来实现二次登录历史库
public class SSOController implements Controller {private RedisTemplate<String, String> redisTemplate;@Overridepublic ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) {SessionUser suser = SecureTool.getCurrentLoginUser();String username = suser.getUserName();String original_pwd = redisTemplate.opsForValue().get(username);//从redis获取key的value值byte[] src = original_pwd.getBytes();String password = Endecrypt.getBase64Encode(src); // String password =original_pwd;//获取jdbc.properties配置文件中url_lskInputStream input = null;try {input = new FileInputStream(new File(request.getRealPath("") + "/WEB-INF/config/jdbc.properties"));} catch (FileNotFoundException e) {e.printStackTrace();}Properties pro = new Properties();try {pro.load(input);} catch (IOException e) {e.printStackTrace();}String url_lsk = pro.getProperty("url_lsk");String lsk_id = request.getParameter("p_id");url_lsk += lsk_id;//url添加lsk_id参数HttpSession usersession = request.getSession(false);usersession.invalidate();//模拟登陆PrintWriter out;try {out = response.getWriter();out.print("<script type='text/javascript'>");out.print("document.write(\"<form id='url' method='post' action='"+url_lsk+"'>\");");out.print("document.write(\"<input type='hidden' name='j_username' value='" +username + "' />\");");out.print("document.write(\"<input type='hidden' name='j_password' value='"+password+"' />\");");out.print("document.write(\"<input type='hidden' name='j_captcha_response' />\");");out.print("document.write('</form>');");out.print("document.getElementById('url').submit();");out.print("</script>");} catch (IOException e) {e.printStackTrace();}return null;}public RedisTemplate<String, String> getRedisTemplate() {return redisTemplate;}public void setRedisTemplate(RedisTemplate<String, String> redisTemplate) {this.redisTemplate = redisTemplate;}}
3在已有的LoginAuthenticationSuccesssHandler(security-end.xml 中配好)中模拟登录后,进入该方法时插入(注意SpObserver等同于web层ConsumerDataSoursePro)
SpObserver.putName(lsk.getBf_standby1()); SpObserver.putPass(lsk.getBf_standby2());
后,在经过web层的自定义的过滤器和DataSource,最后就会成功进入备用历史库了(经过
DubboConsumerContextFilter的setAttachment方法进行插入username和password然后在DubboProviderContextFilter的getAttachment进行接收然后在service层进行换库)
public class LoginAuthenticationSuccesssHandler implementsAuthenticationSuccessHandler {private Logger log = Logger.getLogger(LoginAuthenticationSuccesssHandler.class);private String defaultUrl;private String defaultUrl2;private String defaultUrl3;private String defaultUrl4;private Sys_logService sys_logService;public void setSys_logService(Sys_logService sys_logService) {this.sys_logService = sys_logService;}private GlobalConfig globalconfig;public void setGlobalconfig(GlobalConfig globalconfig) {this.globalconfig = globalconfig;}private LskService lskService;private RedisTemplate<String, Object> redisTemplate;public RedisTemplate<String, Object> getRedisTemplate() {return redisTemplate;}public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) {this.redisTemplate = redisTemplate;}public void setLskService(LskService lskService) {this.lskService = lskService;}/* (non-Javadoc)* @see org.springframework.security.web.authentication.AuthenticationSuccessHandler#onAuthenticationSuccess(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, org.springframework.security.core.Authentication)*/@Overridepublic void onAuthenticationSuccess(HttpServletRequest request,HttpServletResponse response, Authentication authentication) throws IOException,ServletException {if(log.isDebugEnabled()){log.debug("验证完成");}String username = request.getParameter("j_username");Map<String,Integer> pwdWrongMap = globalconfig.getPwdWrongMap();Map<String,String> deployconfigMap = globalconfig.getDeployConfigMap();String position = deployconfigMap.get("position");ServletContext application = request.getSession().getServletContext();if(pwdWrongMap.containsKey(username)){pwdWrongMap.put(username, 0);}String lsk_id = request.getParameter("lsk_id");if(lsk_id != null){try {Lsk lsk = this.lskService.queryByBfid(lsk_id);SpObserver.putName(lsk.getBf_standby1());SpObserver.putPass(lsk.getBf_standby2());request.getSession().removeAttribute("treeObject");request.getSession().setAttribute("dynamicDataSource_UserName", lsk.getBf_standby1());request.getSession().setAttribute("dynamicDataSource_UserPass", lsk.getBf_standby2());request.getSession().setAttribute("dynamicDataSource_Date", lsk.getBf_sj());request.getSession().setAttribute("lsk", lsk);redisTemplate.opsForValue().set("lsk", lsk);//向redis中存储lskresponse.sendRedirect("/main.do");} catch (IOException e) {e.printStackTrace();}}else{//201506 判断用户是否第一次登录系统,第一次强制修改密码UserInfoAdapter localUser = (UserInfoAdapter) authentication.getPrincipal();Sys_log sys_log = new Sys_log();sys_log.setLog_optype("登录");sys_log.setLog_user(username);sys_log.setLog_standby1("login");List<Sys_log> list = sys_logService.queryByVO(sys_log);Calendar calendar = Calendar.getInstance();calendar.setTime(localUser.getUser().getPwd_setDate()==null?new java.util.Date():localUser.getUser().getPwd_setDate());calendar.add(Calendar.DATE, 7);Date pwd_expiredate = calendar.getTime();application.setAttribute("positionSession", position);if(list==null || list.size()==0 /*第一登录*/ ||(localUser.getUser().getIf_modpwd() != null && localUser.getUser().getIf_modpwd())/*管理员改密码*/||(pwd_expiredate.before(new java.util.Date())) /*密码过期*/){application.setAttribute("login_userid", localUser.getUser().getId());application.setAttribute("login_username", localUser.getUser().getUserName());if(localUser.getUser().getIf_modpwd() != null && localUser.getUser().getIf_modpwd()){response.sendRedirect(request.getContextPath()+defaultUrl3);return;}//20160612 仅中央版本用密码过期强制修改if(localUser.getUser().getPwd_setDate() !=null && localUser.getUser().getPwd_setDate().before(new java.util.Date())){if(Constants.QUHUA_ZY.equals(position)){response.sendRedirect(request.getContextPath()+defaultUrl4);return;}else{//地方版本不强制修改,正常通过response.sendRedirect(request.getContextPath()+defaultUrl);return;}}if(list==null || list.size()==0){response.sendRedirect(request.getContextPath()+defaultUrl2);return;}}else{response.sendRedirect(request.getContextPath()+defaultUrl);return;}}}/*** @param defaultUrl the defaultUrl to set*/public void setDefaultUrl(String defaultUrl) {this.defaultUrl = defaultUrl;}public void setDefaultUrl2(String defaultUrl2) {this.defaultUrl2 = defaultUrl2;}public void setDefaultUrl3(String defaultUrl3) {this.defaultUrl3 = defaultUrl3;}public void setDefaultUrl4(String defaultUrl4) {this.defaultUrl4 = defaultUrl4;}}
注意自定义过滤器需要实现com.alibaba.dubbo.rpc.Filter接口!!!
注意自定义过滤器需要实现com.alibaba.dubbo.rpc.Filter接口!!!
注意自定义过滤器需要实现com.alibaba.dubbo.rpc.Filter接口!!!
3退出历史库经过exitbak方法
首先将相关session中的参数删除掉,然后将常量(SpObserver等同于web的ConsumerDataSourseProlieli里的内容置null这样就可以恢复默认数据源)
public ModelAndView exitBak(HttpServletRequest request, HttpServletResponse response) {try {request.getSession().removeAttribute("treeObject");request.getSession().removeAttribute("dynamicDataSource_UserName");request.getSession().removeAttribute("dynamicDataSource_UserPass");request.getSession().removeAttribute("dynamicDataSource_Date");request.getSession().removeAttribute("lsk");request.getSession().removeAttribute("odbc");SpObserver.putName(null);SpObserver.putPass(null);SessionUser suser = SecureTool.getCurrentLoginUser();String username = suser.getUserName();String original_pwd = redisTemplate.opsForValue().get(username).toString();//从redis获取key的value值byte[] src = original_pwd.getBytes();String password = Endecrypt.getBase64Encode(src);//获取jdbc.properties配置文件中url_mainInputStream input = null;try {//input = new FileInputStream(new File(request.getRealPath("") + "/WEB-INF/config/jdbc.properties"));input = new FileInputStream(new File(this.getServletContext().getRealPath("") + "/WEB-INF/config/jdbc.properties"));} catch (FileNotFoundException e) {e.printStackTrace();}Properties pro = new Properties();try {pro.load(input);} catch (IOException e) {e.printStackTrace();}String url_main = pro.getProperty("url_main");HttpSession usersession = request.getSession(false);usersession.invalidate();//数据源切换回默认SpObserver.putName("");SpObserver.putPass("");PrintWriter out;out = response.getWriter();out.print("<script type='text/javascript'>");out.print("document.write(\"<form id='url' method='post' action='"+url_main+"'>\");");out.print("document.write(\"<input type='hidden' name='j_username' value='" +username + "' />\");");out.print("document.write(\"<input type='hidden' name='j_password' value='"+password+"' />\");");out.print("document.write(\"<input type='hidden' name='j_captcha_response' />\");");out.print("document.write('</form>');");out.print("document.getElementById('url').submit();");out.print("</script>");} catch (IOException e) {e.printStackTrace();}return null;}
分布式切换历史库总结相关推荐
- github电脑壁纸_GitHub - jadepeng/bing-wallpaper: Bing每日壁纸,自动获取Bing的精美图片设置为壁纸,并且支持随机切换历史壁纸,查看壁纸故事...
Bing每日壁纸 发布一个开源小软件,Bing每日壁纸. 该小软件可以自动获取Bing的精美图片设置为壁纸,并且支持随机切换历史壁纸,查看壁纸故事. 欢迎大家下载使用,点star!有问题请留言或者提i ...
- github电脑壁纸_GitHub - githubtaotao/bing-wallpaper: Bing每日壁纸,自动获取Bing的精美图片设置为壁纸,并且支持随机切换历史壁纸,查看壁纸故事...
Bing每日壁纸 发布一个开源小软件,Bing每日壁纸. 该小软件可以自动获取Bing的精美图片设置为壁纸,并且支持随机切换历史壁纸,查看壁纸故事. 欢迎大家下载使用,点star!有问题请留言或者提i ...
- springboot+redis 切换redis库操作简洁明了
springboot整合redis后默认使用的是redist的db0号库,在学习redis时对redis库进行了很多数据操作,今天使用redis开始正式写项目的时候我想换一个库,但是不知道操作上网一搜 ...
- 架构设计:分布式服务,库表拆分模式详解
简介:分布式系统架构的明显特点,就是按照业务系统的功能,拆分成各种服务,每个服务下面都有自己独立的数据库,以此降低业务间的耦合度,隔离不同的数据库保证系统最大的稳定性等. 一.服务间隔离 1.分布式结 ...
- 分布式ID-数据库多主模式
如果我们两个数据库组成一个主从模式集群,正常情况下可以解决数据库可靠性问题,但是如果主库挂掉后,数据没有及时同步到从库,这个时候会出现ID重复的现象.我们可以使用双主模式集群,也就是两个Mysql实例 ...
- 强化学习原理与python实现原理pdf_纯Python实现!Facebook发布PyTorch分布式强化学习库...
图灵TOPIA来源:Facebook编译:刘静图灵联邦编辑部出品Facebook于近日发布了PyTorch中用于强化学习(RL)研究的平台:TorchBeast.TorchBeast实现了流行的IMP ...
- MySQL一主二从复制环境切换主从库
假设有一个一主二从的环境,当主库M出现故障时,需要将其中一个从库S1切换为主库,同时将S2指向新的主库S1,如果可能,需要将故障的主库M修复并重置为新的从库. 搭建一主二从复制环境可参考:MySQL搭 ...
- React-Native全球化语言切换工具库react-native-i18n
转载请注明出处王亟亟的大牛之路 开篇啰嗦–阶段感悟 最近2 -3个月基本都因为一些私事没怎么系统的工作和学习,途中看了几天Kotlin的东西写了些demo并且整了个小项目,但是整体状态不是很好,这些天 ...
- oracle历史库架构,oracle体系结构
这几天认真的在看oracle concept. 真让人头疼啊. 先说说了解的大概的体系结构 oracle服务器是由oracle数据库和oracle实例组成. oracle实例是由内存结构和进程. or ...
最新文章
- [转]Extending the User Interface in Outlook 2010
- 不幸的是MyApp已停止。 我该如何解决?
- 揭开AI产品PRD的面纱,浅谈其和互联网产品PRD的异同
- Cocos2d-x V3.2+Cocos Studio1.6 实现一个简单的uibutton点击功能
- 第八篇Django分页
- 电子商务网站常用源码介绍
- 自学机器学习_我用来自学机器学习的最佳资源
- 程序员的10个谎言,你听过几个?
- null=null不能作为关联条件
- WAMPServer安装和配置
- LPDDR4协议规范之 (六)刷新
- 《宏观经济学》 学习笔记
- 酸菜鱼,新一代微商暴富大机会?
- 如何计算样本权重和类别权重? 样本权重怎样起作用?
- 你的脸正在成为别人的生意!
- Python之建模数值逼近篇–最小二乘拟合
- 计算机c盘能备份数据吗,Win10不进系统就能备份C盘文件的方法,你知道吗?
- 未转变者服务器3.26物品id,Unturned未转变者3.21版本物品ID代码汇总
- 大唐西域记 唐朝时代的世界划分 Re: [转载]悟空的仕途生涯(长)
- python获取js渲染后的源码_Python使用PAMIE获取JS渲染后的HTML源码 - 米扑博客