众所周知,git是分布式的,svn是集中式的。
把git当做集中式用,完全可以;但是把svn用出分布式的样子,还是有难度的。
有一些开源工具试图解决这一问题,例如SVK旨在增强脱机工作的功能。
本文只是设想,且注重于svn server双向同步 或 多server互相同步,旨在提高SVN可用性,不在脱机工作方向尝试。
方案如下:
在serverA 上面建repoA,然后使用rsync等工具将repoA 同步到serverB上面形成repoB,以此类推,可以有serverC-repoC……
然后利用每个repo的hooks——start-commit和post-commit
start-commit: lock others repos
post-commit: commit and sync to other server
post-commit: unlock other repos
方案如上,如此可以向不同的server上的repo提交代码,多server之间进行同步,形成 一个伪分布式。
但是还是尽量向同一个server提交比较好,其他server作为备用机,同时可以对读操作进行分流。这又回到本文起点:旨在提高SVN可用性,不在脱机工作方向尝试。
2020年9月11日 update:
初步测试,方案可行
示意图如下:
测试环境:vmware workstation 15 pro / ubuntu 16.04 / svn-1.9.3 / apache2 / rsync-3.1.1
测试步骤:
- 在/pathA/trunk commit文件,在/pathB/trunk中update
- 在/pathB/trunk commit文件,在/pathA/trunk中update
测试结果:
- 步骤1通过
- 步骤2通过
2020年9月16日 update:
实现锁的两种方式:
1.在公共位置指定一个master,每次提交前检查master是不是对应的本机;这种方式适用于仅指定一台server作为master,其他server作为好可用的冗余。例如:在Redis中设置svn_master:master_ip,然后在start-commit, pre-lock, pre-revprop-change这几个hooks中增加对master的检查,获取master_ip检查是不是本机,根据结果判断是不是允许本机的本次提交。
2.在公共位置设置一个令牌,每次提交前先获取令牌再进行提交(,同时也可把当前正在进行提交动作的server信息放上去),提交并同步完成后,将令牌归还以完成解锁动作;这种方式适用于想实现分布式svn的同学,使多台server在一定时间内都可以进行提交动作。 例如:在Redis中设置svn_token:svn_commit_lock,在start-commit, pre-lock, pre-revprop-change这几个hooks中增加对令牌的获取尝试,如果获取到令牌(,获取到以后也可将本机IP放入svn_token中,用于提醒其他server目前的状态),则进行提交动作。
实现同步的方式:
可在post-commit这个hook中,添加rsync命令(rsync如何使用请自行学习),如下例子:
DEST="[the rsync path to destnation]" cd $REPOS rsync --archive --delete-delay --compress --temp-dir=/tmp --delay-updates ./ $DEST
rsync 参数解释:
--archive: 归档模式 可以使用-a代替,更好
--compress: 压缩,可以使用-P代替,也可使用--compress-level=[0-9]代替,主动指明压缩等级,隐含--compress
--delete-delay: 等所有同步完成后删除send端没有,receive端有的文件。
--temp-dir=/tmp: 设置暂存目录,与下面的--delay-updates结合使用
--delay-updates: receive端每个重组的临时文件保留在某个目录中,直到传输结束之前才一次性将它们全部重命名为各自对应的目标文件。这样的行为使得所有文件的更新更具有原子性
./: 与上面cd $REPOS
结合使用,表示同步当前目录。 $DEST: 要同步到的receive地址,具体设定参考rsync。
具体其他参数和操作请根据自己情况添加。
可能存在的问题:
- 提交代码量大,提交频繁,网络带宽不足,没有及时同步完成,导致某些commit被覆盖。情况与上条类似,应该继续研究加锁和释放锁的时机。比如确保所有同步完成再释放锁。
- 假设committer向serverA提交一份代码,未等serverA同步到serverB,网络中断了。此种情况,本次提交的数据源仅存在于committer和serverA上。最好的解决方式是停掉有问题的server,然后committer重新向正常的server提交,按最新的一次提交进行同步覆盖。
不过,解决以上问题最好方式就是尽量使用一台server进行写操作(,即加锁方式一),其余server只进行读操作,或者作为备份提高可用性。回扣本文主旨:旨在提高SVN可用性,不在脱机工作方向尝试。
参考文章:
- svn hooks的使用:https://blog.csdn.net/weixin_42578481/article/details/85272335
- rsync 参数详解:https://www.cnblogs.com/jiangzhaowei/p/8191003.html