<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">博客园_84年的矿泉水</title><subtitle type="text"/><id>http://feed.cnblogs.com/blog/u/31853/rss</id><updated>2012-01-06T15:06:04Z</updated><author><name>xvhfeng</name><uri>http://www.cnblogs.com/Seapeak/</uri></author><generator>feed.cnblogs.com</generator><link rel="alternate" type="text/html" href="http://www.cnblogs.com/Seapeak/"/><link rel="self" type="application/atom+xml" href="http://feed.cnblogs.com/blog/u/31853/rss"/><entry><id>http://www.cnblogs.com/Seapeak/archive/2012/01/06/2315288.html</id><title type="text">2011年年度总结</title><summary type="text">一年又过去了，2011年对我而言不是一个很完美的一年，至少没有09,10年完美。 首先，我跳槽了，离开了5173.5173是一家我需要严重感谢的公司，我在足下起步，然后在5173得到升华，但是在5173工作2年后，我选择了跳槽。跳槽的原因并不是为了金钱（真的不是为了金钱），而是自己的理念、想法和部门、领导的理念产生了严重的偏差，导致了工作的过程越来越不开心，越来越觉得难受，所以最后还是选择了离开。离开后，没有多久，部门领导也离开了。如果我的决定晚一点下的话，也许我就不会离开5173了。不过令我欣慰的是：我原先的关系还保持至今，包括对同事、下属的。 在5173,最值得我骄傲的是搞了一个D...</summary><published>2012-01-06T15:06:00Z</published><updated>2012-01-06T15:06:00Z</updated><author><name>xvhfeng</name><uri>http://www.cnblogs.com/Seapeak/</uri></author><link rel="alternate" href="http://www.cnblogs.com/Seapeak/archive/2012/01/06/2315288.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/Seapeak/archive/2012/01/06/2315288.html"/><content type="html">&lt;p&gt;一年又过去了，2011年对我而言不是一个很完美的一年，至少没有09,10年完美。&lt;/p&gt;&lt;p&gt;首先，我跳槽了，离开了5173.5173是一家我需要严重感谢的公司，我在足下起步，然后在5173得到升华，但是在5173工作2年后，我选择了跳槽。跳槽的原因并不是为了金钱（真的不是为了金钱），而是自己的理念、想法和部门、领导的理念产生了严重的偏差，导致了工作的过程越来越不开心，越来越觉得难受，所以最后还是选择了离开。离开后，没有多久，部门领导也离开了。如果我的决定晚一点下的话，也许我就不会离开5173了。不过令我欣慰的是：我原先的关系还保持至今，包括对同事、下属的。&lt;/p&gt;&lt;p&gt;在5173,最值得我骄傲的是搞了一个DFS，让我很爽;作为一个领导，在人事上有两件事情让我有喜有忧：喜的是培养了&amp;ldquo;叔叔&amp;rdquo;，让他知道了工作中最重要的是什么？怎么通过努力去达到他！虽然他最后因为和我差不多的原因离开了这个部门;忧的是对不起团队中另外一位兄弟：高工。因为培养叔叔（当时叔叔实在太...，不搞不行了）的压力关系，怠慢了高工，后来又由于我的离开，导致没有时间把高工培养起来，唉！一大遗憾。有机会的话，我希望能弥补一下。&lt;/p&gt;&lt;p&gt;在5173干的事情还真不少。人生中写的第一本书《程序员入职锦囊妙计》出版了，虽然没有大卖，但最后终归是挑战自己成功了，值得欣慰。年初的时候，因为朋友的关系，兼职了一份顾问的工作，报酬不算很多，但过程不错，个人比较满意。&lt;/p&gt;&lt;p&gt;离开5173后，我加入了携程。在携程主要从事国际机票的架构工作。国际机票要比火车票复杂多了（12306,哈哈）。虽然国际机票的业务非常复杂，但是系统中所用到的技术我倒是没啥问题。轻轻松松就搞定了。整个系统也是经过我们整个团队的努力，最后还是完成了这个系统的开发并且试运行（悄悄的说一下），一不小心就又成了&amp;ldquo;国内第一&amp;rdquo;，真是&amp;ldquo;躺着也中枪&amp;rdquo;啊！希望公司在年后宣布的时候，股票能涨一点，买车的成色就靠它了！哈哈！&lt;/p&gt;&lt;p&gt;在年中的时候，有个朋友找到我，让我一起去创业。我了解了一下，是做奢侈品电商的。当初我们也接触了几次，但是随着接触的次数越来越多，越来越发现和我想象的有差距，虽然这个奢侈品电商是由一个奢侈品行业非常有名的人投资的，也不差钱，但是他们只知道奢侈品，对中国的互联网其实并不了解。所以经过了几次的接触后，大家都觉得没啥感觉，最后就放弃了。这也再次印证了在互联网行业，土狼往往比海龟更靠谱。所以，个人感觉这个网站成功的可能性很小，主要的问题还是出在了对互联网的了解上，很多人都是想法很好，但是可操作性真的很不高，那就只有等死了。&lt;/p&gt;&lt;p&gt;对于创业公司，用人很重要。我个人倒是觉得对于技术人员而言，不管是领导还是底下的程序员，创业公司需要雇用的不是那种职业经理人，而是那种自己能下去干活的人。在硅谷的创业公司，当面试一个人的时候，如果这个人说：给我一个团队，我能怎么怎么样，那么这个人肯定得不到雇用。这其实在国内也同样适用。职业经理人太讲究团队的配合、流程、绩效......，这一整套确实挺好，至少听上去你像是懂管理的，但是却在无形中扼杀了很多创业公司需要的那种激情、那种出身牛犊不怕虎的团队气质。国内还有很多的技术出身的职业经理人以不写代码为荣，这其实也是有问题的。作为技术人员，连基本的代码都不写了，他还能做什么呢？也正是这种原因，导致了很多的&amp;ldquo;二把刀&amp;rdquo;技术领导出现，然后最倒霉的是公司，大价钱雇用了他，但是最后他搞的一团糟。完了，什么都结束了。技术这个东西用好了，什么都好说，用不好就是属驴的，牵着不走，打着倒退。很多的创业公司最后玩不下去了，除了业务有问题外，很多时候可能最后就是败在了以上的两点上。&lt;/p&gt;&lt;p&gt;最后说一下书，在这一年中，一共花了1867.89元RMB买书，并且全部看完了。其中国庆节之前买的书就把家里的书架放满了，所以国庆后得到LD的指示，去宜家重新买了一个带书架的书桌和一个书架，这回有的放了。虽然我是主要从事net的，但是奇怪的是，这些书中，只有2本书是net的，余下的全部是linux环境的，这个怎么解释？？&lt;/p&gt;&lt;p&gt;2012年，船票有没有不是很重要，我想要一张行驶证，嘿嘿！&lt;/p&gt;&lt;img src="http://www.cnblogs.com/Seapeak/aggbug/2315288.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/Seapeak/archive/2012/01/06/2315288.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/Seapeak/archive/2011/10/19/2218200.html</id><title type="text">albian使用方法-1</title><summary type="text">这段时间都没有写任何的blog，主要的精力都放在了albian的开发上。因为一个朋友创业，原本有意加入之，所以加紧了albian的开发，但因为额启动成本的问题，这段时间开发的albian是java版本的，俗称albianj。后来因为了解的深入，感觉这个创业项目不靠谱就放弃了。但是albianj基本上写完了。总体结构、思想都没有任何的改变，但是代码结构albianj和albian.net相比成熟很多。albian.net会在下次重构的时候更改代码结构。 这次先来说一下albian的使用（因为java版本和net基本上使用方法一样）。和平常的开源软件一样，albian也有配置文件，而且配置文...</summary><published>2011-10-19T13:15:00Z</published><updated>2011-10-19T13:15:00Z</updated><author><name>xvhfeng</name><uri>http://www.cnblogs.com/Seapeak/</uri></author><link rel="alternate" href="http://www.cnblogs.com/Seapeak/archive/2011/10/19/2218200.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/Seapeak/archive/2011/10/19/2218200.html"/><content type="html">&lt;p&gt;&amp;nbsp; &amp;nbsp; 这段时间都没有写任何的blog，主要的精力都放在了albian的开发上。因为一个朋友创业，原本有意加入之，所以加紧了albian的开发，但因为额启动成本的问题，这段时间开发的albian是java版本的，俗称albianj。后来因为了解的深入，感觉这个创业项目不靠谱就放弃了。但是albianj基本上写完了。总体结构、思想都没有任何的改变，但是代码结构albianj和albian.net相比成熟很多。albian.net会在下次重构的时候更改代码结构。&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 这次先来说一下albian的使用（因为java版本和net基本上使用方法一样）。和平常的开源软件一样，albian也有配置文件，而且配置文件还不少，一共有10个，分别是&lt;/p&gt;&lt;p&gt;　 &amp;nbsp;cache.xml 此文件主要配置使用在ORM上的缓存，支持本地和Memcached两种;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;config.xml &amp;nbsp;此文件主要配置&amp;ldquo;配置服务&amp;rdquo;，这是一个albian内置的服务，主要提供程序中经常使用的参数配置功能;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;controller.properties 此文件主要配置albian的控制中心，即albian的管理器;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;log4j.xml 这是日志配置，albian使用log4系列作为默认日志工具，这就不多说了吧;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;persistence.xml 此文件主要配置对象的持久化关闭，即ORM的映射关系、对象和数据库、数据库表之间的关系;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;routing.xml 此文件主要配置数据对象的database router功能，即数据对象会根据你配置的router，路由到不同的库、表中;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;service.xml 此文件主要配置最简单的IOC功能;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;storage.xml 此文件主要配置数据库链接;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;alocker.xml 此文件主要配置分布式锁服务器;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 介绍完了配置文件后，我们通过一个实例来讲述一下。&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;场景描述：&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;有一个电子商务网站，大概一天的pv在2kw左右，数据库采用sql server和mysql，sql server主要用来提供&amp;ldquo;写操作&amp;rdquo;，mysql被大量的部署，用来提供&amp;ldquo;读操作&amp;rdquo;。然后客户端可以发布自己的东西，在电子商务站点中称为发布单;顾客也可以购买东西，即对发布单下订单。发布单除了单页面查看以外，还可以通过list页面来查看。场景应该差不多了吧？这些应该是最简单的电子商务网站的模型吧？！&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; 首先我们确定一下我们将使用albian来完成底层功能的使用。然后审视一下场景描述，我们不难发现，pv在2kw以上，那么应该可以称为中型网站，所以数据量压力、并发压力、流量压力都很大。为了应对网站压力，对数据肯定是进行了一定的拆分，俗称&amp;ldquo;分库分表&amp;rdquo;，然后因为需要list页面的显示，我们肯定又需要一个总体的数据库表来导出列表或者各类分索引的数据库表来完成这项功能（暂且不考虑search引擎，虽然那么大的访问量没有search引擎是很难想象的）。那么大的访问量，肯定是需要缓存来顶部分的压力，可能是分布式缓存、也可能是本地缓存，这需要具体的情况看。好，现在明确一下我们需要什么。&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; 第一：使用albian来完成（一站式服务嘛，为嘛不用？！）;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; 第二：数据对象需要分库分表;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; 第三：数据库存在异构（sql server和mysql）;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; 第四：分库分表后牵连的一个问题，事务问题;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; 第五：缓存问题;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; 第六：数据的并发问题;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 搞定了场景和场景中的利弊，这就简单了，下一节将介绍怎么使用albian来完成！&lt;/p&gt;&lt;img src="http://www.cnblogs.com/Seapeak/aggbug/2218200.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/Seapeak/archive/2011/10/19/2218200.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/Seapeak/archive/2011/08/01/2122603.html</id><title type="text">albian开发笔记六-albian的架构</title><summary type="text">很久之前就想写这篇文章，但是作为一个技术人员，苦于但是只是心中有概念和想法，实施还没有真正的开始，所以一直没有写。现在，albian的net实现主体部分已经完成了75%左右，单机已经可以勉强凑合的运行了，所以心中有了底气，才写这篇关于albian架构的文章。这一篇完成后，下面一连几篇都将会讲述albian的使用方法，从简单开始一直到复杂。 说起albian的架构，就要说起albian的起源。albian其实来源于本人在电商圈内的一些开发经验和实际的项目实施。虽然电商的经验不多，但是加上“站在巨人的肩膀上”，也能勉强的凑合着把albian搞出来。由此可见，albian其实完全是为了电商行业量身.</summary><published>2011-08-01T01:05:00Z</published><updated>2011-08-01T01:05:00Z</updated><author><name>xvhfeng</name><uri>http://www.cnblogs.com/Seapeak/</uri></author><link rel="alternate" href="http://www.cnblogs.com/Seapeak/archive/2011/08/01/2122603.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/Seapeak/archive/2011/08/01/2122603.html"/><content type="html">&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 很久之前就想写这篇文章，但是作为一个技术人员，苦于但是只是心中有概念和想法，实施还没有真正的开始，所以一直没有写。现在，albian的net实现主体部分已经完成了75%左右，单机已经可以勉强凑合的运行了，所以心中有了底气，才写这篇关于albian架构的文章。这一篇完成后，下面一连几篇都将会讲述albian的使用方法，从简单开始一直到复杂。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 说起albian的架构，就要说起albian的起源。albian其实来源于本人在电商圈内的一些开发经验和实际的项目实施。虽然电商的经验不多，但是加上&amp;ldquo;站在巨人的肩膀上&amp;rdquo;，也能勉强的凑合着把albian搞出来。由此可见，albian其实完全是为了电商行业量身定做的（上个星期拿着albian去和朋友交流，朋友提出了很多的意见，最后只有几个被接纳了，丢掉的都是经过讨论和互联网或者电商差别比较大的）。所以albian其实不太适合MIS或者ERP此类的系统。那么就要说到互联网、电商和MIS、ERP传统行业的不同特点问题。其实这些合适或者不合适最大的问题在于互联网、电商面对的一般是海量、高并发的问题；而MIS或者ERP一般面临的是数据的复杂关系、复杂的业务的问题。因为不管是互联网、电商、MIS或者是ERP，归根结底都是面向数据库的编程（创造一个名词：ODBP），所以最终的问题都会是在数据库层面上表现。相对于互联网、电商，数据库中的单表数据量可能很大（有KW甚至更大的），而且数据库也要面临着严重的读压力（互联网经典的2-8原则），但是因为本身数据的特点，数据之间的相关关系性不强，往往很少有相关联3次及以上的表；但是MIS或者ERP就完全不同，单表的压力比较小（一般是在W级别，很少有10W或者100W的，KW的几乎绝迹），但是表之间的相关外键等关系确实错综复杂，而且MIS、ERP相对面向的用户群也是固定的，所以读写压力一般都是可控的。所以如果需要搭建架构，那么就需要面对两种完全不同的特点搭建架构，也许有人说搭建一套就行了，加上开关即可。我个人还是认为一个人同时只能做一件事才能把这件事做好，所以albian还是只是面向互联网或者电商行业。 albian的架构其实很简单，我们先看一张图即可基本上明白albian是怎么一回事：&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2011/28300/2011073110552117.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;如果没看懂就看一下文字说明：个人认为用1，2，3这种方法最能说明清楚，所以还是按照这种格式来说明：&lt;/p&gt;&lt;ol&gt;&lt;li&gt;albian其实是一个面向服务和面向数据的框架，它并不提供UI层的实现；&lt;/li&gt;&lt;li&gt;albian一共提供了5个组件来搭建整个底层框架，这5个分别是：Albian Manager Server;Albian Distributed Locker Server ;Albian IOC;Albian ORM; Albian DataBase Router;&lt;/li&gt;&lt;li&gt;Albian Manager Server：主要提供整个使用Albian环境的管理，比如注册Albian、检查Albian、重启Albian等等，因为这些功能对于服务器的性能要求不高，所以这台机器还可以用来作为多台Albian Distributed Locker Server的manager&amp;nbsp; server；&lt;/li&gt;&lt;li&gt;Albian Distributed Locker Server：主要提供对象在各个应用程序边界的锁，或者说是进程间的锁。功能和Mutex的线程间的锁功能类似，只是Mutex是锁住同一进程内或者说是应用程序边界的对象，让某一线程独享该对象；而Albian Distributed Locker Server提供的是锁住整个应用程序系统（不是操作系统，而是整个站点系统）内的对象，让某一进程或者应用程序边界独享该对象。Albian Distributed Locker Server和Mutex一样是一种编程规则，如果你不使用这种规则，程序也可以运行，但是不保证不会出现进程间的数据不同步问题。使用方法一般也是先获取Albian Distributed Locker Server上的锁，再获得进程内的Mutex，释放的步骤正好相反；Albian Distributed Locker Server的实现目前已经确定会是放到linux上，用纯C实现，业务代码的行数估计也就是K级别的；&lt;/li&gt;&lt;li&gt;Albian IOC：是一个简单的依赖注入实现。它只是简单提供了生成对象并且由Albian托管控制功能。之所以不实现例如参数注入、属性注入等等问题，还是因为觉得没必要去实现这些，一来增加了复杂度，二来albian认为重要的不是在IOC这里，IOC只要能提供一些最简单、最简洁的功能，实现运行性能的最优化即可；&lt;/li&gt;&lt;li&gt;Albian ORM：是一个简单的ORM实现。鉴于互联网和电商的特点，Albian ORM删掉了相比市面上成熟的ORM少的多的功能，因为互联网那和电商基本上只是相对&amp;ldquo;单表&amp;rdquo;化的，所以Albian只提供&amp;ldquo;单表&amp;rdquo;的操作，而一旦表之间需要关系的维护，那么只有麻烦程序员了。&lt;/li&gt;&lt;li&gt;Albian Database Router：这是Albian整个系统架构的重点。Albian Database Router的实现理论是著名的CAP理论（不知道CAP理论的请google一下）。但是Albian Database Router为了实现海量数据存储和操作的效率，Albian Database Router最后还是在CAP的C上面做了文章，将一致性的要求降低，使用最后一致性来保证效率。Albian Database Router支持多数据库的访问，包括异构数据库。Albian Database Router还支持将对象routing到指定的数据库、指定的表；Albian Database Router提供了用户自定义routing规则的接口；Albian Database Router还提供了乐观的分布式事务解决方案（常见Distributed Algorithms的wait-free termination概念）。&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;对于Albian的总体架构和重点的Router功能，看下面两个示意图：&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2011/28300/2011073110554558.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这是一个读写分离示意图，Albian DataBase Router将会根据配置将数据理由到左边的数据库中，然后再通过数据库之间的同步，将数据同步到后边的MySql中，这样我们就可以查询右面的MySql来减轻DB的压力了；&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2011/28300/2011073110561049.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这是多次写的示意图，及但一个对象持久化时，根据Albian Database Router的配置，可以将一个对象同时写到两个数据库中去。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/Seapeak/aggbug/2122603.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/Seapeak/archive/2011/08/01/2122603.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/Seapeak/archive/2011/07/21/2112716.html</id><title type="text">hashTable和多线程问题</title><summary type="text">刚刚被一同事叫去看一个问题，问题的表象是程序会周期性的报“集合被修改，循环无法继续”的异常，查了半天的问题，最后找到问题如下： 因为本地缓存很少过期，所以我们就将本地的缓存全部放入hashtable中，而hashtable中的value一般情况下就是IList&lt;T&gt;类型，而hashtable中的数据也不是一定不过期，所以我们就增加了缓存的更新功能，好了，问题出现了。 代码大致是这样的 private readonly static hashtable ht = hashtable.sync(new hashtable()); public static hashtable Cach</summary><published>2011-07-21T05:44:00Z</published><updated>2011-07-21T05:44:00Z</updated><author><name>xvhfeng</name><uri>http://www.cnblogs.com/Seapeak/</uri></author><link rel="alternate" href="http://www.cnblogs.com/Seapeak/archive/2011/07/21/2112716.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/Seapeak/archive/2011/07/21/2112716.html"/><content type="html">&lt;p&gt;刚刚被一同事叫去看一个问题，问题的表象是程序会周期性的报&amp;ldquo;集合被修改，循环无法继续&amp;rdquo;的异常，查了半天的问题，最后找到问题如下：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; 因为本地缓存很少过期，所以我们就将本地的缓存全部放入hashtable中，而hashtable中的value一般情况下就是IList&amp;lt;T&amp;gt;类型，而hashtable中的数据也不是一定不过期，所以我们就增加了缓存的更新功能，好了，问题出现了。&lt;/p&gt;&lt;p&gt;代码大致是这样的&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;private readonly static hashtable ht = hashtable.sync(new hashtable());&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;public static hashtable Cache{return ht;};&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;这个代码是在我们的缓存类中的，下面的代码是引用的地方：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; IList&amp;lt;T&amp;gt; list = Cache["key"] as IList&amp;lt;T&amp;gt;;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; foreach(T obj in list)&lt;/p&gt;&lt;p&gt;{&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;do somthing;&lt;/p&gt;&lt;p&gt;}&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; 看看代码，好像没有你问题，但是真的运行起来就不是那么一回事情了。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; 这里的问题出在我们的一个思维定势。ht是线程安全的，但是ht中value不一定，这是主因。从代码中可以看出来，value存放是IList，那么存放的应该是引用（也就是指针），而当我们通过索引器得到这个IList时，这部操作是线程安全的，但是到这里的安全并不意味着foreach也是安全的。因为hashtable提供的线程安全功能已经完成了，foreach已经是在脱离了hashtable的线程安全运行的。所以问题就会出现了。IList是引用类型，所以我们foreach的Ilist只是一个指针，具体的值存放在IList指针指向的地方，而当我们正好在更新hashtable中的foreach中指定的那个IList的时候，这个IList的指针变改变了，所以就会报错；&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; 解决问题的办法就是增加一个结构体，这个结构体中有两个对象：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; struct Item{object locker;IList list;},这样，每次更新或者循环的时候都要先加上locker的锁，这样就可以避免了线程的我安全问题！&lt;/p&gt;&lt;img src="http://www.cnblogs.com/Seapeak/aggbug/2112716.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/Seapeak/archive/2011/07/21/2112716.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/Seapeak/archive/2011/07/20/2111017.html</id><title type="text">albian开发笔记五--谈缓存同步</title><summary type="text">今天我在weibo上发布了albian将放弃支持缓存同步后，引起了以前的伙计们一片的谈论声。有认为缓存同步不是一项好的解决方案的、也有认为没有缓存同步将无法使用本地缓存的、还有担忧一台机器的本地缓存各自为政导致全站缓存状态错乱的......，但是很不幸，albian还是决定不支持本地缓存的同步。 缓存：主要的目的是用来为了让客户得到更高的响应。这是没有错的。但是从架构人员来说，当你考虑使用一种方案来实现某一目的时，你不能只从一点看，约束条件有很多。比如金钱投入、扩展性（这个很重要）等等。 缓存从架构上分，又有本地和分布式之分。本地缓存一般存储在提供服务的机器上，最大的优点就是进车内通讯，得到.</summary><published>2011-07-20T00:30:00Z</published><updated>2011-07-20T00:30:00Z</updated><author><name>xvhfeng</name><uri>http://www.cnblogs.com/Seapeak/</uri></author><link rel="alternate" href="http://www.cnblogs.com/Seapeak/archive/2011/07/20/2111017.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/Seapeak/archive/2011/07/20/2111017.html"/><content type="html">&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;今天我在weibo上发布了albian将放弃支持缓存同步后，引起了以前的伙计们一片的谈论声。有认为缓存同步不是一项好的解决方案的、也有认为没有缓存同步将无法使用本地缓存的、还有担忧一台机器的本地缓存各自为政导致全站缓存状态错乱的......，但是很不幸，albian还是决定不支持本地缓存的同步。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;缓存：主要的目的是用来为了让客户得到更高的响应。这是没有错的。但是从架构人员来说，当你考虑使用一种方案来实现某一目的时，你不能只从一点看，约束条件有很多。比如金钱投入、扩展性（这个很重要）等等。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;缓存从架构上分，又有本地和分布式之分。本地缓存一般存储在提供服务的机器上，最大的优点就是进车内通讯，得到数据几乎没有时间差；分布式缓存从名字上就能知道缓存是分布在不同的机器上的，目前业界比较流行的做法是使用memcached或者类似的软件，它的优点就是可以线性接近无限的扩展，而且保证存取缓存数据时不会因为数据量的增大而损耗性能。然后是缺点：本地缓存最大的问题是扩展性：表现在几个方面：缓存的状态更新怎么办？缓存的大小限制，等等。分布式缓存的最大问题可能就是一台服务down数据库压力剧增时怎么办？频繁操作分布式缓存性能怎么样？等等。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;先说本地缓存。支持使用本地缓存的XT基本上是为了效率出发，因为本地缓存的存取基本上不需要考虑时间消耗，所以用起来非常爽。如果你只有10台之内的服务器，这个架构基本上没有问题。就算是增加上缓存内对象状态的考虑（这个问题就是：如果有2台以上的服务器同时存了一个A对象，当第一台机器上的A被改变时怎么让第二台或者第三台甚至更多台机器也知道A对象已经被更改了？），问题也不大。我们增加一个服务，专门用来同步各个对象的状态：架构如图所示：&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2011/28300/2011071920215863.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;步骤是这样的：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;1.同步服务器和业务服务器全部启动起来，业务服务器向同步服务器注册，告知同步服务器业务服务器已经准备完毕；&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;2.某一机器上的A对象被更改了，它会通过网络通知同步服务器，告诉同步服务器，A对象已经被更改；&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;3.同步服务器的得到了A对象被更改的消息后，首先从内存中得到刚刚注册的并且还健在的业务服务器；&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;4.通知所有的健在业务服务器，A对象已经被更改，你们需要更新；&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;5.业务服务器得到通知后，启动更新程序，从数据库中获取最新的A对象的信息，并且缓存；&lt;/p&gt;&lt;p&gt;同步大概的步骤就是这样的。问题有以下几点：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; 1.延迟。网络通讯是需要有时间的，同步中，至少经过了3个网络传输步骤，时间的延迟会比较长；&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; 2.扩展性不好。我业务服务器少这套机制还能抗住，一旦我业务服务器多呢？很多人可能会说，增加同步服务器，对，就是这个策略，但是你还要更改业务代码，把不同的对象按照你的逻辑分发到不同的同步服务器，然后再通知业务服务器。但是如果业务服务器有200台呢？你一台同步服务器通知200台需要多少时间？&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; 3.容灾新不强。如果有一台同步服务器down掉你怎么办？这个好像有解决办法。在同步服务器集群上套小集群，采用pxois算法，应该可以搞定；&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; 4.每台业务服务器都要从数据库中load一遍同样的数据，而且几乎是在同一时刻完成，数据库的压力也会增加；&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; 5.业务服务器上占用过多的内存浪费不说还会导致我们单机处理业务的量下降。业务服务器最主要的还是处理业务请求，假设一个进程使用2G内存可以处理500个请求，然后本地缓存消耗掉2g，我们一台8G的机器本来可以同时跑3个进程，现在却只能跑2个，无形中损耗掉500个业务的处理量；&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;而如果我们换成分布式的系统架构，我们的架构将会是这样子：&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2011/28300/2011071920364666.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;步骤如下：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;1.程序起来的时候，需要将需要的数据全部冲入缓存；&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;2.起来业务服务器，什么都不用做；&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;3.当更改一台业务服务器上的A对象时，再更改完后同时把A对象更新到分布式缓存集群；&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;4.当另外的业务服务器需要A对象时，从分布式缓存集群中获取；&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;5.重复3-4；&lt;/p&gt;&lt;p&gt;分布式也有缺点：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;1.每次读取都要时间；这也许是一个问题。但是目前从测试的结果看，10k的数据从memcached中获取时间为0.4毫秒；&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;2.如果一台缓存服务器down掉，那么数据库压力就会增大，并且可能会存在需要重新导入数据的风险；&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;从目前分析的本地缓存和分布式缓存来看，本地缓存问题比较多，而且最重要的是扩展性没办法很好的搞定。对于一个定位于企业级应用的架构而言，失去了扩展性意味着当数据量上去的时候，很多事情就束手无策了。所以albian最后还是放弃了同步。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;其实从albian的角度出发，albian的IAlbianObject本身就是为了网络传输的考虑而设计的，albian推荐使用贫血对象，业务和数据结构分开。类似于数据就像是水管中的水，而业务流程就像水管。水（对象）从水管进口（GUI）流入，经过水管（业务流程），流向蓄水池（数据库）或者再次回给客户（回流）。这样当数据量上去（水大的时候）的时候，我们就可以想水管工那样在这个环节中增加我们的策略，分流、直接炸掉大坝等等很容易的做出相应的应对。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;其实albian不是不推荐不使用本地缓存，albian推荐的缓存使用规则如下：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;1.全站都要使用的缓存就是用分布式缓存；&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;2.本地缓存肯定要用，但是最好用在过期的对象上，比如列表的list对象等等；&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;3.所有的对象都应该是可序列化和满足网络传输的；&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;4.如果缓存是从分布式缓存集群中获取的，可以使用会话内缓存（不是session那么简单）；&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/Seapeak/aggbug/2111017.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/Seapeak/archive/2011/07/20/2111017.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/Seapeak/archive/2011/07/19/2109964.html</id><title type="text">albian开发笔记四</title><summary type="text">到目前为止，albian的ORM开发工作基本上那算是告一个段落了。下面的就是测试和完善。经过测试以后，我会写一篇怎么使用albian的orm完成基本的数据库增删改查工作，并且加上数据库路由功能等等。当然对于一些未经历过系统架构的XT，偶也会增加一些系统架构的示意图，当然主要还是围绕着albian的ORM和数据库路由功能展开。 在这一阶段的开发过程中，和往常一样，还是碰到了一些问题。 1. 在以往的开发中，泛型是我们非常喜欢的代码增强。但是对于albian而言，就泛型碰到了一些使用上的失误。albian的数据对象都是直接或者间接派生于IAlbianObject接口，而对于albian orm托.</summary><published>2011-07-19T00:58:00Z</published><updated>2011-07-19T00:58:00Z</updated><author><name>xvhfeng</name><uri>http://www.cnblogs.com/Seapeak/</uri></author><link rel="alternate" href="http://www.cnblogs.com/Seapeak/archive/2011/07/19/2109964.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/Seapeak/archive/2011/07/19/2109964.html"/><content type="html">&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; 到目前为止，albian的ORM开发工作基本上那算是告一个段落了。下面的就是测试和完善。经过测试以后，我会写一篇怎么使用albian的orm完成基本的数据库增删改查工作，并且加上数据库路由功能等等。当然对于一些未经历过系统架构的XT，偶也会增加一些系统架构的示意图，当然主要还是围绕着albian的ORM和数据库路由功能展开。&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; 在这一阶段的开发过程中，和往常一样，还是碰到了一些问题。&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; 1. 在以往的开发中，泛型是我们非常喜欢的代码增强。但是对于albian而言，就泛型碰到了一些使用上的失误。albian的数据对象都是直接或者间接派生于IAlbianObject接口，而对于albian orm托管的数据对象，我们提供了数据库路由功能。数据库的路由分为2类，一类是路由到&amp;ldquo;指定&amp;rdquo;数据库，另外一类当然是路由到&amp;ldquo;指定&amp;rdquo;表了。路由数据库功能由配置决定，而路由表则由程序员提供路由算法（别担心，这个算法很简单的，只是需要根据你的业务实现，故无法有albian原生提供），而注册这个算法的时候，就是用了泛型，但是往往当我们往数据库save数据时，至少save两个object，一个是原生数据，另外一个是日志。所以我们在使用Save&amp;lt;T&amp;gt;方法时T一般都会指定是IAlbianObject。但是我们在读取是，一般读取的都是一个对象，故可以指定对象的具体类型，比如User。而albian的表路由算法是保存在一个hashtable中的，key是typefullname+routingName，这样问题就来了，注册的时候typename是IAlbianObject，而读取的时候是User，自然无法取到了。不是没有想到使用参数传入一个typefullname，当时想的是既然已经用了泛型，为什么不能使用泛型一下子搞定呢？思前想后最后还是无法得出使用泛型的解决方案。最好一火之下更改了表路由功能的全部代码，取消泛型，取而代之的是使用IAlbianObject为参数类型，增加参数typefullname参数。这样的后果就是无法对没有被IAlbianObject签名的对象进行表路由。其实真正解决数据路由的最好办法就是提供原生态的数据路由，完全脱离App，但是对于现在的主流数据库（Oracle，MySql，SqlServer），除了mysql协议完全开放之外，别的好像都很难开发；&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; 2.Albian Service的Id问题。用过spring或者spring.net的都有体会吧，配置注册对象时，一般都要提供这个对象的ID，在app中需要取得对象时需要传入一个id，然后由ioc容器根据id返回app需要的对象。这些本身没有错，在开始设计albian的ioc时也是这么干的，但是后来发现为什么要配置id呢？不是有interface吗？直接使用interface就可以确定一个service了，遂改掉。去掉id，一切为了简单。但是在设计albian &amp;nbsp;orm缓存时碰到了问题：用分布式缓存？还是本地缓存？还是两者皆用？最灵活的方式当然是两者兼用。而albian提供的缓存接口是同一个，所以碰到了同一个接口有两个类实现的service，用interface肯定是不行了。所以又改回来，但是为了程序的简单，当一个接口的实现是一个类时，还是可以省略id。当然从这个事情上，albian还是认为为了以后的扩展方便，最好还是配置id；&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; 3.mysql的字符支持问题。albian的orm支持主流的3中数据库，oracle，mysql，sqlserver。目前albian的开发工作实在mysql的环境下进行的。在第一轮测试的时候就碰到了mysql的字符集支持问题。不管你服务器端怎么调整，怎么读出不来中文。所有插入的中文全部被&amp;ldquo;?&amp;rdquo;替代了。饶头了半天，还是没有找到解决办法。只能上mysql的官方网站上找，在一个极其不起眼的地方找到了一个类似于&amp;ldquo;客户端也要配置字符集支持&amp;rdquo;的信息。好吧，加上charset=gb2312.等等，这样是有问题的。不知道是mysql net客户端的bug还是mysql服务器的bug，charset=gb2312是不假，但是必须在等号两边加上两个空格，需要配置成charset = gb2312.是不是very bt？不过这样一来，一切ok了！&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; 4.还有一个缓存同步问题，这个问题将会在下面的一篇中作为一个主题来讲述。albian从一开始考虑支持缓存同步到最后放弃缓存同步功能虽然经历了很长很纠结的过程，但是最后的结果还是放弃之。《放弃缓存同步》这篇bolg更多的是为了以前的兄弟们所写的，当然里面会有一些主观的想法，不一定完全是对的。但是我希望将来有一天我能提供一个示例来证明我的观点。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/Seapeak/aggbug/2109964.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/Seapeak/archive/2011/07/19/2109964.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/Seapeak/archive/2011/07/11/2102572.html</id><title type="text">albian开发笔记三</title><summary type="text">这个星期虽然工作很忙，但是albian的开发进度还是没有拉下。目前albian已经完成了简单的IOC功能（至少对于albian够用了）；还有albian的ORM已经完成的差不多了，下个星期应该可以完成ORM，但是不带cache的。 这个星期的开发中，也碰到了一些问题。记录下来和大家一起探讨。如果对于这些问题有更好的解决方案，欢迎联系我。 1.ORM中的Save功能。其实Save功能很简单，它主要完成的工作就是向数据库中insert或者update一条数据。当需要save的记录不存在于数据库中时，就采用insert操作；当需要save的记录已经存在数据库中时就采用update操作。开始我是想使.</summary><published>2011-07-11T01:16:00Z</published><updated>2011-07-11T01:16:00Z</updated><author><name>xvhfeng</name><uri>http://www.cnblogs.com/Seapeak/</uri></author><link rel="alternate" href="http://www.cnblogs.com/Seapeak/archive/2011/07/11/2102572.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/Seapeak/archive/2011/07/11/2102572.html"/><content type="html">&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这个星期虽然工作很忙，但是albian的开发进度还是没有拉下。目前albian已经完成了简单的IOC功能（至少对于albian够用了）；还有albian的ORM已经完成的差不多了，下个星期应该可以完成ORM，但是不带cache的。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这个星期的开发中，也碰到了一些问题。记录下来和大家一起探讨。如果对于这些问题有更好的解决方案，欢迎联系我。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1.ORM中的Save功能。其实Save功能很简单，它主要完成的工作就是向数据库中insert或者update一条数据。当需要save的记录不存在于数据库中时，就采用insert操作；当需要save的记录已经存在数据库中时就采用update操作。开始我是想使用Exists，大概的意思就是这样 if exists select 1 from table where pk update&amp;hellip;&amp;hellip;. else insert&amp;hellip;.,但是因为albian需要支持异构数据库，这条语句在mysql中不能被执行，只能作罢。但是save功能一定要提供，所以只能另找出路。想到了按照不同的数据库采用不同的方法，比如刚刚那个if exists select 1 from table where pk update&amp;hellip;&amp;hellip;. else insert&amp;hellip;.结构就用在mssql中，然后mysql中使用mysql的方言提供&amp;hellip;&amp;hellip;，这倒未必不是一个好的办法。但是在这种办法的实现在代码上有一定的臃肿而且增加了难度，至少3个方法，然后委托执行。然后就想到了另外一个办法：使用显示的本地对象属性和alibian的orm中所拥有的isnew属性，这样就可以区分对象是否是新的。然后按照isnew属性拼凑sql语句，当isnew为true时需要insert，反之则update。这样既不会出现臃肿的sql语句，还会准确的表达代码的意义。唯一的不好就是需要在每个使用albian orm的数据层对象类实现中需要实现IAlbianObject接口，虽然以前也要实现IAlbianObject接口，但是现在的接口已经不是简单的签名接口了，需要实现两个属性，一个数Id（即数据库的主键），一个是IsNew属性。幸好只是属性，所以实现这个接口需要花的时间不长，而且也非常简单，只是简单的实现属性即可。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 2.IOC的问题。以前也用过IOC，比如spring等等！但是这些IOC给我的感觉就是太重了。虽然spring其实来自于j2ee的改良，但是对于一般的app来说还是太重，配置太多、太复杂。几乎支持了所能想到的所有的注入方式。但是对于Albian来说，其实它的重点在于ORM（其实99%的app重点都是在于和数据库交互），所以IOC只要是够用就可以了。鉴于这个思想，albian实现了一个super轻量级的IOC，不过已经完成了最简单最实用的定义和实现分离。不过虽然简单，albian IOC还是支持loading所有的ioc对象，并且没有前后位置关系的限制；但是对于相互交叉使用的对象，在启动时会报异常，需要程序员通过别的方式来完成相应的功能。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 3.构建查询。对于一个企业级的框架而言，特别是在电子商务这种行业，数据库查询功能永远都是最重要的。在构建查询的时候，曾经想过为了数据库吞吐增加效率，增加查询时指定字段的功能，在实践中，确实也增加了这些功能的接口。但是真正在开发过程中发现了此举其实并不一定增加了app的运营效率。从数据库访问来看，增加了需要查询的指定字段，确实增加了数据库的吞吐效率，因为使用指定字段时每次都会load需要的字段，那些不需要的字段就不会被select出来，这样加快了数据库的查询速度，减少了数据库的吞吐量。但是从整个app（db+app应用程序）来看，其实有的时候反而倒是会减少了整体效率。原因是假设我们的读写比例是4：1（已经很少了，基本上都在9：1左右），我们一个展示功能不太可能只是用一次的指定相同字段查询就可以完成，所以如果采用指定字段，就会出现一个cache过多并且命中率下降的问题。但是如果不指定字段，那么不管你查询什么字段，只要你的pid一样，我就可以优先使用缓存中的对象，这样可以极大的减少对于数据库的压力，而且如果使用本地缓存，那么对于多服务器的缓存同步问题也会容易很多。所以从app的整体考虑点出发，最终还是放弃了指定字段接口，但是这个功能不是没有用处。比如taobao、ebay，当数据库中的表字段多到一定的量，而且当缓存同步的代价小于多缓存内存消耗的代价时，这个接口就有用了。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 后面的事情：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 接下来的事情主要就是完成ORM，目前留下的工作就是完成查询功能和缓存功能。缓存提供两种接口：分布式缓存和本地缓存。故因为可能会启用本地缓存，所以需要增加缓存同步的功能。这部分工作原来准备使用remoting完成，但是后来想到可能很多公司一个系统本身就是异构平台的，而且albian本来就打算后面会移植到java去，所以albian本身也是异构平台的，这部分开发应该会使用原始的TCP来完成。同步服务器程序会使用基于linux的c来完成。完成了同步程序后，对于大型的app还需要一个分布式锁服务器，这部分开发也会使用linux的c来完成。当这些都完成后，albian看上去就会像一个样子了。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/Seapeak/aggbug/2102572.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/Seapeak/archive/2011/07/11/2102572.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/Seapeak/archive/2011/06/28/2091937.html</id><title type="text">albian开发笔记二</title><summary type="text">昨天晚上未加班，回家继续albian。发现了两个问题。 目前albian已经可以简单的保存数据了，albian提供了2个create的重载：保存一个实体、保存多个实体。在保存一个实体的时候未发生问题，数据能准确的根据路由保存到我们指定的数据库和表。在保存多个实体时，开始测试了保存两种不同的实体：比如一个order、另外一个bizoffer，也不会出问题。但是在保存两个相同类型的实体时（比如两个order）。就发生了问题：后面的一个实体数据会覆盖掉前面的一个实体数据。开始怀疑是不是在分配storagecontext的时候出错了，后来debug未发现；再怀疑是不是sql语句出现了问题，debug.</summary><published>2011-06-28T02:07:00Z</published><updated>2011-06-28T02:07:00Z</updated><author><name>xvhfeng</name><uri>http://www.cnblogs.com/Seapeak/</uri></author><link rel="alternate" href="http://www.cnblogs.com/Seapeak/archive/2011/06/28/2091937.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/Seapeak/archive/2011/06/28/2091937.html"/><content type="html">&lt;p&gt;昨天晚上未加班，回家继续albian。发现了两个问题。&lt;/p&gt;&lt;p&gt;目前albian已经可以简单的保存数据了，albian提供了2个create的重载：保存一个实体、保存多个实体。在保存一个实体的时候未发生问题，数据能准确的根据路由保存到我们指定的数据库和表。在保存多个实体时，开始测试了保存两种不同的实体：比如一个order、另外一个bizoffer，也不会出问题。但是在保存两个相同类型的实体时（比如两个order）。就发生了问题：后面的一个实体数据会覆盖掉前面的一个实体数据。开始怀疑是不是在分配storagecontext的时候出错了，后来debug未发现；再怀疑是不是sql语句出现了问题，debug后还是未发现问题；只能看代码，发现自己在建模的时候就已经犯下的错误。在我当初的建模中，storagecontext中的cmd和paras是使用IDictionary&amp;lt;string,dbpara[]&amp;gt;结构来存储的，当时的想法是：一个cmdtext对应一个它自己的参数；这样IDictionary结构正好可以满足要求，但是这种情况，如果发生在cmdtext相同的时候就会出问题了，因为我做了替换的操作，所以后面的实体会更新掉前面的实体数据。其实自己傻掉了，但是cmd-paras的结构是有实体类承载的，这边只要改成IList即可。重构代码，test用例一遍走过，没问题了。&lt;/p&gt;&lt;p&gt;第二个碰到问题的是albian的代码结构问题。开始的时候，我想对DML的操作创建一个接口，然后不同的操作实现这个接口。但是经过create的代码重构，发现除了拼SQL部分的代码不一样之外，别的代码都一模一样。这样的话，这个接口就一个方法（比如叫GetSql），开始感觉还行，但是怎么的越看越不顺眼，后来一想，一个方法的接口不就是委托嘛？全部改成委托，每个实现方法按照委托的签名编写，然后通过参数传递进去不就剩下了很多代码吗？还省下了继承接口这种体力活。这样，这部分也改成了委托。&lt;/p&gt;&lt;p&gt;问题解释：&lt;/p&gt;&lt;p&gt;就上一篇文章中提到的&amp;ldquo;伪分布式事务&amp;rdquo;问题进行一下解答。albian使用的事务管理是每个数据库一个事务，然后分步操作，等全部操作完成后分步提交的方式。这种方式确实会存在一定的风险性。可能出现问题的地方是如果我们有2（A，B）个操作需要提交。当我们提交了A之后再提交B。如果在这两个操作中间（提交了A，正要提交B）发生了网络的中断或者B机器的down机，那么我们的程序将会rollback事务。但是对于A而言，操作已经被commit了，已经成了永久存储，无法被rollback，这样我们的系统中就出现了脏数据。对于这种情况，我们可以根据情况进行补救，比如在保存之后判断是否操作正确，不正确的话执行一段补救代码。但是对于一般的系统，并不需要这样做。类似于刚刚的操作问题其实只有在分布式系统的情况下才可能发生。对于分布式系统，对于单节点的CAP理论已经不能适用了。你必须放弃CAP中的任何一种特性，满足剩下的两种特性。albian放弃的是一致性，其实你分析事务那段源代码很容易就能得出我们使用了&amp;ldquo;最后一致性&amp;rdquo;来保证数据的完整性。在分布式系统中，一般对于数据的完整性要求不那么高，至少不会是100%。高的可能是99。99%，低的可能是95%，甚至还有更低的。当然这些指标数据只是对于一段时间内（比如一个数据库的访问，或者一个用户对于系统的访问）的数据完整性而言，最后我们还是会通过复制、同步等等外在的方法来达到系统内的数据一致性。&lt;/p&gt;&lt;p&gt;就CAP理论在分布式系统中的使用，请g之！&lt;/p&gt;&lt;img src="http://www.cnblogs.com/Seapeak/aggbug/2091937.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/Seapeak/archive/2011/06/28/2091937.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/Seapeak/archive/2011/06/27/2090650.html</id><title type="text">albian开发笔记一</title><summary type="text">albian经过了一个星期的开发，目前一条主线已经完成了。能完成简单的单实体insert操作，并且已经支持了database routing。就目前的开发进度，语句不带cached的albian orm会在一个半月之后完成。 在这段时间内，开发碰到了一些问题，自己也得到了一些启示。 1.首先是databse connection pool问题。一般net链接的都是sql server数据库，而一般我们需要使用connection pool的时候，我们经常在connection string加入pooling = true，max poll size 和 min pool size来控制。一般.</summary><published>2011-06-27T00:30:00Z</published><updated>2011-06-27T00:30:00Z</updated><author><name>xvhfeng</name><uri>http://www.cnblogs.com/Seapeak/</uri></author><link rel="alternate" href="http://www.cnblogs.com/Seapeak/archive/2011/06/27/2090650.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/Seapeak/archive/2011/06/27/2090650.html"/><content type="html">&lt;p&gt;&amp;nbsp; &amp;nbsp; albian经过了一个星期的开发，目前一条主线已经完成了。能完成简单的单实体insert操作，并且已经支持了database routing。就目前的开发进度，语句不带cached的albian orm会在一个半月之后完成。&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 在这段时间内，开发碰到了一些问题，自己也得到了一些启示。&lt;/p&gt;&lt;p&gt;1.首先是databse connection pool问题。一般net链接的都是sql server数据库，而一般我们需要使用connection pool的时候，我们经常在connection string加入pooling = true，max poll size 和 min pool size来控制。一般我们也能如愿的使用上pool。但是当你面对着异构数据库时，这些配置就会出现问题。我在实验mysql驱动链接database时，加入了pooling的配置就会无法创建connection，而albian原则上是需要提供异构数据库支持的，那么别无选择，这个时候就要自己实现connection pool。幸好不是很难，自己实现了一个。有兴趣可以查看源代码的Albian.Pool和Albian.Pool.Imp。再说一句：以前飞客在线的某框架自己实现了connection pool，很多同事都无法理解，现在我算是理解了初衷。看样子是要自己写一下才有发言权，否则纸上谈兵真的没有意思；&lt;/p&gt;&lt;p&gt;2.关于cached。在albian中，一个程序集中使用到很多的cached。挣扎了很久，终于决定牺牲代码的可维护性用来增加程序性能。在Albian.Persistence.Imp程序集的cached文件夹中，到目前为止一共有4个cached的代码，分别存放不同对象的缓存，其实这4个可以合并成一个cached，但是为了性能和看上去的&amp;ldquo;清爽&amp;rdquo;，还是放弃了共用；&lt;/p&gt;&lt;p&gt;3.分库分表的实现。首先考虑的是事务问题。当你提交多个请求到不同的数据库时，那么就要用到分布式事务。MSDTC？如果你的oracle或者mysql在linux上呢？所以，这是必须解决的一个问题。不过树死人活还是有道理的。albian设计了一种&amp;ldquo;伪分布式事务&amp;rdquo;。当我们在提交数据库访问时，albian会把此次访问设置成一个task，task中会有很多个storagecontext，每个storagecontext会对应一个数据库链接。这样，albian会在根据你的实体和配置文件解析你的意图，并且组合成storagecontext，这样最后就会变成一个task上对应着很多个数据库操作的命令，然后我们在每个storagecontext打开数据库连接，并且带本地事务的执行命令，最后由task的context来决定事务是要提交还是回滚，这样就可以即做到分布式事务，又可以对异构数据库的支持。唯一的不足是可能会产生数据的不一致性（如果网络非常不好的话），但是对于分布式环境而言，这样的数据损耗还是可以接受的；&lt;/p&gt;&lt;p&gt;项目前景：&lt;/p&gt;&lt;p&gt;就目前的情况下，下2个星期的工作主要还是在于albian的orm上，最少要完成对于数据库的DML的操作。完成DML后，开始设置albian orm中最大的症结问题：查询。albian将会提供一个人性化、在一定范围内灵活、快速的查询功能。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/Seapeak/aggbug/2090650.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/Seapeak/archive/2011/06/27/2090650.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/Seapeak/archive/2011/06/23/2088050.html</id><title type="text">Albian开发库的设计与规划</title><summary type="text">Albian是一个开源的企业级开发库。它提供了我们在开发过程中使用的ORM、IOC等功能。但是如果Albian只是提供这些功能，那么现在市面上随便找找开源的框架就可以集成。Albian真正的亮点在于它提供的另外几个实用但是市面上很少提供的功能。数据库（表）路由、读写分离、异构数据库、分布式锁服务、缓存同步，分布式锁等等功能。 功能解释： ORM、IOC：谁都知道，不解释； 1.数据库（表）路由：通俗一点说句是分库分表。单我们的数据量猛增的时候，任何一个关系型数据库都无法使用单库、单表来支撑。那么我们这个时候就会想到按照业务分。这也是一种不错的办法。但是当一个业务的数据大到单库单表无法承受时，.</summary><published>2011-06-23T05:43:00Z</published><updated>2011-06-23T05:43:00Z</updated><author><name>xvhfeng</name><uri>http://www.cnblogs.com/Seapeak/</uri></author><link rel="alternate" href="http://www.cnblogs.com/Seapeak/archive/2011/06/23/2088050.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/Seapeak/archive/2011/06/23/2088050.html"/><content type="html">&lt;p&gt;Albian是一个开源的企业级开发库。它提供了我们在开发过程中使用的ORM、IOC等功能。但是如果Albian只是提供这些功能，那么现在市面上随便找找开源的框架就可以集成。Albian真正的亮点在于它提供的另外几个实用但是市面上很少提供的功能。数据库（表）路由、读写分离、异构数据库、分布式锁服务、缓存同步，分布式锁等等功能。&lt;/p&gt;&lt;p&gt;功能解释：&lt;/p&gt;&lt;p&gt;ORM、IOC：谁都知道，不解释；&lt;/p&gt;&lt;p&gt;1.数据库（表）路由：通俗一点说句是分库分表。单我们的数据量猛增的时候，任何一个关系型数据库都无法使用单库、单表来支撑。那么我们这个时候就会想到按照业务分。这也是一种不错的办法。但是当一个业务的数据大到单库单表无法承受时，你怎么办？那么就对单库单表在拆分吧！现在市面上的ORM基本上都没有提供这个功能的，但是这个功能在互联网企业非常需要也非常实用。那么Albian就会支持这种功能。你只需要对于你的实体进行简单的routing配置，在实体保存时，它会自动的根据你的配置和分表算法（比如hash pid）保存到你指定的数据库或者表中；&lt;/p&gt;&lt;p&gt;2.读写分离：这个功能现在一般都是通过数据库同步来完成的！这也未尝不是一种很好的办法！当然，Albian也支持这种做法。其实Albian自己也可以完成这个功能，不需要数据库同步，唯一的遗憾就是当仅仅使用Albian完成这个功能时，对于保存数据有一定的性能损耗，因为保存的时候数据要保存多份（其实根据经验，一下子写只要不超过8份，基本可以接受），当读取的时候，根据你指定的routingName即可从你想加载数据的数据库（表）中加载数据。这个场景比较适合于还没有做搜索，但是需要提供多中查询搜索数据的场景；你可以对一份数据做不同的索引，存放到不同的数据库或者表，这样你可以最大的节省你的搜索性能。&lt;/p&gt;&lt;p&gt;3.异构数据库：Albian支持MSSQL，MySql，Oracle三种数据库，异构数据库就是指一个对数据库进行的request操作（比如insert，update，delete）Albian可以同时使用这三种数据库。比如我们将核心的业务使用Oracle，但是日志记录到MySql，而日志很重要，必须要同步完成（或者说在一个事务中完成），那么Albian就可以给你完成这个任务，Albian会根据你配置的routing，同时把数据库保存到你需要的数据库上（哪怕一个是oracle，一个是Mysql也可以）。&lt;/p&gt;&lt;p&gt;4.分布式锁服务：这是在大型互联网应用中，当我们有多台业务服务器时，我们对于一个业务单体（比如同一个商品进行操作时）时，需要的加锁。我们现在知道的一般是进程内线程间的锁，这是锁住一个对象在一个进程中不能被同时使用的，那么分布式锁就是系统内进程间的锁，锁住一个对象在系统内同时只能被一个进程操作（进程的锁还是使用框架内置的来保证）。这个组件及其重要，并且压力应该比较大。目前考虑这个组件将会使用纯c在linux上实现；&lt;/p&gt;&lt;p&gt;5.缓存同步功能。当我们开发的系统时，对于一些不变或者少变的数据还是放在本地比较好，memcached的速度在0.4毫秒/条，本地应该在0.1毫秒内。但我们的对象很多时，就算是通过memcached来得到数据也是一个很大的时间开销。那么当我们有多台业务机器缓存同一个对象时，如果一台机器上的该缓存对象状态被改变了，我们就要通知别的服务器更新此对象。这就是同步服务的由来。这个组件目前也在考虑是否要放到linux实现？！&lt;/p&gt;&lt;p&gt;6.分布式事务：其实很简单，就是对于两台数据库进行操作，我们能实现原子操作。现在的分布式事务服务比如MSDTC等都比较麻烦，而且使用的代价也很高。Albian准备自己实现一个，虽然可能Albian实现的分布式事务不能完全成为分布式事务，但是实用，能完成功能就行，实用主义！&lt;/p&gt;&lt;p&gt;设计原则：&lt;/p&gt;&lt;p&gt;1.实用主义：用该用的，放弃不该用的；&lt;/p&gt;&lt;p&gt;2.让正确的对象完成正确的事情：比如惰性加载、外键关系。这些在Albian中将不会存在，这部分实在是应该让程序员来完成的。如果程序员这些都不干的话，不知道他应该干什么了？再比如分布式锁服务放到linux，完全是因为windows的内存管理实在是让我费解，而linux这块正好又是强项，那么就linux吧！&lt;/p&gt;&lt;p&gt;3.可控：当你面对现在市面上的一些框架时最愁的是什么？不是功能不能实现，而是可控的太少。什么都实现了，完全傻瓜化，那还要程序员干嘛？&lt;/p&gt;&lt;p&gt;4.一件事情只有一个方法完成：很多框架一件事情提供了很多的实现方法，美其名曰：灵活。但是殊不知这正是&amp;ldquo;罪恶&amp;rdquo;的来源。正因为灵活，所以导致了前一个人干的活，下一个完全看不懂，每上来一个人都有想重构的冲动。所以在Albian中，要完成一件事情只能用一个方法；&lt;/p&gt;&lt;p&gt;Albian开发计划：&lt;/p&gt;&lt;p&gt;1.实现带routing的ORM，大概需要3-4个月时间；&lt;/p&gt;&lt;p&gt;2.实现IOC，这部分现在还未考虑；&lt;/p&gt;&lt;p&gt;3.实现缓存同步；&lt;/p&gt;&lt;p&gt;4.实现分布式锁；&lt;/p&gt;&lt;p&gt;5.将缓存同步和锁迁移到linux上&lt;/p&gt;&lt;p&gt;6.将Albian迁移到java平台；&lt;/p&gt;&lt;p&gt;PS：因为Albian完全是个人利用业余时间开发，故时间上可能有比较大的调整&lt;/p&gt;&lt;p&gt;目前情况：&lt;/p&gt;&lt;p&gt;目前Albian项目已经开始开发，项目的地址为：&lt;a href="http://code.google.com/p/albian/"&gt;http://code.google.com/p/albian/&lt;/a&gt;&amp;nbsp;有兴趣可以关注啦！&lt;/p&gt;&lt;img src="http://www.cnblogs.com/Seapeak/aggbug/2088050.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/Seapeak/archive/2011/06/23/2088050.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry></feed>
