otter依赖于canal提供数据库日志,针对mysql数据有一些要求,具体请查看:https://github.com/alibaba/canal/wiki/QuickStart 有一点特别注意:目前canal支持mixed,row,statement多种日志协议的解析,但配合otter进行数据库同步,目前仅支持row协议的同步,使用时需要注意. show variables like '%binlog_format%'; SET SESSION binlog_format = 'ROW'; SET GLOBAL binlog_format = 'ROW'; #SET SESSION binlog_format = 'STATEMENT'; #SET GLOBAL binlog_format = 'STATEMENT'; #SET SESSION binlog_format = 'MIXED'; #SET GLOBAL binlog_format = 'MIXED'; 环境准备 1. 操作系统 a. otter为纯java编写,windows/linux均可支持 b. jdk建议使用1.6.25以上的版本,稳定可靠,目前阿里巴巴使用基本为此版本 2. 整个otter同步由几部分组成,需要预先进行安装,后续会有专门的篇幅展开介绍 manager node 3. otter node依赖于zookeeper进行分布式调度,需要安装一个zookeeper节点或者集群. 重要:考虑异地机房的地域性,node机器会优先选择就近的zookeeper节点进行访问,比如国际站会在杭州和美国各部署node,针对美国的node会选择美国的zookeeper进行访问,提升读效率. ps. 不同机房的zookeeper集群组成一个物理大集群,只不过是根据地域不同划分为不同逻辑集群,所有地域的node机器对zookeeper进行写操作都会发到一个地域的zookeeper进行paoxs算法仲裁. 所以,manager启动完成后,需要首先定义不同机房的zookeeper机器集群。 比如:目前otter使用的zookeeper集群,在杭州会有3个机房,分别部署3+2+2台机器组成一个leader/follower集群,在美国一个机房部署2台机器,做为杭州机房zookeeper的observer(读镜像),(observer模式特点:读请求在自己本地,写请求代理到leader/follower上投票处理,然后异步接收leader的写结果反馈. ) observer配置文档: http://zookeeper.apache.org/doc/trunk/zookeeperObservers.html 说明:添加了zookeeper集群后,会在添加node和canal时自动出现在可选列表里。 这也是添加node和canal的一个前提 环境安装 1. manager安装 Otter Manager QuickStart: Manager_Quickstart 2. node安装 Otter Node QuickStart : Node_Quickstart 网友分享 网友安装otter过程记录,供未接触java/mvn开发的运维人员使用 :http://blog.sina.com.cn/s/articlelist_1869333262_0_1.html 操作演示 演示视频(5分钟教你配置一个同步任务):请点击图片或者这里 演示说明: 1. 搭建一个数据库同步任务,源数据库ip为:10.20.144.25,目标数据库ip为:10.20.144.29. 源数据库已开启binlog,并且binlog_format为ROW.
1 |
mysql> show variables like '%binlog_format%'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | binlog_format | ROW | +---------------+-------+ |
2. 数据同步精确到一张表进行测试,测试的表名为test.example,简单包含两个子段,测试过程中才创建. […]
View Details双机热备的概念简单说一下,就是要保持两个数据库的状态自动同步。对任何一个数据库的操作都自动应用到另外一个数据库,始终保持两个数据库数据一致。 这样做的好处多。 1. 可以做灾备,其中一个坏了可以切换到另一个。 2. 可以做负载均衡,可以将请求分摊到其中任何一台上,提高网站吞吐量。 对于异地热备,尤其适合灾备。废话不多说了。我们直接进入主题。 我们会主要介绍两部分内容: 一, mysql 备份工作原理 二, 备份实战 我们开始。 我使用的是mysql 5.5.34, 一, mysql 备份工作原理 简单的说就是把 一个服务器上执行过的sql语句在别的服务器上也重复执行一遍, 这样只要两个数据库的初态是一样的,那么它们就能一直同步。 当然这种复制和重复都是mysql自动实现的,我们只需要配置即可。 我们进一步详细介绍原理的细节, 这有一张图: 上图中有两个服务器, 演示了从一个主服务器(master) 把数据同步到从服务器(slave)的过程。 这是一个主-从复制的例子。 主-主互相复制只是把上面的例子反过来再做一遍。 所以我们以这个例子介绍原理。 对于一个mysql服务器, 一般有两个线程来负责复制和被复制。当开启复制之后。 1. 作为主服务器Master, 会把自己的每一次改动都记录到 二进制日志 Binarylog 中。 (从服务器会负责来读取这个log, 然后在自己那里再执行一遍。) 2. 作为从服务器Slave, 会用master上的账号登陆到 master上, 读取master的Binarylog, 写入到自己的中继日志 Relaylog, 然后自己的sql线程会负责读取这个中继日志,并执行一遍。 到这里主服务器上的更改就同步到从服务器上了。 在mysql上可以查看当前服务器的主,从状态。 其实就是当前服务器的 Binary(作为主服务器角色)状态和位置。 以及其RelayLog(作为从服务器)的复制进度。 例如我们在主服务器上查看主状态:
1 2 3 4 5 6 7 |
mysql> show master status\G *************************** 1. row *************************** File: mysql-bin.000014 Position: 107 Binlog_Do_DB: Binlog_Ignore_DB: mysql,information_schema,performance_schema,amh 1 row <span class="kwrd">in</span> set (0.00 sec) |
稍微解释一下这几行的意思: 1. 第一行表明 当前正在记录的 binarylog文件名是: mysql-bin.000014. 我们可以在mysql数据目录下,找到这个文件: 2. 第二行, 107. 表示当前的文件偏移量, 就是写入在mysql-bin.000014 文件的记录位置。 这两点就构成了 主服务器的状态。 配置从服务器的时候,需要用到这两个值。 告诉从服务器从哪读取主服务器的数据。 (从服务器会登录之后,找到这个日志文件,并从这个偏移量之后开始复制。) 3. […]
View Details
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
public void CheckServerState(string ServiceName) { ServiceController[] service = ServiceController.GetServices(); bool isStart = false; bool isExite = false; for (int i = 0; i < service.Length; i++) { if (service[i].ServiceName.ToUpper().Equals(ServiceName.ToUpper())) { isExite = true; server = service[i]; if (service[i].Status == ServiceControllerStatus.Running) { isStart = true; break; } } } if (!isExite) { this.label1.Text = ("不存在此服务"); }else{ if (isStart) { this.label1.Text = ("服务已经启动"); } else { this.label1.Text = ("服务没启动"); } } } |
from:http://www.cnblogs.com/lujin49/p/3527704.html
View Details
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 |
#region Windows服务控制区 #region 安装服务 /// <summary> /// 安装服务 /// </summary> private bool InstallService(string NameService) { bool flag = true; if (!IsServiceIsExisted(NameService)) { try { string location = System.Reflection.Assembly.GetExecutingAssembly().Location; string serviceFileName = location.Substring(0, location.LastIndexOf('\\') + 1) + NameService + ".exe"; InstallmyService(null, serviceFileName); } catch { flag = false; } } return flag; } #endregion #region 卸载服务 /// <summary> /// 卸载服务 /// </summary> private bool UninstallService(string NameService) { bool flag = true; if (IsServiceIsExisted(NameService)) { try { string location = System.Reflection.Assembly.GetExecutingAssembly().Location; string serviceFileName = location.Substring(0, location.LastIndexOf('\\') + 1) + NameService + ".exe"; UnInstallmyService(serviceFileName); } catch { flag = false; } } return flag; } #endregion #region 检查服务存在的存在性 /// <summary> /// 检查服务存在的存在性 /// </summary> /// <param name=" NameService ">服务名</param> /// <returns>存在返回 true,否则返回 false;</returns> public static bool IsServiceIsExisted(string NameService) { ServiceController[] services = ServiceController.GetServices(); foreach (ServiceController s in services) { if (s.ServiceName.ToLower() == NameService.ToLower()) { return true; } } return false; } #endregion #region 安装Windows服务 /// <summary> /// 安装Windows服务 /// </summary> /// <param name="stateSaver">集合</param> /// <param name="filepath">程序文件路径</param> public static void InstallmyService(IDictionary stateSaver, string filepath) { AssemblyInstaller AssemblyInstaller1 = new AssemblyInstaller(); AssemblyInstaller1.UseNewContext = true; AssemblyInstaller1.Path = filepath; AssemblyInstaller1.Install(stateSaver); AssemblyInstaller1.Commit(stateSaver); AssemblyInstaller1.Dispose(); } #endregion #region 卸载Windows服务 /// <summary> /// 卸载Windows服务 /// </summary> /// <param name="filepath">程序文件路径</param> public static void UnInstallmyService(string filepath) { AssemblyInstaller AssemblyInstaller1 = new AssemblyInstaller(); AssemblyInstaller1.UseNewContext = true; AssemblyInstaller1.Path = filepath; AssemblyInstaller1.Uninstall(null); AssemblyInstaller1.Dispose(); } #endregion #region 判断window服务是否启动 /// <summary> /// 判断某个Windows服务是否启动 /// </summary> /// <returns></returns> public static bool IsServiceStart(string serviceName) { ServiceController psc = new ServiceController(serviceName); bool bStartStatus = false; try { if (!psc.Status.Equals(ServiceControllerStatus.Stopped)) { bStartStatus = true; } return bStartStatus; } catch (Exception ex) { throw new Exception(ex.Message); } } #endregion #region 修改服务的启动项 /// <summary> /// 修改服务的启动项 2为自动,3为手动 /// </summary> /// <param name="startType"></param> /// <param name="serviceName"></param> /// <returns></returns> public static bool ChangeServiceStartType(int startType, string serviceName) { try { RegistryKey regist = Registry.LocalMachine; RegistryKey sysReg = regist.OpenSubKey("SYSTEM"); RegistryKey currentControlSet = sysReg.OpenSubKey("CurrentControlSet"); RegistryKey services = currentControlSet.OpenSubKey("Services"); RegistryKey servicesName = services.OpenSubKey(serviceName, true); servicesName.SetValue("Start", startType); } catch (Exception ex) { return false; } return true; } #endregion #region 启动服务 private bool StartService(string serviceName) { bool flag = true; if (IsServiceIsExisted(serviceName)) { System.ServiceProcess.ServiceController service = new System.ServiceProcess.ServiceController(serviceName); if (service.Status != System.ServiceProcess.ServiceControllerStatus.Running && service.Status != System.ServiceProcess.ServiceControllerStatus.StartPending) { service.Start(); for (int i = 0; i < 60; i++) { service.Refresh(); System.Threading.Thread.Sleep(1000); if (service.Status == System.ServiceProcess.ServiceControllerStatus.Running) { break; } if (i == 59) { flag = false; } } } } return flag; } #endregion #region 停止服务 private bool StopService(string serviceName) { bool flag = true; if (IsServiceIsExisted(serviceName)) { System.ServiceProcess.ServiceController service = new System.ServiceProcess.ServiceController(serviceName); if (service.Status == System.ServiceProcess.ServiceControllerStatus.Running) { service.Stop(); for (int i = 0; i < 60; i++) { service.Refresh(); System.Threading.Thread.Sleep(1000); if (service.Status == System.ServiceProcess.ServiceControllerStatus.Stopped) { break; } if (i == 59) { flag = false; } } } } return flag; } #endregion #endregion |
from:http://blog.csdn.net/smartsmile2012/article/details/8666635
View Details在使用winform程序获取调用cmd命令提示符时,如果是win7以上的操作系统,会需要必须以管理员身份运行才会执行成功,否则无效果或提示错误。 比如在通过winform程序执行cmd命令时,某些情况下如果不是以管理员身份运行,则会提示命令无效。 或者通过winform程序执行Windows Service 服务时,也需要以管理员身份才能调用Service服务。 下面讲解一下如何使程序获取管理员权限来运行。 一: 在Visual Studio 中--解决方案资源管理器--右键项目名称--属性,找到“安全性”选项, 二:勾选“启用ClickOnce安全设置”, 三:这时,在项目下面会多出一个“app.manifest”的文件,选中它,并找到代码段<requestedExecutionLevel level="asInvoker" uiAccess="false" />,将其改为:<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />, 打开: 将上图部分修改为: 四:改正后,不要急于重新编译生成,再次打开“属性--安全性”界面, 将“启用ClickOnce安全设置”前面的勾去掉后再编译运行。 不然程序会报错无法运行。 五:最后,保存修改,重新编译运行程序。 打开程序时,会提示“用户账户控制”来获取管理员权限运行,点击“是”则获取了管理员权限。 from:http://www.cnblogs.com/babycool/p/3569183.html
View Details如果mysql不小心操作失误导致数据错误或者丢失这时候binlog起到了很大的作用 恢复有几种方式 1.按时间恢复--start-datetime 如果确定了时间点,那么按时间恢复是一个再好不过的事,一般是通过日常的定期备份+差异备份(日志) 如果日常备份在4点,出错的时间在12:00点,12:30发现的,首先我们要确认12点出了什么错,12点以后的数据还能不能继续使用,如果不影响,那么我们只需跳过12:00执行的数据即可 首先,恢复4点的备份 然后,通过binlog获取4点到11:59的数据,获取的数据可以直接作用到数据库中,避免二次污染,最好先生成sql文件 mysqlbinlog --start-datetime="2014-11-07 04:01:00" --stop-datetime="2014-11-07 11:59:00" /data/mysql/data/mysql-bin.000020 >/home/madong/aa.sql 在获取12:01-12:30的数据 mysqlbinlog --start-datetime="2014-11-07 12:01:00" --stop-datetime="2014-11-07 12:30:00" /data/mysql/data/mysql-bin.000020 >>/home/madong/aa.sql 最后通过mysql命令行 source /home/madong/aa.sql 如果12点以后的数据还不能继续使用 那么我们只需要恢复到12点,12:00-12:30的数据就不需要恢复 2.通过--start-position节点 思路和上面的一样,首先要确定节点的id,在恢复 例: 描述:2014-11-07 13:50 游戏数据库数据全部清空 故障发现时间:13:50 故障发生时间:13:40左右 故障结束时间:15:55 恢复过程: 故障触发,游戏马上关服,进行维护,故障原因已知(数据没了) 1.首先确认恢复时间点 恢复带2014-11-07 13:30 2.因为刚开服不久,所以准备从最原始开始恢复,不从4点的完整备份节点恢复 准备不直接操作,先生成sql, mysqlbinlog --start-datetime="2014-11-06 09:50:00" --stop-datetime="2014-11-07 13:30:00" /data/mysql/data/mysql-bin.000020 >/home/madong/aa.sql (aa.sql 500M左右) 3.因数据库重置之后又有玩家注册,如果导入数据会出现主键冲突,所以再次清空数据库(保留基表数据) 4.导入sql 进入mysql命令行,并切换数据库(use DBNAME) source /home/madong/aa.sql 执行开始时间14:57 结束时间15:54 大约一个小时 from:http://www.cnblogs.com/liuyisai/p/5621909.html
View Details解决方案:visual studio 2010 选定web项目,右键选择“属性”—“生成”,将“生成序列化程序集”设成“关闭”。 若你使用的是Visual Studio 2012,还需要在“标准”工具栏将“解决方案配置”设置为 Release 模式(Visual Studio 2012 默认使用 Release 模式发布 Web 应用),然后再进行上述操作即可。 from:http://www.cnblogs.com/songling/p/3623612.html
View DetailsMySQL 字符串截取函数:left(), right(), substring(), substring_index()。还有 mid(), substr()。其中,mid(), substr() 等价于 substring() 函数,substring() 的功能非常强大和灵活。 1. 字符串截取:left(str, length) mysql> select left('example.com', 3); +————————-+ | left('example.com', 3) | +————————-+ | exa | +————————-+ 2. 字符串截取:right(str, length) mysql> select right('example.com', 3); +————————--+ | right('example.com', 3) | +————————--+ | com | +————————--+ 实例: #查询某个字段后两位字符 select right(last3, 2) as last2 from historydata limit 10; #从应该字段取后两位字符更新到另外一个字段 update historydata set last2=right(last3, 2); 3. 字符串截取:substring(str, pos); substring(str, pos, len) 3.1 从字符串的第 4 个字符位置开始取,直到结束。 mysql> select substring('example.com', 4); +——————————+ […]
View Details今天用到了MySql里的isnull才发现他和MSSQL里的还是有点区别,现在简单总结一下: mysql中isnull,ifnull,nullif的用法如下: isnull(expr) 的用法: 如expr 为null,那么isnull() 的返回值为 1,否则返回值为 0。 mysql> select isnull(1+1); -> 0 mysql> select isnull(1/0); -> 1 使用= 的null 值对比通常是错误的。 isnull() 函数同 is null比较操作符具有一些相同的特性。请参见有关is null 的说明。 IFNULL(expr1,expr2)的用法: 假如expr1 不为 NULL,则 IFNULL() 的返回值为 expr1; 否则其返回值为 expr2。IFNULL()的返回值是数字或是字符串,具体情况取决于其所使用的语境。 mysql> SELECT IFNULL(1,0); -> 1 mysql> SELECT IFNULL(NULL,10); -> 10 mysql> SELECT IFNULL(1/0,10); -> 10 mysql> SELECT IFNULL(1/0,’yes'); -> 'yes' IFNULL(expr1,expr2)的默认结果值为两个表达式中更加“通用”的一个,顺序为STRING、 REAL或 INTEGER。假设一个基于表达式的表的情况, 或MySQL必须在内存储器中储存一个临时表中IFNULL()的返回值: CREATE TABLE tmp SELECT IFNULL(1,’test') AS test; 在这个例子中,测试列的类型为 CHAR(4)。 NULLIF(expr1,expr2) 的用法: 如果expr1 = expr2 成立,那么返回值为NULL,否则返回值为 expr1。这和CASE WHEN expr1 = expr2 THEN NULL ELSE expr1 END相同。 mysql> SELECT NULLIF(1,1); […]
View Details首先先引用System.ServiceProcess.dll 然后在引用命名空间using System.ServiceProcess; ServiceController sc = new ServiceController("Server");建立服务对象 //服务运行则停止服务 if (sc.Status.Equals(ServiceControllerStatus.Running)) { sc.Stop(); sc.Refresh(); } //服务停止则启动服务 if ((sc.Status.Equals(ServiceControllerStatus.Stopped)) || (sc.Status.Equals(ServiceControllerStatus.StopPending))) { sc.Start(); sc.Refresh(); } from:http://www.cnblogs.com/luluping/archive/2010/08/27/1809896.html
View Details