Quantcast
Channel: IT社区推荐资讯 - ITIndex.net
Viewing all 15843 articles
Browse latest View live

前端学习——选择结果为JQuery对象还是DOM对象?

$
0
0
0.前言
    在学习和使用javascript过程中经常使用JQuery的选择器,但是在获取到选择结果之后经常“犯迷糊”,需要一个DOM对象时或者一个JQuery对象,这样的尴尬经常遇到。为了让自己不再迷糊通过博文总结经验教训,希望自己在总结过程中缓慢提高。
    【相关博文】
    【示例页面】——test-ul.html
<!DOCTYPE html><meta charset="utf-8"><html><head> <!-- <script src="jquery.js"></script> --><script src="http://libs.baidu.com/jquery/1.10.2/jquery.min.js"></head> <body> <ul><li>Raspberry</li> <li>Arduino</li> <li>Intel Galileo</li> </ul></body> </html>

1.选择所有的li
    【使用jquery】
var $obj = $("li");
console.log($obj);
    【使用javascript】
var obj = document.getElementsByTagName("li");
console.log(obj);
     【主要区别】
    此时$obj为Jquery对象集合,而obj为DOM对象集合。

2.Jquery对象变为DOM对象——[]方法
var obj = $("li")[0];
console.log(obj);                    // <li>Raspberry</li>
console.log(obj.innerHTML);     // Raspberry
    【说明】
    此处obj为DOM对象,可以使用属性innerHTML。如果使用Jquery的html方法那么浏览器将会发出错误警告。

3.Jquery对象变为DOM对象——get方法
var obj = $("li").get(1);
console.log(obj);                    // <li>Arduino</li>
console.log(obj.innerHTML);     // Arduino
    【说明】
    []方式和Jquery的get方法效果相同。

4.使用javascript达到相同效果
var obj = document.getElementsByTagName("li")[2];
console.log(obj);                    // <li>Intel Galileo</li>
console.log(obj.innerHTML);     // Intel Galileo

5.选择子元素时仍为Jquery对象——eq方法
var $obj = $("li").eq(0);
console.log($obj);
console.log($obj.html());           // Raspberry
    【说明】
    使用eq方法获得Jquery对象,那么获得此对象的HTML内容需要使用Jquery的html()方法,而不是javascript的innerHTML属性。

6.使用Jquery遍历所有子节点
$("li").each(function(index,item){
    console.log(item);                  // item为DOM对象
    console.log(item.innerHTML);   // 依次输出 Raspberry Arduino Intel Galileo
});
    【说明】
    each遍历的item为DOM对象而不是Jquery对象。

7.遍历时再变为Jquery对象
$("li").each(function(index,item){
    $item = $(item);                    // 再次变为Jquery对象
    // console.log($item);              
    console.log($item.html());       // 依次输出 Raspberry Arduino Intel Galileo
});
    【说明】
     $item = $(item)再一次变化出JQuery对象,$(item)此时和$(<li>Raspberry<li>)等价,意为选择一个DOM对象并变为JQuery对象。  

8.使用Javascript遍历所有子节点
var objs = document.getElementsByTagName("li");
for(var i=0; i<objs.length; i++) {
    console.log(objs[i]);
    console.log(objs[i].innerHTML);    // 依次输出 Raspberry Arduino Intel Galileo
}

9.总结
    【1】使用Jquery选择器之后可以使用[]和get获得子DOM,也就是说[]和get具有把Jquery对象转换为DOM对象的功能。
    【2】eq方法获得的对象仍为JQuery对象
    【3】each方法遍历时的item为DOM对象
    【4】JQuery对象使用JQuery方法,DOM对象使用DOM方法。
作者:xukai871105 发表于2014-6-25 22:06:21 原文链接
阅读:43 评论:0 查看评论

【I/O 2014】总结:互通互联的 Android 生态帝国

$
0
0

img_00201
一年一度的 Google I/O 大会刚刚闭幕,本次大会的主角依旧是 Android,但与以往很不同的是,Android 开始进入可穿戴、汽车、电视甚至是笔记本。虽然发布会上没有抢眼的硬件,但是 Google 展示了一个基于 Android 的生态帝国:汽车、手表、手机、电脑、电视、家居电器……的互通互联。

Android L 操作系统

L (Lollipop?)这个系统版本带来了很多重要更新,其中首推的是“材料设计”,以及 Android One 参考设计。“材料设计”将成为未来 Android 以及 Chrome OS 的界面灵魂,为二者体验的统一打下基础,而 Android One 则肩负着攻占低端市场的重任。

googleio_2014_112-730x486

使用“材料设计”的新版 Android 系统包含这些变化:应用图标更加扁平、系统配色经过重新调色、底栏虚拟按键设计。Android L 在图标和功能界面上都进行了改进,比如底部虚拟按键变成了三角形、圆形和方块的线条。而通知不再是只使用顶栏那点面积,而是和 Windows Phone、iOS 那样的大块弹出。

Android One 的基本规格为双卡双待,4.5 英寸屏幕,低于 100 美元价格,这对于亚洲市场十分有吸引力。Android One 将于今年秋季正式启动,首先确认的合作方是印度的三个厂商:Micromax、Karbon 和 Spice,之后将扩散到全球。

此外,新版本的 Android 提供了多达 5000 个的软件接口,并默认采用了 ART 编码,这将使得系统运行更为流畅,启动速度更快,是此前 Dalvik 的两倍,同时兼容 64 位设计。在 Android 4.4 中,这一选项需要在开发者模式中手动开启。

Android L 系统将会在秋天面世。

Android Wear

googleio_2014_642-730x486

Google 早在三月份就公布了这个项目,昨晚的发布会并未更新太多消息,倒是带来了 3 款终端,分别是 LG G Watch、Moto360、Samsung Gear Live。LG G Watch 和 Samsung Gear Live 在美国当天即可买到,Moto360 则在夏季晚些时候上市。

在功能上,它仍然是连接手机通知消息,卡片式的交互方式,整合语音指令。Android Wear 有自己的专属应用,这些应用可以和 Android 标准应用同步,当你利用手表记录语音笔记时,手机上也会有相应内容。

若 Android 应用有针对 Android Wear 的版本,当我们安装了这个应用后,它就会自动安装以及升级相对应的 Android Wear 版本的应用。换言之,Google Play 不会单独开 Android Wear 的应用分类,而是会显示应用是否支持 Android Wear。也许很快,在中国市场会涌现很多 Android Wear 应用商店。

Android Auto

5

紧跟着老对手苹果 CarPlay,Google 发布了 Android Auto,同样,它不是一款独立的系统,而是手机映射过去的界面,驾驶人员通过中控台、汽车按钮以及语音操控 Android 手机。

在提供 Android Auto 的汽车内,司机可以通过语音接听电话、收发短信,通过 Google Maps 查找目的地,turn by turn 导航等。Google Maps 也支持语音操控,支持餐馆、咖啡厅、加油站等生活服务地点搜索,类似你在手机上使用地图那样。目前它还整合了 Pandora, Songza, Stitcher, Spotify, Pocket Casts 和 Tune In Radio 等音乐服务,同时将开放 SDK 供开发者打造应用。

Android Auto 将会和首款车型一起在年底推出。

Android TV

googleio_2014_850-730x383

在经过 Google TV、Nexus Q 不那么成功的尝试之后,Android TV 应运而生。其实说白了,它就是一个 Android 系统,只不过有专属的界面和开发包。

和此前泄露的一样,Android TV 采用卡片式 UI,非常整洁,支持 Android L,推荐版块位于屏幕顶部,任何项目可以自定义放在推荐栏。卡片主要展示电影和电视节目。它还具备手机端、手表上 Android TV 应用,可通过手机、Android Wear 控制电视。

它有自己的 Google Play,将会在秋天发布,并开放特有的 SDK。Android TV 未来将会在索尼、夏普、飞利浦等品牌的 4K 电视上运行。Razer 和华硕将生产基于 Android TV 的盒子。另外,Android TV 可以运行在不同的处理器上。

同时,Google 还更新了 Chromecast,这款小配件颇受欢迎。新版本支持不接入 Wi-Fi 将内容投射到电视屏幕上,同时还可投射应用程序。当用户没有用它来播放视频时,Chromecast 可以依据你的喜好投射一些精美的图片到电视屏幕。

Chrome OS

DSC_3933

Chrome OS 带来了一个十分令人振奋的新特性:支持 Android 应用。也就是说,Chrome OS 有了百万应用作为支撑,现场还成功展示了运行 Android 版 Evernote 和 Vine 的 Chromebook。这招利用移动平台优势往桌面系统回流实在高明,这可能也是 Chrome、Android 整合的又一个迹象。

此外,Android 和 Chorme OS 之间的障碍也被打通了——用户还可以用 Android 手机解锁和登陆 Chromebook。除此之外,他们还可以在 Chromebook 上查看 Android 手机的来电和短信通知。这个功能有点类似苹果在今年 WWDC 上推出的 Handoff。

现在 Chromebook 在教育市场的反响不错,目前已经登陆了 28 个国家,根据 Pichai 的介绍,它的用户评价很高,亚马逊用户评价排名前 10 的笔记本电脑全部是 Chromebook。

Google Fit 平台、Google Drive

googleio_2014_1222-730x486

Google Fit 类似苹果的 HealthKit,将健身应用和设备的数据集合收纳,提供图形化的数据界面,兼容可穿戴和智能体重秤等设备。加入的成员包括 HTC、摩托罗拉、LG、华硕等传统制造商,耐克和阿迪达斯同样是 Google Fit 平台的成员。

另外,发布会上还更新了 Google Drive,包括 Android 版的 Google Slides,Android 上的 QuickOffice 内置了 Google Drive 的 Docs 和 Sheets 应用,可以直接编辑/保存 Office 文件,“suggested edited”特性,以及 Drive for work,目前 Google Drive 月活跃用户高达 1.9 亿。

DSC_3328

source:ifanr


(关注更多人人都是产品经理观点,参与微信互动(微信搜索“人人都是产品经理”或“woshipm”)

【I/O 2014】Google I/O大会不得不看的十大亮点

$
0
0

作者头像
作者: 诸神之黄昏/产品观察家
上帝的归上帝,凯撒的归凯撒
[核心提示]刚刚结束的 Google I/O 大会上,Android 系统提升到了重要高度,Google 的触角都伸向了哪些领域呢?一起来看看极客公园总结的十大看点吧。

北京时间 2014 年 6 月 26 日零时,Google I/O 2014 开发者大会在旧金山 Moscone West 会场准时召开。本次大会发布了全新的 Android 设计,以及一系列备受瞩目硬件产品。下面本文将梳理大会上出现的主要产品及相关亮点。

1. Android One

Google 试图加速 Android 系统在全球(尤其是发展中市场)的推广速度,从而推出了名为「Android One」的激励措施。它向 OEM 厂商提供制造手机的标准模板,从而让他们能够以较低的成本成产出高质量的手机。Android One 使用普通版本的 Android 系统,但是 OEM 厂商和运营商可以通过 Google Play 来加入他们自己的 App。

Micromax 是 Android One 计划的范例之一。它配备双 SIM 卡、4.5 英寸屏幕及 FM 收音机,价格不到 100 美元。Android One 今年秋季从印度开始,随后向世界范围推广,其目标是向下一批十亿用户提供批量供应、高质量且买得起的智能手机。

2. Material Design

Android 将采用的全新设计风格称作「Material Design」(并非此前传言的 Quantum Paper),其视觉和交互上具备的新特性有:

  • 多彩而简洁,既不像 Holo 那样阴暗,也不像 iOS 的半透明;
  • 从纸张和墨水中吸取灵感;
  • 调色板(pallete)功能,可以让开发者自动识别图像中的色彩并适配其 UI;
  • 新的动画效果支持,带有实时阴影的 3D 视觉;
  • 不用解锁即可在锁屏界面处理很多通知;
  • 个人解锁(personal unlocking),可以设置位置、蓝牙设备甚至人声为「信任」,这样就不用输入 PIN 码。

3. Android L

Google 并没有像以前那样明确指出下一代手机操作系统的代号和版本号,而仅仅被模糊地称作「Android L」 。它新增多达 5000 个新的 API,采用新的图标设计(最明显的莫过于导航栏的三个虚拟按键)。不过 Android L 的重头戏并不只是设计,而是其在机器上运行的表现和方式:

  • ART 将成为主要运行方式,它比之前采用的 Dalvik 快两倍,能够更好地管理内容并全面兼容 64 位系统,提升 CPU 和 GPU 性能;
  • 更好的电源管理;
  • Google 未来将通过 Google Play 推送安全更新;
  • 全局数据控制(Universal Data Controls),可以调整应用的隐私设定;
  • Android L 具备文本感知、语音支持和无缝跨平台,且移动优先。
  • 并非只为手机设计,将是全平台运行的系统,实现良好的多屏互动。

4. Android Wear

本次会上亮相了三款智能手表,分别是 LG G Watch、三星 Gear Live 和 Moto 360。它们与手机均能够实现屏幕内容的同步交互,当在手机上安装某个 App 时,手表上也会自动装上与其对应的版本。

Android Wear SDK 让开发者能够快速写出能直接在手表上运行的程序,因为它采用了大量和 Android 系统相同的 API。

LG G Watch、三星 Gear Live 在发布会当天晚些时候即可预订,不过 Moto 360 要到夏季后才可发售。

5. Android Auto

Google 将 Android L 系统带到了汽车里。它在语音识别方面做了特别的加强,如搜索和导航,从而不需要用手操作;阅读信息内容并用语音直接回复。Android Auto 通过 Google Now 的深度使用,使得行车过程更加安全便利。Android Auto 将和 L 一起在今年年底推出。

Android Auto SDK 能够让开发者快速将应用移植到汽车平台。Google 宣布会与包括诸多豪车品牌在内的 40 多家汽车厂商合作,年底就会推送到 25 家汽车 4S 店。

6. Android TV

Google 称 Android TV 是和手机、平板同等重要的产品。它具备极简交互界面,语音控制同样是重点。除了手机和平板之外,用户还能够通过 Android Wear 来控制 Android TV。在 Android TV 上玩游戏时,玩家能够与线上的其他玩家进行互动和网络对战。

索尼、夏普等将推出搭载 Android TV 的 HD 和 4K 电视。

7. Chromecast

Chromecast 获得大量功能升级。其他人无需在同一 WiFi 下也能将内容推送到你的电视上,这样好友之间就能共享正在收看的节目。

新增的 Backdrop 功能在用户没有收看节目时在屏幕上呈现新闻、天气和来自个人 Google+ 的照片。

通过 Chromecast,Android 手机屏幕内容将可以同步到电视上。Google 新增了 Cast Screen 按钮,大幅提升流畅度。三星、Nexus、HTC 和 LG 将支持该项新功能。

8. Chrome OS

Android 和 Chrome OS 的边界正在逐渐缩小。通知信息将在手机和 Chromebook 之间互通,包括电话和文本信息。

不过最大的变化在于外界一直猜想的情景终于出现,那就是本地 Android App 终于可以直接在 Chrome OS 中运行。会上演示了在 Chromebook 上运行的 Evernote、Flipboard 和 Vine。

9. Google Office

单独的 Google Slides 应用将在 Android 上推出。Quickoffice 将能够在本地编辑和保存 Microsoft Office 文件。

Google 在会上公布了一些数据:排名前 100 的创业公司中的 67 家、58% 的世界五百强公司以及排名前 100 大学中的 72 所都在使用 Google 办公套件。这对 Microsoft Office 造成了极大挑战。

10. Google Cloud platform

Google Cloud 支持 SQL、NoSQL、BigQuery 和 Google 自家的计算引擎。目前 Netflix、Snapchat、Airbnb、Secret 等都在使用 Google Cloud。Google 列举了 Secret 只有一名后端开发,以证明其云服务的强大功能。

总结

正如 Google 自己所说的,这是近年来最大最完整的一次升级和扩张。Google 的触角全面伸向各个领域,试图占领每一块屏幕。Android 系统全所未有地上升到一个制高点,超出原先手机和平板的局限,成为 Google 四面出击的核心力量。

Android 和 Chrome 二者分头并进,最终合而为一,成为一个拥有健康生态链的平台。Google 对可穿戴设备、智能家居、汽车三个当前最热门领域表现出的强烈企图不得不令苹果感到强大的竞争压力。

Android L 所采用的全新设计和运行方式使得 Android 系统更快速地走向安全和稳定,而加上其多平台互动的模式,碎片化的现状应该会加速得到改善。

文章头图及配图均来自 The Verge

极客观察均为极客公园原创报道,转载请注明原文链接。

原文地址: http://www.geekpark.net/read/view/207382

关注极客公园,即时获得最新内容: Twitter | 微信:极客公园 | 新浪微博 | 花瓣网 | 人人小站 | Google+ | 点点

深入理解Java:SimpleDateFormat安全的时间格式化

$
0
0

原文引用自:http://www.cnblogs.com/peida/archive/2013/05/31/3070790.html,解决 java.lang.NumberFormatException: multiple points

 想必大家对SimpleDateFormat并不陌生。SimpleDateFormat 是 Java 中一个非常常用的类,该类用来对日期字符串进行解析和格式化输出,但如果使用不小心会导致非常微妙和难以调试的问题,因为 DateFormat 和 SimpleDateFormat 类不都是线程安全的,在多线程环境下调用 format() 和 parse() 方法应该使用同步代码来避免问题。下面我们通过一个具体的场景来一步步的深入学习和理解SimpleDateFormat类。

   一.引子
  我们都是优秀的程序员,我们都知道在程序中我们应当尽量少的创建SimpleDateFormat 实例,因为创建这么一个实例需要耗费很大的代价。在一个读取数据库数据导出到excel文件的例子当中,每次处理一个时间信息的时候,就需要创建一个SimpleDateFormat实例对象,然后再丢弃这个对象。大量的对象就这样被创建出来,占用大量的内存和 jvm空间。代码如下:

复制代码
package com.peidasoft.dateformat;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class DateUtil {
    
    public static  String formatDate(Date date)throws ParseException{
         SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return sdf.format(date);
    }
    public static Date parse(String strDate) throws ParseException{
         SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return sdf.parse(strDate);
    }
}
复制代码

  你也许会说,OK,那我就创建一个静态的simpleDateFormat实例,然后放到一个DateUtil类(如下)中,在使用时直接使用这个实例进行操作,这样问题就解决了。改进后的代码如下:

复制代码
package com.peidasoft.dateformat;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class DateUtil {
    private static final  SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    public static  String formatDate(Date date)throws ParseException{
        return sdf.format(date);
    }
    public static Date parse(String strDate) throws ParseException{

        return sdf.parse(strDate);
    }
}
复制代码

  当然,这个方法的确很不错,在大部分的时间里面都会工作得很好。但当你在生产环境中使用一段时间之后,你就会发现这么一个事实:它不是线程安全的。在正常的测试情况之下,都没有问题,但一旦在生产环境中一定负载情况下时,这个问题就出来了。他会出现各种不同的情况,比如转化的时间不正确,比如报错,比如线程被挂死等等。我们看下面的测试用例,那事实说话:

复制代码
package com.peidasoft.dateformat;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class DateUtil {
    
    private static final  SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    public static  String formatDate(Date date)throws ParseException{
        return sdf.format(date);
    }
    public static Date parse(String strDate) throws ParseException{

        return sdf.parse(strDate);
    }
}
复制代码
复制代码
package com.peidasoft.dateformat;

import java.text.ParseException;
import java.util.Date;

public class DateUtilTest {
    
    public static class TestSimpleDateFormatThreadSafe extends Thread {
        @Override
        public void run() {
            while(true) {
                try {
                    this.join(2000);
                } catch (InterruptedException e1) {
                    e1.printStackTrace();
                }
                try {
                    System.out.println(this.getName()+":"+DateUtil.parse("2013-05-24 06:02:20"));
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            }
        }    
    }
    public static void main(String[] args) {
        for(int i = 0; i < 3; i++){
            new TestSimpleDateFormatThreadSafe().start();
        }
    }
}
复制代码

  执行输出如下:

复制代码
Exception in thread "Thread-1" java.lang.NumberFormatException: multiple points
    at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1082)
    at java.lang.Double.parseDouble(Double.java:510)
    at java.text.DigitList.getDouble(DigitList.java:151)
    at java.text.DecimalFormat.parse(DecimalFormat.java:1302)
    at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1589)
    at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1311)
    at java.text.DateFormat.parse(DateFormat.java:335)
    at com.peidasoft.orm.dateformat.DateNoStaticUtil.parse(DateNoStaticUtil.java:17)
    at com.peidasoft.orm.dateformat.DateUtilTest$TestSimpleDateFormatThreadSafe.run(DateUtilTest.java:20)
Exception in thread "Thread-0" java.lang.NumberFormatException: multiple points
    at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1082)
    at java.lang.Double.parseDouble(Double.java:510)
    at java.text.DigitList.getDouble(DigitList.java:151)
    at java.text.DecimalFormat.parse(DecimalFormat.java:1302)
    at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1589)
    at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1311)
    at java.text.DateFormat.parse(DateFormat.java:335)
    at com.peidasoft.orm.dateformat.DateNoStaticUtil.parse(DateNoStaticUtil.java:17)
    at com.peidasoft.orm.dateformat.DateUtilTest$TestSimpleDateFormatThreadSafe.run(DateUtilTest.java:20)
Thread-2:Mon May 24 06:02:20 CST 2021
Thread-2:Fri May 24 06:02:20 CST 2013
Thread-2:Fri May 24 06:02:20 CST 2013
Thread-2:Fri May 24 06:02:20 CST 2013
复制代码

  说明:Thread-1和Thread-0报java.lang.NumberFormatException: multiple points错误,直接挂死,没起来;Thread-2 虽然没有挂死,但输出的时间是有错误的,比如我们输入的时间是:2013-05-24 06:02:20 ,当会输出:Mon May 24 06:02:20 CST 2021 这样的灵异事件。

   二.原因

  作为一个专业程序员,我们当然都知道,相比于共享一个变量的开销要比每次创建一个新变量要小很多。上面的优化过的静态的SimpleDateFormat版,之所在并发情况下回出现各种灵异错误,是因为SimpleDateFormat和DateFormat类不是线程安全的。我们之所以忽视线程安全的问题,是因为从SimpleDateFormat和DateFormat类提供给我们的接口上来看,实在让人看不出它与线程安全有何相干。只是在JDK文档的最下面有如下说明:

  SimpleDateFormat中的日期格式不是同步的。推荐(建议)为每个线程创建独立的格式实例。如果多个线程同时访问一个格式,则它必须保持外部同步。

  JDK原始文档如下:
  Synchronization:
  Date formats are not synchronized. 
  It is recommended to create separate format instances for each thread. 
  If multiple threads access a format concurrently, it must be synchronized externally.

  下面我们通过看JDK源码来看看为什么SimpleDateFormat和DateFormat类不是线程安全的真正原因:

  SimpleDateFormat继承了DateFormat,在DateFormat中定义了一个protected属性的 Calendar类的对象:calendar。只是因为Calendar累的概念复杂,牵扯到时区与本地化等等,Jdk的实现中使用了成员变量来传递参数,这就造成在多线程的时候会出现错误。

  在format方法里,有这样一段代码:

复制代码
 private StringBuffer format(Date date, StringBuffer toAppendTo,
                                FieldDelegate delegate) {
        // Convert input date to time field list
        calendar.setTime(date);

    boolean useDateFormatSymbols = useDateFormatSymbols();

        for (int i = 0; i < compiledPattern.length; ) {
            int tag = compiledPattern[i] >>> 8;
        int count = compiledPattern[i++] & 0xff;
        if (count == 255) {
        count = compiledPattern[i++] << 16;
        count |= compiledPattern[i++];
        }

        switch (tag) {
        case TAG_QUOTE_ASCII_CHAR:
        toAppendTo.append((char)count);
        break;

        case TAG_QUOTE_CHARS:
        toAppendTo.append(compiledPattern, i, count);
        i += count;
        break;

        default:
                subFormat(tag, count, delegate, toAppendTo, useDateFormatSymbols);
        break;
        }
    }
        return toAppendTo;
    }
复制代码

  calendar.setTime(date)这条语句改变了calendar,稍后,calendar还会用到(在subFormat方法里),而这就是引发问题的根源。想象一下,在一个多线程环境下,有两个线程持有了同一个SimpleDateFormat的实例,分别调用format方法:
  线程1调用format方法,改变了calendar这个字段。
  中断来了。
  线程2开始执行,它也改变了calendar。
  又中断了。
  线程1回来了,此时,calendar已然不是它所设的值,而是走上了线程2设计的道路。如果多个线程同时争抢calendar对象,则会出现各种问题,时间不对,线程挂死等等。
  分析一下format的实现,我们不难发现,用到成员变量calendar,唯一的好处,就是在调用subFormat时,少了一个参数,却带来了这许多的问题。其实,只要在这里用一个局部变量,一路传递下去,所有问题都将迎刃而解。
  这个问题背后隐藏着一个更为重要的问题--无状态:无状态方法的好处之一,就是它在各种环境下,都可以安全的调用。衡量一个方法是否是有状态的,就看它是否改动了其它的东西,比如全局变量,比如实例的字段。format方法在运行过程中改动了SimpleDateFormat的calendar字段,所以,它是有状态的。

  这也同时提醒我们在开发和设计系统的时候注意下一下三点:

  1.自己写公用类的时候,要对多线程调用情况下的后果在注释里进行明确说明

  2.对线程环境下,对每一个共享的可变变量都要注意其线程安全性

  3.我们的类和方法在做设计的时候,要尽量设计成无状态的

  三.解决办法

  1.需要的时候创建新实例:

复制代码
package com.peidasoft.dateformat;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class DateUtil {
    
    public static  String formatDate(Date date)throws ParseException{
         SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return sdf.format(date);
    }
    public static Date parse(String strDate) throws ParseException{
         SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return sdf.parse(strDate);
    }
}
复制代码

   说明:在需要用到SimpleDateFormat 的地方新建一个实例,不管什么时候,将有线程安全问题的对象由共享变为局部私有都能避免多线程问题,不过也加重了创建对象的负担。在一般情况下,这样其实对性能影响比不是很明显的。

  2.使用同步:同步SimpleDateFormat对象

复制代码
package com.peidasoft.dateformat;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class DateSyncUtil {

    private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    public static String formatDate(Date date)throws ParseException{
        synchronized(sdf){
            return sdf.format(date);
        }  
    }
    public static Date parse(String strDate) throws ParseException{
        synchronized(sdf){
            return sdf.parse(strDate);
        }
    } 
}
复制代码

  说明:当线程较多时,当一个线程调用该方法时,其他想要调用此方法的线程就要block,多线程并发量大的时候会对性能有一定的影响。

  3.使用ThreadLocal: 

复制代码
package com.peidasoft.dateformat;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class ConcurrentDateUtil {

    private static ThreadLocal<DateFormat> threadLocal = new ThreadLocal<DateFormat>() {
        @Override
        protected DateFormat initialValue() {
            return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        }
    };

    public static Date parse(String dateStr) throws ParseException {
        return threadLocal.get().parse(dateStr);
    }

    public static String format(Date date) {
        return threadLocal.get().format(date);
    }
}
复制代码

  另外一种写法:

复制代码
package com.peidasoft.dateformat;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class ThreadLocalDateUtil {
    private static final String date_format = "yyyy-MM-dd HH:mm:ss";
    private static ThreadLocal<DateFormat> threadLocal = new ThreadLocal<DateFormat>();     
public static DateFormat getDateFormat() { DateFormat df = threadLocal.get(); if(df==null){ df = new SimpleDateFormat(date_format); threadLocal.set(df); } return df; } public static String formatDate(Date date) throws ParseException { return getDateFormat().format(date); } public static Date parse(String strDate) throws ParseException { return getDateFormat().parse(strDate); } }
复制代码

   说明:使用ThreadLocal, 也是将共享变量变为独享,线程独享肯定能比方法独享在并发环境中能减少不少创建对象的开销。如果对性能要求比较高的情况下,一般推荐使用这种方法。

  4.抛弃JDK,使用其他类库中的时间格式化类:

  1.使用Apache commons 里的FastDateFormat,宣称是既快又线程安全的SimpleDateFormat, 可惜它只能对日期进行format, 不能对日期串进行解析。

  2.使用Joda-Time类库来处理时间相关问题

   

  做一个简单的压力测试,方法一最慢,方法三最快,但是就算是最慢的方法一性能也不差,一般系统方法一和方法二就可以满足,所以说在这个点很难成为你系统的瓶颈所在。从简单的角度来说,建议使用方法一或者方法二,如果在必要的时候,追求那么一点性能提升的话,可以考虑用方法三,用ThreadLocal做缓存。

  Joda-Time类库对时间处理方式比较完美,建议使用。

  参考资料:

  1. http://dreamhead.blogbus.com/logs/215637834.html

  2.http://www.blogjava.net/killme2008/archive/2011/07/10/354062.html



已有 0人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



【Oracle】物理体系结构

$
0
0


一、ORACLE 物理体系结构

  1. 原理结构图

各部分解释:

PGA: 私有内存区,仅供当前发起用户使用。

三个作用

  1. 用户登录后的session信息会保存在PGA。
  2. 执行排序,如果内存不够,oracle会在临时表空间中完成
  3. 保存用户权限信息

SGA: 包含共享池,数据缓冲区,日志缓冲区以及一些相关的进程。

DATABASE: 数据最终存放的地方,其中一块区域是日志存放区。数据和记录日志又由DBWR和LGWR来写入数据库和重做日志组,待一个重做日志组满了之后切换到下一个,等到循环了一次之后,原来排序为第一组的日志会被ARCH进程写入归档日志。

2结构深入

2.1 从一条查询sql语句解析结构

    假设有一条sql: select * from user where user_id='20'

  1. Sql被解析后,(1区)PGA保存其登陆和权限信息。这一点必须注意,如果保存了该信息,下次调用sql的时候就不需要重新校验,直接玩PGA里取就行了。
  2. 随后该sql会匹配一条唯一的HASH值并到达2区的共享池,共享池判断此HASH值是否之前已经存在,如果存在就直接执行就OK了;如果不存在,就要检查sql的语法、语义等进行验证并解析。解析什么呢?就是要把select * from user where user_id='20' 这条语句,在user_id存在索引的情况下,oracle对最优COST做出选择(到底是索引扫描还是全表扫描),作出选择后oracle会把改执行计划和之前的那条HASH值放在一起。
  3. 带着条件,sql下一步会到数据缓冲区中查找是否存在user_id为20的记录。如果缓冲区有则马上返回结果;如果无,则要到3区(database)中查找,无论是否找到都要返回结果。

2.2 从一条更新sql语句解析结构

    假设有一条sql:update user set user_name='萧红'

  1. 如上步骤1.2 。
  2. 把数据的操作记录写到重做日志
  3. 写入数据库中,持久化数据,把数据库user表的user_name 字段都改为萧红。

3提交与回滚

  1. 当用户提交commit的时候,数据并不会马上刷进数据库。数据何时会被刷入数据库?

    这与CKPT进程有关,当缓冲区的数据量达到一定的程度时,CKPT进程会被触发,数据此时才批量刷入数据库。当刷入数据库前断电了怎么办?REDU机制重新执行日志恢复数据。

      2. ROLLBACK 执行的是UNDO

详细请参见《收获,不止Oracle》,本文只作为总结用,如有错误请更正。
作者:gokenpa 发表于2014-6-26 9:59:44 原文链接
阅读:0 评论:0 查看评论

保存android程序崩溃日志到SD卡

$
0
0


	private boolean writeToSDCard(Throwable ex) 
	{
		boolean isDealing = false;
		if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
		{
			RandomAccessFile randomAccessFile = null;
			try
			{
				String fileName = SDCARDROOT + File.separator + "logs" + File.separator + "crash" + File.separator;
				File file = new File(fileName);
				if(!file.exists())
					file.mkdirs();
				randomAccessFile = new RandomAccessFile(fileName + paserTime(System.currentTimeMillis())+ ".log", "rw");
				long fileLength = randomAccessFile.length();
				randomAccessFile.seek(fileLength);
				randomAccessFile.writeBytes(getThrowableInfo(ex));
			} 
			catch (IOException e) 
			{
				e.printStackTrace();
			} 
			finally 
			{
				if (randomAccessFile != null)
				{
					try 
					{
						randomAccessFile.close();
						isDealing = true;
					} 
					catch (IOException e)
					{
						e.printStackTrace();
					}
				}
			}
		}
		return isDealing;
	}

	private static String getThrowableInfo(Throwable ex)
	{
		StringWriter stringWriter = new StringWriter();
		PrintWriter printWriter = new PrintWriter(stringWriter);
		ex.printStackTrace(printWriter);
		return stringWriter.toString();
	}


作者:pmtoam 发表于2014-6-26 9:29:11 原文链接
阅读:6 评论:0 查看评论

java程序cpu占用过高问题分析

$
0
0

针对某个java程序cpu占用过高问题分析,要想找到问题的真正原因,首先要明确cpu过高的进程,通过对进程下线程的分析,定位到具体的应用代码,从而定位问题的原因所在。

    在jdk自带的分析工具中,通过jconsole只能分析到应用程序的相关系统资源使用情况,但无法定位应用程序,故通过此工具了解到应用程序存在问题,但要具体定位到哪块程序不合理造成的是很困难的。
    通常java程序部署在windows或者linux下,首先来介绍一下windows下分析的步骤:
    1:首先,要获取windows下应用程序在操作系统中的进程id,查看的方式,可以从任务管理器中查看,也可以通过命令查看,通过任务管理器查看我这边就不再累赘了,现在介绍一下通过命令查看的方式,首先打开cmd窗口,输入tasklist命令:
 
 
此时发现在应用程序的进程id为6424
    目前应用程序的cpu使用情况如下:
    即项目一起动,程序没有处理任何业务的情况下,cpu占用已经在49左右了,我截图的时候还是偏低了情况。
    其次,要分析一下为什么用占用过高的问题,接下来需要使用一个window的一个自带命令,首先确认一下你的window是否安装了pslist命令程序,如果命令不认别,可以上微软的官网下载,下载地址为:http://technet.microsoft.com/en-us/sysinternals/bb896682.aspx
下载完直接解压到C:\WINDOWS\system32下即可,此命令的作用是获取进程下线程列表,比如说pslist -dmx 6424
从以上截图是6424进程下线程的使用情况,可以发现线程3872的占用率很高,于是现在开始要定位到是哪个应用程序造成的问题
    第三:在这里需要使用jstack jdk自带的一个命令工具,关于jstack的用法,大家可以百度一下,网上关于这个命令的使用详解很多,我在这就不再多说了,通过jstack 6424 >C:\test\cdf.log就可以获取到程序的相关信息
    最后:把占用cpu的线程的id转换成16进行的数据
打开cdf.log文件,从中搜索f20,即可得到以下结果
即在at cn.sslsocket.SSLSocketClient.run(SSLSocketClient.java:239)中run方式就执行某段代码出现占用过高的问题,经过代码定位,发现在此处出现在了死循环,修复即可
 
    通过以上分析,大家应该有一个比较清楚的了解,解决此类问题首先要知道怎么入手,接着要定位到问题的发生点,这样才能从根本上解决问题。
    关于linux下如何解决此问题我在此就不多说了,其它步骤是一样的,只是用到的命令可能不一样而已!


已有 0人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



Linux-HA实战(1)— Heartbeat安装

$
0
0
接触Heartbeat主要是因为之前项目中使用了TFS,最近想给nameserver做HA,因为TFS官方用的Heartbeat,所以刚好了解下,参考了网络上很多内容,这里简单记录下。

环境和软件包

我的机器是两台64位的CentOS,其它Linux机器应该差不多可以参考 官方的说明。 从Heartbeat 2.1.4之后原先的项目被拆分成了三个子项目: cluster-glueresource-agentsheartbeat,导致了配置更加复杂。下面列出了我使用的各个软件包版本并提供了 下载(后面具体安装提供了官方的下载地址,这里自己做个备份)。
  • cluster-glue 1.0.9
  • resource-agents 3.9.2
  • heartbeat 3.0.5
 

Heartbeat源码安装

先最小化系统安装:gcc编译环境等。

# yum install gcc gcc-c++ autoconf automake libtool glib2-devel libxml2-develbzip2-devel e2fsprogs-devel libxslt-devel libtool-ltdl-devel make wget docbook-dtds docbook-style-xsl
 

添加 Haclient 组和 Hacluster 账户。

这个用户主要用来配置respawn的。
# groupadd haclient
# useradd -g haclient hacluster -M -s /sbin/nologin
 

安装libaio

cluster-glue依赖的库。libaio是Linux下的一个异步非阻塞接口,它提供了以异步非阻塞方式来读写文件的方式,读写效率比较高。
# yum install libaio-devel
 

  安装cluster-glue

glue(胶水的意思)是用来粘合Heartbeat、Pacemake以及Resource Agent的一系列类库、工具的集合。
# wget http://hg.linux-ha.org/glue/archive/glue-1.0.9.tar.bz2
# tar jxvf glue-1.0.9.tar.bz2
# cd Reusable-Cluster-Components-glue--glue-1.0.9/
# ./autogen.sh
# ./configure --prefix=/usr/local/heartbeat --sysconfdir=/etc/heartbeat libdir=/usr/local/heartbeat/lib64 LIBS='/lib64/libuuid.so.1'
# make & make install l
 

安装Resource Agents

resource-agents为集群资源的访问提供了一系列标准的接口。
# wget https://codeload.github.com/ClusterLabs/resource-agents/zip/v3.9.2
# unzip v3.9.2
# cd resource-agents-3.9.2/
# ./autogen.sh
# ./configure --prefix=/usr/local/heartbeat --sysconfdir=/etc/heartbeat libdir=/usr/local/heartbeat/lib64 CFLAGS=-I/usr/local/heartbeat/include LDFLAGS=-L/usr/local/heartbeat/lib64 LIBS='/lib64/libuuid.so.1'
//建立一个软连接,避免编译时找不到所需要的包
# ln -s /usr/local/heartbeat/lib64/* /lib64/
注意:LDFLAGS的空格,否则configure时不会报错但make时报错。  

安装Heartbeat

# wget http://hg.linux-ha.org/heartbeat-STABLE_3_0/archive/7e3a82377fa8.tar.bz2
# tar jxvf 7e3a82377fa8.tar.bz2
# cd Heartbeat-3-0-7e3a82377fa8/
# ./bootstrap
# ./configure --prefix=/usr/local/heartbeat --sysconfdir=/etc/heartbeat CFLAGS=-I/usr/local/heartbeat/include  LDFLAGS=-L/usr/local/heartbeat/lib64 LIBS='/lib64/libuuid.so.1'
# vi  /usr/local/heartbeat/include/heartbeat/glue_config.h
 // 删除 glue_config.h 最后一行定义的配置文件路径,避免编译时产生的路径重复定义错误,Shift+g 跳到末行,dd删除
# make && make install
 

配置文件修改

将配置文件复制到 /etc/heartbeat/ 下,并使用sed 修改路径
# cp doc/ha.cf /etc/heartbeat/ha.d/
# cp doc/haresources /etc/heartbeat/ha.d/
# cp doc/authkeys /etc/heartbeat/ha.d/
# chkconfig --add heartbeat
# chkconfig heartbeat on
# chmod 600 /etc/heartbeat/ha.d/authkeys
# sed -i 's#/usr/lib/ocf#/usr/local/heartbeat/usr/lib/ocf#g' /etc/heartbeat/ha.d/shellfuncs
# sed -i 's#/usr/lib/ocf#/usr/local/heartbeat/usr/lib/ocf#g' /etc/heartbeat/ha.d/resource.d/hto-mapfuncs
# sed -i 's#/usr/lib/ocf#/usr/local/heartbeat/usr/lib/ocf#g' /usr/local/heartbeat/usr/lib/ocf/lib/heartbeat/ocf-shellfuncs
 

建立Resource-Agent 的脚本软连接,避免Heartbeat 找不到路径而无法工作

# ln -s /usr/local/heartbeat /usr/lib/ocf
 

Heartbeat yum安装

推荐通过yum来安装Heartbeat,因为无论是tfs官方还是网上一些参考资料都是采用这种方式,这样会少很多路径配置方面的问题。但CentOS默认情况通过yum install heartbeat好像找不到相应的包,需要先下载并安装epel包:
# wget http://mirrors.sohu.com/fedora-epel/6/i386/epel-release-6-8.noarch.rpm
# rpm -ivh epel-release-6-8.noarch.rpm 
# yum install heartbeat*
 

Heartbeat配置

Heartbeat的配置主要涉及到ha.cf、haresources、authkeys这三个文件。其中ha.cf是主配置文件,haresource用来配置要让Heartbeat托管的服务,authkey是用来指定Heartbeat的认证方式,具体参考: http://ixdba.blog.51cto.com/2895551/548625 需要注意几点:
  • authkeys的配置方式:
# auth 1      //认证序号1
# 1 md5 password  //序号1 采用MD5 后面是密钥
auth 后面填写序号,可任意填写,但第二行开头必须为序号名,然后为验证方式,支持三种( crc md5 sha1 )方式验证,最后面是自定义密钥。  
  • 需要保证authkeys有相应的读写权限:
# chmod 600 /etc/heartbeat/ha.d/authkeys
 
  • 对于HA系统来说主从节点的机器时间同步时很重要的。
 
  • 服务要想被Heartbeat托管则必须写成可以通过start/stop来启动和关闭的脚本,然后放在/etc/init.d或者Heartbeat自己的ha.d/resource.d目录中。
 
  • HA的备份节点也需要安装Heartbeat,可以同错scp命令来复制配置文件:
# scp –r node1:/etc/heartbeat/ha.d/*  /etc/heartbeat/ha.d/  
//node1为主节点的主机名(uname -n)
 

测试

  • 创建测试脚本 在Heartbeat的ha.d/resource.d下如下建立一个脚本:
# vi /etc/heartbeat/ha.d/resource.d/test1
输入如下内容:
#!/bin/bash
logger $0 called with $1
case "$1" in
start)
# Start commands go here
echo "start!!!";
;;
stop)
# Stop commands go herer
echo "stop!!!";
;;
status)
# Status commands go here
echo "status!!!";
;;
esac
增加相应的权限:
# chmod 755 test1
可以这样执行该脚本:
# ./test1 start
此处输入图片的描述  
  • 配置haresource文件
# vi /etc/heartbeat/ha.d/haresources
# 输入下面的内容
# ydhl-test1 test1
其中ydhl-test1为uname –n输出的结果。  
  • 配置authkeys,参见上段内容。
 
  • 配置ha.cf
debugfile /var/log/ha-debug
# 用于记录heartbeat的调试信息
logfile /var/log/ha-log
# 用于记录heartbeat的日志信息
logfacility local0
keepalive 2
# 设置心跳间隔
watchdog /dev/watchdog
deadtime 30
# 在30秒后宣布节点死亡
warntime 10
# 在日志中发出“late heartbeat“警告之前等待的时间,单位为秒
initdead 120
 # 网络启动时间
udpport 694
# 广播/单播通讯使用的udp端口
#baud 19200
#serial /dev/ttyS0
# 使用串口heartbeat
bcast eth0
# 使用网卡eth0发送心跳检测
auto_failback on
# 当主节点从故障中恢复时,将自动切换到主节点
watchdog /dev/watchdog
# 该指令是用于设置看门狗定时器,如果节点一分钟内都没有心跳,那么节点将重新启动
node HA-01
node HA-02
# 集群中机器的主机名,与“uname –n”的输出相同。
ping 192.168.0.254
# ping 网关或路由器来检测链路正常
respawn hacluster /usr/local/heartbeat/lib64/heartbeat/ipfail
# respawn调用 ipfail 来主动进行切换
apiauth ipfail gid=haclient uid=hacluster
# 设置启动ipfail的用户和组
 
  • 备份节点配置,参见上段内容。
 
  • 同步主从节点系统时间:可以通过ntpdate来同步
 
  • 启动Heartbeat
在启动之前用下面的命令在主从节点上面测试一下配置是否正确,ReourceManager在Heartbeat安装目录的share/heartbeat目录下。
# ./ResourceManager listkeys `/bin/uname -n`
测试通过后启动主节点和从节点Heartbeat:
# service heartbeat start
通过查看 /var/log/messages可以看到Hearbeat的很多信息:  此处输入图片的描述 可以看到我们前面的测试脚本test1输出的信息。 当通过service heartbeat stop命令停止一个节点的Heartbeat的时候,从日志中可以看到另外一个节点已经感知到了:  此处输入图片的描述 重启后可以看到: 此处输入图片的描述  

FAQ

Q :为什么在/var/log/messages里看到很多下面这样的警告? 此处输入图片的描述A :这种情况是因为部署Heartbeat是直接从其它机器上拷贝过来导致的。直接拷过来会导致两个节点上的uuid冲突,解决方法是强制某个Hearbeat重新生成uuid,先停止Heatbeat然后删除hb_uuid这个文件(可以通过find命令查找)重启就好了:
# rm –rf /usr/local/heartbeat/var/lib/heartbeat/hb_uuid
  Q:什么是“脑裂”问题? A :采用keepalive等心跳软件,需要注意“脑裂”问题: "在“双机热备”高可用(HA)系统中,当联系2个节点的“心跳线”断开时,本来为一整体、动作协调的HA系统,就分裂成为2个独立的个体。由于相互失去了联系,都以为是对方出了故障,2个节点上的HA软件像“裂脑人”一样,“本能”地争抢“共享资源”、争起“应用服务”,就会发生严重后果:或者共享资源被瓜分、2边“服务”都起不来了;或者2边“服务”都起来了,但同时读写“共享存储”,导致数据损坏(常见如数据库轮询着的联机日志出错)。   Q:启动heartbaet的时候可能会报很多库找不到的错误: A:可以先通过find命令查找,然后通过建立软连接就可以解决了:
# ln -s /usr/libexec/pacemaker/* /usr/local/heartbeat/lib64/heartbeat/
 

参考链接

[1] 高可用方案之脑裂问题探讨

   

linux高可用集群heartbeat实现http的高可用

$
0
0
    linux高可用集群的种类很多,比如常见的heartbeat,corosync,rhcs,keepalived,这些集群软件的出现为我们的业务生产环境提供了高可用的保证,本文将简单介绍一下用heartbeat的v2版本来处理一个简单的http高可用集群的搭建。
  
    在实现http高可用集群之前,首先至少需要2台主机,并且需要做3点基本的准备工作:
    1.设置节点名称,并且集群中的所有节点都能通过节点名称去解析集群中的所有主机。为了集群服务的高可用性,这里选择使用/etc/hosts,而且要保证uname -n的值必须和hostname中的值一致。
    2.使用ssh让双机互信。
    3.时间同步。

    在安装heartbeat软件之前,首先把上面的基本工作完成。这里采用2台主机(192.168.1.201,192.168.1.202)来做我们的高可用集群服务。
    1.首先登陆192.168.1.201修改hostname=test1.qiguo.com,在/etc/sysconfig/network中修改HOSTNAME=test1.qiguo.com保证服务器下次启动的时候主机名不变。在/etc/hosts中添加192.168.1.201 test1.qiguo.com test1; 192.168.1.20 test2.qiguo.com test2两行,再在192.168.1.202的这台主机上执行同样的操作。  
    2.在192.168.1.201中执行ssh-keygen -t rsa,然后使用ssh-copy-id -i root@test2实现ssh互信。这个步骤在两个机器上都要执行。
    3.在2台服务器上使用时间同步命令ntpdate 133.100.11.8(可用的ntp服务器ip地址)

    上面三步完成以后,就可以开始安装heartbeat了。可以去epel下载heartbeat的安装包,默认需要下heartbeat-2.1.4-11.el5.i386,heartbeat-gui-2.1.4-11.el5.i386,heartbeat-pils-2.1.4-11.el5.i386,heartbeat-stonith-2.1.4-11.el5.i386 这4个软件包。但是这4个软件包依赖于其它两个软件包perl-MailTools-1.77-1.el5.noarch,libnet-1.1.6-7.el5.i386,所以首先得把这2个软件包给装出来。使用rpm -ivh perl-MailTools-1.77-1.el5.noarch的时候会报依赖关系的错误,所以用yum --nogpgcheck localinstall perl-MailTools-1.77-1.el5.noarch来安装。然后用同样的方式来一起安装剩余的几个包。注意:这些软件要在2个服务器上都要安装

    安装完成heartbeat中,heartbeat默认的配置文件在/etc/ha.d中。ha.d中的rc.d都是资源管理相关的脚本,而resource.d中都是资源代理脚本,服务脚本在/etc/ha.d/heartbeat中。默认装起后的heartbeat没有配置文件,不过可以从/usr/share/doc/heartbeat-2.1.4/中把ha.cf,authkeys和haresources三个文件放在/etc/ha.d中。这3个配置文件的作用是:
    authkeys:密钥文件,这个文件的权限必须为600,否则不能启动heartbeat服务
    ha.cf:heartbeat服务自身的配置文件
    haresources:资源代理配置文件
    下面只需要对这3个文件做下配置就可以实现我们的http高可用集群了。先来看authkeys文件:
    #auth 1   提供密钥的认证方式
    #1 crc   循环冗余校验码认证
    #2 sha1 HI!   sha1算法认证
    #3 md5 Hello!   md5认证
    这里最好采用sha或者md5认证,crc的性能偏低。如果使用md5认证的配置文件如下: 
    auth 1 # 1代码使用下面以1开头的行来作为密钥认证的条件    
    1 md5 9adc3f50d9bb9e9c795fce0a839aa766
    生成md5的方式只需要在shell命令行中,输入echo "qiguo" | md5sum即可

    第二个配置文件ha.cf里面的内容很多,简单介绍如下:
    #debugfile   /var/log/ha-debug #是否启用debug的日志
    logfile   /var/log/ha-log  #日志文件的存放位置
    #logfacility   local0  #日志的设施,如果启用了logfile,就不要启动这个选项
    keepalive   2   #每隔多少时间进行心跳检测一次
    #deadtime   30   #服务器经过多少时间后,还没有检测到其存在,就认为其已经掉线
    #warntime   10   #警告时长
    #initdead   120  #一个集群起来多久,第二个集群还没启动,则认为集群不成功
    #udpport    694  #监听的端口
    #baud     19200  #串行线的发送速率
    bcast    eth0   #以广播的方式发送心跳检测(这里我们使用广播的方式,直接启动bcast eth0即可,这种方式在局域网中机子多的情况下,很耗费资源)
    #mcast    eth0 255.0.0.1 694 1 0  #以多播的方式发送心跳检测
    #ucast    eth0 192.168.1.2 #以单播的方式发送心跳检测
    #auto_failback on  #主节点挂了以后,又恢复了,是否从新跳转到主节点上,on表示从新跳转。
    #stonith baytech /etc/ha.d/conf/stonith.baytech  #定义stonith,怎么隔绝不在线的节点
    #node ken3  #集群内的节点名称,每一个节点需要使用一个node,并且值必须与uname -n的值相同
    node test1.qiguo.com
    node test2.qiguo.com
    #ping 10.10.10.254  #指定ping的地址
    ping 192.168.1.1    #网管地址
    
    第三个配置文件haresources文件是集群资源配置文件。上面提供了很多的配置样例,拿其中一个的样例配置文件来说明: #node1  10.0.0.170 Filesystem::/dev/sda1::/data1::ext2
    node1就是主节点的名称,10.0.0.170就是vip,Filesystem是资源代理(资源代理可以从/etc/ha.d/resource.d和/etc/init.d/从查找,"::"代表该资源代理的参数)。这里我们做http高可用,所以配置如下:
    test1.qiguo.com IPaddr::192.168.1.210/24/eth0 httpd即可
    上述三个配置文件成功后,就把他们复制到192.168.1.202这个主机上。复制完成以后,分别在两台主机上装上httpd服务。装上的httpd服务一定不能让他们开机自动启动。如果全部配置成功以后,可以关闭httpd服务开始启动heartbeat服务了。
   
heartbeat[4825]: 2014/05/11_23:54:35 info: Version 2 support: false
heartbeat[4825]: 2014/05/11_23:54:35 WARN: Logging daemon is disabled --enabling logging daemon is recommended
heartbeat[4825]: 2014/05/11_23:54:35 info: **************************
heartbeat[4825]: 2014/05/11_23:54:35 info: Configuration validated. Starting heartbeat 2.1.4
heartbeat[4826]: 2014/05/11_23:54:35 info: heartbeat: version 2.1.4
heartbeat[4826]: 2014/05/11_23:54:35 info: Heartbeat generation: 1399811242
heartbeat[4826]: 2014/05/11_23:54:35 info: glib: UDP Broadcast heartbeat started on port 694 (694) interface eth0
heartbeat[4826]: 2014/05/11_23:54:35 info: glib: UDP Broadcast heartbeat closed on port 694 interface eth0 - Status: 1
heartbeat[4826]: 2014/05/11_23:54:35 info: glib: ping heartbeat started.
heartbeat[4826]: 2014/05/11_23:54:35 info: G_main_add_TriggerHandler: Added signal manual handler
heartbeat[4826]: 2014/05/11_23:54:35 info: G_main_add_TriggerHandler: Added signal manual handler
heartbeat[4826]: 2014/05/11_23:54:35 info: G_main_add_SignalHandler: Added signal handler for signal 17
heartbeat[4826]: 2014/05/11_23:54:35 info: Local status now set to: 'up'
heartbeat[4826]: 2014/05/11_23:54:36 info: Link test1.qiguo.com:eth0 up.
heartbeat[4826]: 2014/05/11_23:54:36 info: Link 192.168.1.1:192.168.1.1 up.
heartbeat[4826]: 2014/05/11_23:54:36 info: Status update for node 192.168.1.1: status ping
heartbeat[4826]: 2014/05/11_23:54:41 info: Link test2.qiguo.com:eth0 up.
heartbeat[4826]: 2014/05/11_23:54:41 info: Status update for node test2.qiguo.com: status up
harc[4835]:     2014/05/11_23:54:41 info: Running /etc/ha.d/rc.d/status status
heartbeat[4826]: 2014/05/11_23:54:42 info: Comm_now_up(): updating status to active
heartbeat[4826]: 2014/05/11_23:54:42 info: Local status now set to: 'active'
heartbeat[4826]: 2014/05/11_23:54:42 info: Status update for node test2.qiguo.com: status active
harc[4853]:     2014/05/11_23:54:42 info: Running /etc/ha.d/rc.d/status status
heartbeat[4826]: 2014/05/11_23:54:53 info: remote resource transition completed.
heartbeat[4826]: 2014/05/11_23:54:53 info: remote resource transition completed.
heartbeat[4826]: 2014/05/11_23:54:53 info: Initial resource acquisition complete (T_RESOURCES(us))
IPaddr[4907]:   2014/05/11_23:54:53 INFO:  Resource is stopped
heartbeat[4871]: 2014/05/11_23:54:53 info: Local Resource acquisition completed.
harc[4957]:     2014/05/11_23:54:53 info: Running /etc/ha.d/rc.d/ip-request-resp ip-request-resp
ip-request-resp[4957]:  2014/05/11_23:54:53 received ip-request-resp IPaddr::192.168.1.210/24/eth0 OK yes
ResourceManager[4976]:  2014/05/11_23:54:53 info: Acquiring resource group: test1.qiguo.com IPaddr::192.168.1.210/24/eth0 httpd
IPaddr[5002]:   2014/05/11_23:54:53 INFO:  Resource is stopped
ResourceManager[4976]:  2014/05/11_23:54:53 info: Running /etc/ha.d/resource.d/IPaddr 192.168.1.210/24/eth0 start
IPaddr[5097]:   2014/05/11_23:54:53 INFO: Using calculated netmask for 192.168.1.210: 255.255.255.0
IPaddr[5097]:   2014/05/11_23:54:53 INFO: eval ifconfig eth0:0 192.168.1.210 netmask 255.255.255.0 broadcast 192.168.1.255
IPaddr[5068]:   2014/05/11_23:54:53 INFO:  Success
ResourceManager[4976]:  2014/05/11_23:54:53 info: Running /etc/init.d/httpd  start
   观察日志,可以发现高可用的http集群已经启动起来了。现在人为的在test1这台机子上执行shutdown -h now后观察日志的变化。(也可以使用heartbeat自带的hb_standby脚本来切换,默认在/usr/lib/heartbeat目录下)    
heartbeat[11796]: 2014/05/11_20:56:46 info: Received shutdown notice from 'test1.qiguo.com'.
heartbeat[11796]: 2014/05/11_20:56:46 info: Resources being acquired from test1.qiguo.com.
heartbeat[11862]: 2014/05/11_20:56:46 info: acquire local HA resources (standby).
heartbeat[11863]: 2014/05/11_20:56:46 info: No local resources [/usr/share/heartbeat/ResourceManager listkeys test2.qiguo.com] to acquire.
heartbeat[11862]: 2014/05/11_20:56:46 info: local HA resource acquisition completed (standby).
heartbeat[11796]: 2014/05/11_20:56:46 info: Standby resource acquisition done [all].
harc[11888]:    2014/05/11_20:56:46 info: Running /etc/ha.d/rc.d/status status
mach_down[11903]:       2014/05/11_20:56:46 info: Taking over resource group IPaddr::192.168.1.210/24/eth0
ResourceManager[11928]: 2014/05/11_20:56:46 info: Acquiring resource group: test1.qiguo.com IPaddr::192.168.1.210/24/eth0 httpd
IPaddr[11954]:  2014/05/11_20:56:46 INFO:  Resource is stopped
ResourceManager[11928]: 2014/05/11_20:56:46 info: Running /etc/ha.d/resource.d/IPaddr 192.168.1.210/24/eth0 start
IPaddr[12049]:  2014/05/11_20:56:46 INFO: Using calculated netmask for 192.168.1.210: 255.255.255.0
IPaddr[12049]:  2014/05/11_20:56:46 INFO: eval ifconfig eth0:0 192.168.1.210 netmask 255.255.255.0 broadcast 192.168.1.255
IPaddr[12020]:  2014/05/11_20:56:46 INFO:  Success
ResourceManager[11928]: 2014/05/11_20:56:46 info: Running /etc/init.d/httpd  start
mach_down[11903]:       2014/05/11_20:56:46 info: /usr/share/heartbeat/mach_down: nice_failback: foreign resources acquired
mach_down[11903]:       2014/05/11_20:56:46 info: mach_down takeover complete for node test1.qiguo.com.
heartbeat[11796]: 2014/05/11_20:56:46 info: mach_down takeover complete.

   打开备服务器上的日志,注意观察,在备服务器上,已经将资源全部拿了过去,现在继续访问192.168.1.210可以看到显示的就是test2这台主机上的内容,当test1从新上线以后,由于我们上面设置了auto_failback的值为on,所以会再次把资源拿回来,这里就不再放日志文件了。到这里一个简单的高可用httpd服务就已经建立起来了。 

   由于很多情况下httpd高可用服务还会用到共享文件的服务,所以有时候需要共享文件系统。只需要在haresources中多定义一个文件系统的资源。
test1.qiguo.com IPaddr::192.168.1.210/24/eth0 Filesystem::192.168.1.230:/html::/var/www/html::nfs httpd。这里采用nfs文件系统来挂载。
作者:z1547840014 发表于2014-5-12 10:42:23 原文链接
阅读:106 评论:0 查看评论

BMP文件格式详解

$
0
0

位图文件(Bitmap-File,BMP)格式是Windows采用的图像文件存储格式,在Windows环境下运行的所有图像处理软件都支持这种格式。Windows 3.0以前的BMP位图文件格式与显示设备有关,因此把它称为设备相关位图(device-dependent bitmap,DDB)文件格式。Windows 3.0以后的BMP位图文件格式与显示设备无关,因此把这种BMP位图文件格式称为设备无关位图(device-independent bitmap,DIB)格式,目的是为了让Windows能够在任何类型的显示设备上显示BMP位图文件。

      位图文件可看成由4个部分组成:位图文件头(bitmap-file header)、位图信息头(bitmap-information header)、彩色表(color table)和定义位图的字节阵列。可以文本打开方式打开BMP文件。

(1)文件头信息块

0000-0001:文件标识,为字母ASCII码“BM”,42 4D。亦或者与19778相比较。
0002-0005:整个文件大小,单位字节。
0006-0009:保留,每字节以“00”填写。
000A-000D:记录图像数据区的起始位置。从文件开始到位图数据(bitmap data)之间的偏移量。 
(2)图像描述信息块

000E-0011:图像描述信息块的大小,常为28H。
0012-0015:图像宽度。以像素为单位。
0016-0019:图像高度。以像素为单位。
001A-001B:图像的plane总数(恒为1)。
001C-001D:记录像素的位数,很重要的数值,图像的颜色数由该值决定。1 - Monochrome bitmap,4 - 16 color bitmap,8 - 256 color bitmap,F - 16位位图,18 - 24bit (true color) bitmap,20 - 32位位图。

001E-0021:数据压缩方式(数值位0:不压缩;1:8位压缩;2:4位压缩;3:Bitfields压缩)。
0022-0025:图像区数据的大小。单位字节,该数必须是4的倍数。
0026-0029:水平每米有多少像素,在设备无关位图(.DIB)中,每字节以00H填写。
002A-002D:垂直每米有多少像素,在设备无关位图(.DIB)中,每字节以00H填写。
002E-0031:此图像所用的颜色数。

0032-0035:指定重要的颜色数。当该域的值等于颜色数时(或者等于0时),表示所有颜色都一样重要。

     如上,整个位图的信息头共54字节,每个位置有特定含义。

(3)颜色表(调色板)

      颜色表的大小根据所使用的颜色模式而定,其中每4字节表示一种颜色,并以B(蓝色)、G(绿色)、R(红色)、alpha(32位位图的透明度值,一般不需要)。对于24-位真彩色图象就不使用彩色表(同样也包括16位、和32位位图),因为位图中的RGB值就代表了每个象素的颜色;而对于使用索引颜色的,则需要较大的调色板。

(4)图像数据区

       颜色表接下来为位图文件的图像数据区,在此部分记录着每点像素对应的颜色索引号,其记录方式也随颜色模式而定,既2色图像每点占1位(8位为1字节);16色图像每点占4位(半字节);256色图像每点占8位(1字节);真彩色图像每点占24位(3字节)。所以,整个数据区的大小也会随之变化。究其规律而言,可的出如下计算公式:图像数据信息大小=(图像宽度*图像高度*记录像素的位数)/8。扫描行是由底向上存储的,这就是说,阵列中的第一个字节表示位图左下角的像素,而最后一个字节表示位图右上角的像素。

       然而,未压缩的图像信息区的大小。除了真彩色模式外,其余的均大于或等于数据信息的大小。这是为什么呢?原因有两个:
BMP文件记录一行图像是以字节为单位的。因此,就不存在一个字节中的数据位信息表示的点在不同的两行中。也就是说,设显示模式位16色,在每个字节分配两个点信息时,如果图像的宽度为奇数,那么最后一个像素点的信息将独占一个字节,这个字节的后4位将没有意义。接下来的一个字节将开始记录下一行的信息。 

(5)实例分析

     如下的4x4像素的位图

,经过UE打开成16进制文件后,显示如下:

我们可以通过查找对应的数据位来验证上面所分析的各部分信息。这样就比较清楚了。

(6)位图操作常使用的结构体 

      位图头文件结构:

typedef struct tagBITMAPFILEHEADER{
     short bfType;
     int bfSize;
     short bfReserved1;
     short bfReserved2;
     int bfOffBits;
}BITMAPFILEHEADER, *PBITMAPFILEHEADER;

      位图信息结构:

typedef struct tagBITMAPINFOHEADER{
      int biSize;
      int biWidth;
      int biHeight;
      short biPlanes;
      short biBitCount;
      int biCompression;
      int biSizeImage;
      int biXPelsPerMeter;
      int biYPelsPerMeter;
      int biClrUsed;
      int biClrImportant;
}BITMAPINFOHEADER,*PBITMAPINFOHEADER;

 

 

 

转自:http://blog.csdn.net/zhandoushi1982/article/details/5196017

 

 

参考博客:http://blog.csdn.net/o_sun_o/article/details/8351037



已有 0人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



离职程序猿是如何把邮件营销的打开率做到15%滴

$
0
0

高成是一个做广告系统的程序员,毕业以后,做过网络游戏开发,淘宝周边的软件开发等等。

在2010年6月份的某一天,高成在公司做广告系统相关的一个项目,他灵机一动,何不利用这个项目里的用户做一下测试,通过淘宝客的模式流量变现?

这不测不知道,一测吓一跳,在短短的一个小时内,后台就生成了大量的成交订单,高成回忆道:“当时做测试的时候,没想那么多,只是抱着玩一玩的心态,但是测试的结果还是给我的内心产生了不小的冲击,没想到淘宝客这种模式赚钱这么快,比我想象的快。”

于是高居开始做兼职,然后又辞职了做专职,目前其月进账3万,拥有几十万的会员,忙到没有时间吃饭,连上洗手间都能忘记。

我们都知道淘宝客的推广模式有很多种,QQ、微博、网站等等。而高成选择的推广方式是比较少的人会做的,就是—邮件营销。为什么选择邮件营销?高成跟我们分享了两点:

1.做邮件营销受到平台影响的因素较少。而像QQ空间政策限制比较多,不能随便发,官方对于分享的内容也会有限制,一旦影响用户的体验,就会受到限制,严重会封账号。

2.当时自己手头上有一些资源,想做精准营销,利用邮件可以让用户订阅,自己也有技术基础,数据比较好分析,邮件营销对于流量更有把握,更好管理。

 

自写代码抓取邮件数据

其实无论是做微博还是做QQ还会做网站,初期会员(粉丝)的积累都是摆在淘宝客面前的一个难题,做邮件营销也不例外。

对此,高成分享道:“我用的是QQlist,它有个好处,就是订阅的功能比较完善。可以用订阅功能来增加邮件的到达率。“

因为有技术的基础,所以当时就写了一段代码, 通过软件扫号的方式,抓取到数据,给用户发邮件,邀请订阅,只要用户点击订阅,就成为自己的会员了。只要用户成为会员,以后发的邮件是可以100%到达他的邮件里面,这是QQlist的优势,不会去到垃圾邮件里面

布置跟踪代码实现精准营销

刚开始发的时候,高成发送邮件的订阅率在8%左右,这也积累一批初期的会员。后来,为了提升订阅率,他会通过技术手段采集到数据进行筛选。

QQ是一个很大的系统,有了用户的qq号,就能知道qq空间,微博,等级,是否黄钻,地域,年龄,性别等等。根据这个数据,高成就能针对不同的用户发送不同的商品。

在发邮件的过程中,他对推送的商品都布置了跟踪代码。这样就可以知道用户点了哪些商品,喜欢什么品牌,喜欢什么型号。后期再对这些用户做定向营销。这一整套就是一个数据不断筛选沉淀的过程。“说专业一些,这个算得上是数据库营销吧。”

怎样不被系统判定为垃圾邮件?

做邮件营销的,估计大家担心的都是因为对用户的“骚扰”而流失大批用户,其实最悲剧的还不是用户把你的邮件判断成垃圾邮件,而且官方把你的IP发出的邮件判定成垃圾邮件。

高成选择的邮箱是QQ邮箱,在测试的时候他发现,QQ邮件活跃度最高。

腾讯官方对于每个IP发出的邮件量有一定的额度控制,但是每个IP的额度都不一样,它有一套具体的算法。根据用户投诉的比例、邮箱地址是否真实存在、邮件的到达率、打开率等等综合判断。如果综合分高会自动给你加量,反之,就会降低你的量。一旦当天的额度到了,就不能再发,发了就进垃圾箱。

所以为了扩大我的用户群体,高成想办法把用户体验放到第一位。1.做好精准营销,根据用户的喜好推荐商品。2.把邮件的退订按钮,移动到头部,一旦用户不喜欢,他可以及时退订,不然投诉的话,会影响每天邮件的额度。

如何选择产品?

导购的网站在选商品的时候,可以有很多的选择,那么邮件营销在选商品时是否也是一样的思路?高成认为,这其中还是有一些区别,因为邮件基本都是按照专题页面和店铺活动页面去推广。

首先,只选择化妆品,女装,男装三个类目,因为这三个类目的转化比较高,受众比较广。

其次选取的都是前几十家知名度比较广的品牌,因为邮件推出去都是以一个店铺的活动页面去推,品牌的知名度高,意味着用户的接受程度也相对高。

后期在运营的时候,哪些店铺推的比较好,哪些店铺推的不好,优胜劣汰,自然也能沉淀出一些比较好的店铺。

如何选择人群?

前面提到,他们会根据品牌去推广,在人群的选择方面也会根据品牌去选受众。其实有了数据库,其他都好说。

举个例子,比如GXG男装,就可以选择订阅过GXG的,点过GXG,或者点击过其他相似品牌的用户。可以说是根据不同的品牌,去选择不同的人群。

那这里会产生一个问题:如果要是之前没有推过的品牌怎么办?因为没有对应的数据积累。对于这个问题,高成坦言:“对于自己陌生的品牌,这点会比较谨慎。一般看这个品牌的知名度,在大量发送前,会选取小部分的用户,做测试。”

怎么提升邮件打开率和转化率?

现如今,邮箱被各种广告邮件填满是常事。如何让你的邮件能在众多的邮件里面脱颖而出,这还真是一门花心思的学问。高成说:“关于这个,其实就一个要点,不要当成是在给用户推销商品,而且用心给用户服务,我为用户推荐他们喜爱的商品,节省他们的时间,这样用户的接受程度比较高。

高成透露,他通过邮件列表做了很多栏目,比如韩都衣舍一个栏目,家居一个栏目,前期做的时候就是分栏目的去收集用户。 在发送邮件的过程中,又会不断的过滤用户,如果一个邮件发同一个人3次都没有打开,就会把他从这个组剔除,不会再发给他同样的邮件。长期积累下来,发出去的广告就很精准。

另外由于选的商品都是淘宝上做的比较好的大众品牌,像韩都衣舍,裂帛等。他与这些大众品牌建立了很好的合作关系,店铺一旦有大促活动或者上新了,他就会把素材做好,第一时间发给用户,甚至还可能做到比商家通知得还早,用户自然乐意看。

高成透露,他的邮件打开率在15%左右,邮件列表,有10w左右的订阅用户,收入也非常稳定。

后记

现在高成是自己全职在做淘宝客,他说自己也在做网站,想做特卖类的网站,用一个平台把用户积累起来,具体怎么样,现在还没有成型,但是会把淘宝客作为一个事业去做。

 

五张图告诉你美国95后上网都在做啥?

$
0
0

人人都说青少年是人类的未来,对于互联网,他们的喜好,也意味着相关的公司是否将具有美好的“钱景”。据美国综合新闻网站BusinessInsider报道,最近,一家名为Niche的新公司,针对七千名青少年的互联网产品使用习惯进行了广泛调查,从而得出了多个数据。其中显示,社交网络Facebook和原创视频网站YouTube是最受欢迎的两大服务。

从青少年青睐的网络服务上看,同样呈现出“江山代有人才出”,一些创新服务和产品,也获得了青少年的欢迎。

——总体流行度

062005

Facebook和Youtube是最受青少年欢迎的互联网服务

Facebook和YouTube两家名列前茅,其中Facebook在青少年群体中拥有61%的活跃用户,YouTube的比例则为55%。在移动照片分享方面,Facebook收购的Instagram以及靠阅后即焚一炮打响的Snapchat,难分伯仲,两家公司的活跃用户比例都在50%左右,Instagram略高于Snapchat。

微博服务Twitter最近陷入了用户增速下滑的危机,股价暴跌。而这一调查给Twitter带来了好消息,35%的少年用户是Twitter的活跃用户,另外这一数字在过去两年当中呈现增长趋势。

对于网络签到工具Foursquare来说,就有点“悲催”了。在青少年用户中,其活跃用户仅仅占到3%,几乎可以忽略不计。这显示青少年已经对签到这种位置服务失去了兴趣。

062006

高中生最常做的事情

另外对于白领社交网络LinkedIn,也不是好消息。调查结果显示,在高中年龄段的青少年用户中,只有2%的用户经常使用LinkedIn。一直以来,LinkedIn在设法吸引大学申请者这类群体加入,但是成效不大。

——新闻应用

062007

青少年最常访问的新闻网站

青少年青睐列表式的简单快速的新闻报道方式,以及个性十足的新闻垂直网站。15%的用户经常阅读BuzzFeed,21%的用户经常访问“赫芬顿邮报”新闻网站。另外Onion和Reddit大约有10%的活跃用户。

——娱乐

062008

视频网站使用统计

在网络视频领域,YouTube占据王者地位,垄断了55%的青少年用户。另外,以电视剧点播为主的Hulu网站,其只获得了23%的青少年用户。这一数据表明,青少年对于在网上观看电视兴趣并不大,实际上,他们对于传统的电视节目并不怎么感冒。

062009

Pandora为最受欢迎的音乐服务

在音乐流媒体服务上,Pandora名列第一名,获得了37%的活跃用户。以点播为主的音乐流媒体对手Spotify,只有14%的用户。

从数据上看,青少年用户更喜欢随机播放的Pandora,而不是点播具体歌曲的Spotify。

 


© 推荐 for 互联网的那点事. | 猛击下载: iPhone客户端猛击下载: Android客户端

Growth Hacker 奇技淫巧一则:零授权,抓取新浪微博任何用户的微博内容

$
0
0

有时或基于以下凡此种种需求,我们会想要去抓取新浪微博的内容:

  • 产品冷启动,导入外部数据,而非从头积累;
  • 通过大数据+语义分析获取用户兴趣行为偏好,提供智能推荐;
  • 监控微博舆情,对特定关键词或是用户行为进行响应;etc

想必新浪深知微博内容本身是最其有价值的资产,一旦被竞争对手大批量抓取导入,则辛苦建立起的门槛将瞬间化作他人之嫁衣,因此做了非常繁复的安全保护,包括强制登录跳转认证、跨域检测、cookie 植入、禁止账号密码登录而启用 OAuth2.0 等等。

近期个人有一些抓取需求,在查询大量过时的网络资料测试无果后,决定另辟蹊径完成这一目标,并最终测试成功。在此分享出来。(这篇文章将提供解决问题的方法思路,但不会给出具体代码。伸手党请移步百度或 Github。)

你需要准备:一个个人微博账号,我们将透过它去访问其他用户页面,从而抓取。除此之外,别无所求。

解题思路:

1.最初我从微博 Web 版入手,发现即使是浏览器中可正常查看的内容,若直接通过 PHP 的 curl 或者 file_get_contents 读取,也无法直接取得,而是读取到一串 js 代码,作用是跨域判断+cookie判断+header跳转。料想要模拟的请求和一重重越过的限制定会很多。

2.转换思路,既然微博的 Web 版限制很多,那就从移动版下手(移动网页 weibo.cn,而非指移动 App)。移动版碍于手机机能的限制,身份验证要求会降低很多。经过实验,微博移动版的展示规则是:加V用户、微博广场,可直接访问其页面;普通用户,则必须登录才能看到。而判定当前登录用户身份的标识,则应该是手机浏览器本身存储的 cookie 与服务端的某个 session 比对。

3.由于我需要获取普通用户的微博内容,因此还要想办法继续绕。你当然可以每次直接模拟用户登录,但相对繁琐,我希望能一劳永逸。既然移动版的身份判定很大程度上依赖手机浏览器 cookie,而一般浏览器 cookie 不那么容易取,且某些土鳖机型连 cookie 都无法记录(号称 1.3 亿月活跃用户的上市公司一定会照顾穷苦大众的),那么微博一定提供了其他退而求其次的解决方法。于是我注意到了登陆框下的「记住登录状态,需支持并打开手机的cookie功能。」选项。

Screen Shot 2014-05-08 at 5.47.19 PM

See?默认是勾上的,也即是说微博团队主观上是希望用户勾上这个,从而借助 cookie 判断来提高登录安全性的。

我遂果断取消勾选该选项,输入任何一个自己的微博账号密码,点击登录。

4.值得注意的情况出现了:登录时的验证网页走的是 newlogin.sina.cn,而非勾选状态下会走的 login.sina.cn。说明此种情况下,登录验证的确是进行了特殊的处理,从而让没有开启 cookie 功能的手机也能被判定为登录。

查看跳转页面的源代码,发现有如下一行:

如果没有自动跳转,请<a href="http://weibo.cn/?s2w=login&amp;gsid=4uwc8bfa1vnw8ivzI9gUd706F3W&amp;vt=4">点击这里</a>

注意这个 gsid 参数,料想它就是判定本地用户身份的标识,于是整个提取出来(为了我的账号安全,我对这个案例中的 gsid 做了修改,你们直接照搬是无法成功的,还是自己跑一遍登录流程吧)。

Screen Shot 2014-05-08 at 5.56.30 PM

5.最精彩的情况来了。为了验证我们能不能凭这一串 gsid 伪造登录后的身份,我开启 Chrome 的隐身模式,随便找了一个正常情况下必须登录才能看到页面的非加V用户,然后在地址栏后面加上了 gsid 参数,URL 整个变成:

http://weibo.cn/u/1665167973?vt=4&st=7fe6&gsid=4uwc8bfa1vnw8ivzI9gUd706F3W

(当然这里的 gsid 我也做了改动,只是作为演示,实际 gsid 还请自行获得)

直接回车!擦,虽然此前没有执行过登录动作,但是已经以登录后的的身份在看他的页面内容了哟。这样,我就可以直接凭借上述固定 URL 去爬去用户的内容。

Screen Shot 2014-05-08 at 6.01.28 PM

(上图中的「我们都关注XDash」,你就可以知道当前是登录状态,取到了用户身份的。事实上的确如此。)

背后原理应该是,以 GET 方式在 URL 中发送了本地登录后的身份标识,微博服务器比对这串标识来判定对应的登录用户身份,然后返回到本地,本地于是就以这个用户身份登录,堂而皇之地获取数据了。(大一的时候我曾参与过一个基于 ASP 的校园社区的开发,阅读了帝国 CMS 的代码,那时候对于手机用户的身份认证就是这么原始哒。)

现在想要的尽收眼底了,接下来…Hulk,smash!

hulksmash

微博手机版,阿喀琉斯的脚后跟。

Windows装10gRAC需要注意的几个要点

$
0
0

虚拟机:VMware 9.0

OS:Window Server 2003 Enterprise (32 Bit)

Clusterware:10.2.0.1->10.2.0.4

Database:10.2.0.1->10.2.0.5


    以前习惯了在Linu环境下搭建玩RAC,昨天第一次尝试在Windows上玩了一把,有人肯定会觉得很不屑,觉得Windows平台没什么实用价值,谁说不是呢?话虽如此,但也不能说就一定没有用windows的生产环境了,既然如此,那么作为DBA的我们,就要成为多面手,无论处理何种平台,都要做到心中有数,遇事才不会慌了手脚。下面我把部署过程中遇到的一些问题分享一下,不会讲具体操作过程,只会列出几个比较需要注意的问题:


1.必须确保使用administrator用户执行安装,不允许空密码


2.推荐使用远程桌面连接方式安装,如VNC等


3.要修改2个环境变量

TEMP=C:\WINDOWS\TEMP,TMP=C:\WINDOWS\TEMP


4.网络配置(重点)

主网卡(桥接),配上VIP地址,要有网关

副网卡(Host Only),配上PRIV地址,无需网关

配置完后要用PING和NET USE \\NODE1\C$测试一下,看网络是否连同,这是正确安装RAC的基本保障

另外,由于Windows是网络传输敏感性的,所以还要修改一下注册表,在HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters项目中,要添加一个DoubleWord字段,值为1。改完后作为网络连通性测试,还要连一下远程注册表,看能否正常连上节点2的注册表,必须是可以的才行

最后,一定要注意把网卡顺序调成PUBLIC在第一位,PRIVATE在后面,否则安装OUI时,执行到添加节点这里,会自动添加-PRIVv到相应的节点名称后面,如:

原来在%sysroot%\DRIVERS\ETC\HOSTS文件中明明写了NODE NODE-VIP NODE-PRIV将会变成NOD-PRIV NODE-VIP-PRIV NODE-PRIV-PRIV这样,就算你修改成和HOST中配置的文件一样也没用,无法NEXT的,所以一定千万要注意!!!


5.运行services.msc,把其中一个服务关闭,名字是Distributed Tracation Coordinator


6.时间同步也要注意,保证2个节点的时间是一致的,可以双击任务栏中的时间,然后选择“Internet时间”,选择相应的服务器进行同步


7.配置共享磁盘(也是重点)

具体不多说,可以去网上搜命令和方法,主要讲讲我的经验。这块如果配置不好,2个节点间是无法正常通信的,因为RAC环境的两个重要部分OCR和VOTINGDISK都是需要放在共享磁盘中的。主要就是注意,提前规划好磁盘大小,因为一旦确定了OCR和VOTINGDISK磁盘,就不太会再动了,我的经验是,10g的话,OCR只有100多M,给个500M就足够了,VOTINGDISK也不需要给很多,500M也足够了,如果是11g那相应要多给一点,1G吧。Windows查看磁盘工具是DISKPART,挺好用的,具体用法可以不带参数直接输入DISKPART按回车,就能看帮助了,10g我们一般是用裸盘,不要格式化文件系统,也不要给盘符,只要建立好分区和逻辑驱动器就可以了

另外,如果是VMware来搞的话,要注意在“节点名”.vmx文件中添加入disk.locking = "FALSE",否则当你同时启动2个虚拟机时,会报一个xx磁盘被lock的错误弹窗,无法正常开启。


8.做完以上步骤以后,其实就可以clone一个主机作为节点2了,然后修改主机名、网卡IP等信息,需重启生效


9.安装RAC之前,要先用命令预检一下,看各个配置环节有没有疏漏,命令如下:runcluvfy.bat stage -pre crsinst -n node1,node2 [-verbose]

安装完以后,也可以用这个命令再次检验一下:runcluvfy.bat stage -post hwos -n node1,node2 [verbose]


10.坑爹的来了,这个问题困扰了我一天,前前后后装了足足4次,就是关于vipca在10.2.0.1 RAC的bug引发的一系列问题,官方是这么说的,由于Windows在10.2.0.1这个版本下存在Oracle相关服务不能自动启动的BUG,必须安装一个后续PATCH中才有的工具来解决,名字叫做opmd.exe。否则当你顺利装完RAC后,满心欢喜去执行VIPCA就以为大功告成的时候,会很悲催的,会报PRKH-1010和PRKR-1062的错误,丝毫没有别的解决办法,手动去启动SERVICE服务也没用,执行crsctl start crs就卡住,而且日志信息也没有明显的ERROR提示。安装完opmd以后,一切问题都搞定,整个人都轻松了好多,执行VIPCA也正常了。


好了,先写这么多,希望对大家以后在Windows上玩RAC带来一定的帮助。最后应用一下官方对这个bug SOLUTION的说明:

Oracle BUG:4537790 was logged for this issue, although the problem is more of an OS initialization problem than a CSS problem.  The fix for BUG:4537790 is to provide an executable called 'opmd.exe'  .  The opmd.exe allows the creation of a new service called the 'Oracle Process Manager'.   The Oracle Process Manager will control the startup of the clustering services to prevent the OracleCSService (or OracleCMService9i) from starting up before the rest of the OS services have started.  

To resolve this problem, you must obtain the patchset for your release which contains the 'opmd.exe'.  The following patches contain this utility:



作者:aaron8219 发表于2014-6-26 17:38:14 原文链接
阅读:82 评论:0 查看评论

王海亚:淘宝交易系统演进之路

$
0
0

淘宝的交易系统承载了购物车、下单、订单管理等多项淘宝的重要业务,随着淘宝业务量的不断上升,交易系统也随之几经改造。InfoQ此次专访了阿里巴巴架构师王海亚,另外作为ArchSummit深圳2014大会《电商,各走各的路》专题的讲师,王海亚将会分享淘宝交易平台的架构演变及并行化实践。以下为专访全文:

InfoQ:淘宝的交易系统,主要承载了哪些业务?

王海亚:从用户视角来看,交易承担了购物车、下单、订单管理这些功能;从功能视角来看,交易系统包括做业务规则和服务整合的交易平台以及支撑交易功能的底层服务,服务包括商品、优惠、库存、订单、物流等,业务规则主要是确定在不同的购买场景如何使用底层服务的不同功能,比如什么样的购买要走付款减库存,什么样的购买要走预售模式的价格体系和支付体系,什么样的购买要限制使用积分等等。

InfoQ:请您简单介绍下交易系统的架构演进过程。

王海亚:个人把交易系统的演化分成三个阶段,第一个阶段是单应用阶段,那个阶段淘宝的业务比较简单,业务量也比较少,交易系统相对还是很简单的,当时的交易系统只有一个应用,囊括了商品、优惠、物流、订单等功能,一个小的开发团队就能够完成交易系统的开发维护工作。

随着承载的业务越来越多,交易系统变得越来越复杂,需要投入越来越多的开发来维护这个系统。人员规模上去之后,内部沟通的成本、代码管理的越来越高,大家都针对一个代码库做更新,很难保证非常好的功能模块设计,经过持续的代码累积,满足业务需求并行开发越来越难。后来提出了服务化改造,从原来的单一应用中逐步做功能剥离,拆分出多个系统,每个子系统负责不同的功能,由不同的团队维护。交易系统的架构进入第二个阶段,交易系统采用分布式架构,存在多个后台服务系统,多个前端应用。商品、优惠、库存等功能逐步沉淀成纯粹的后台服务系统,原来的交易系统作为前端应用存在。由于组织结构的原因,当时是存在几个交易前端应用,比如说当时的商城也就是后来的天猫,无线团队等等,因为前端内容的差异,都有自己独立的前端应用。

服务化改造之后,从某种程度上缓解了第一代架构的缺陷,但是新的架构在落地过程中还是存在一些问题,比较突出的有两个问题,一是由于功能是从原有单核应用中剥离出来时,缺乏一个明确的功能边界定义,对业务规则和功能的识别没有统一的标准,导致业务规则和功能存在紧耦合,同一个业务的业务规则一部分在前端应用中,一部分在后端服务系统中,业务规则变化又比较快,任何一次规则变化都要涉及到多个团队做配合实施,沟通协调的成本比较大;另外一个问题是由于多个前端应用,前端应用做的比较重,业务逻辑都要在多个前端应用中重复实现,除了开发的人力浪费之外,也引发了很多由于落地节奏不一致导致的业务问题,即使耗费大量精力做沟通协调也无法完全避免此类问题。

在新的系统架构中,对业务规则和功能做了明确的识别,通过集中式的业务规则控制以及功能定制化机制,实现业务规则和功能的完全解耦,多数情况下业务规则变更不会引发后台服务系统的变更,后台服务系统的功能增加也能做到对前端应用的透明。另外在前端应用中引入新的编程框架,通过框架做纯粹的服务整合就能组织出要给用户披露的信息。前端做轻之后,针对不同终端提供统一的业务服务,或者针对不同终端根据单页需要披露的内容来做不同服务的整合,成本都降低很多。

InfoQ:没有改造之前的交易系统,大概遇到了哪些问题?

王海亚:问题主要可以分成三类,第一类问题是业务快速落地很难,由于交易的业务规则变更很快,通过casebycase代码修改,系统中功能与功能之间的耦合越来越多,系统维护成本越来越高。另外业务规则散布在多个前端应用和后端服务系统中,经常由于各个系统的规则不一致或者上线节奏不一致导致业务故障。第二个问题是系统接入的成本很高,由于业务的需要,会引入越来越多新的服务系统提供对应的功能,这些服务都是在一个前端系统中做服务的整合,一个点的不稳定或者性能瓶颈,都会影响整个系统的稳定及用户体验,想通过小成本的尝试来做业务创新的验证成本非常高。第三类问题是前端应用比较重,业务逻辑主要存在于前端应用中,前端应用的页面逻辑和后台逻辑职责边界又不是特别清晰,导致前端应用的开发成本非常大,另外又存在多个前端应用,业务逻辑的一致性很难保证。

InfoQ:新的交易系统是如何解决老系统的问题的?

王海亚:总结来说,可以从7个点来讲。

第一,通过服务治理,把业务规则从原有功能中剥离,明确各个服务所提供功能的完备性及独立性,从系统边界上确保功能之间无耦合。

第二,通过集中式的业务规则管控,保证交易全链路的业务规则统一及业务规则灵活可配置。

第三,通过标准化的交易框架及组件化设计,保证服务在交易平台快速接入。

第四,通过异步并行及容错,提升系统响应速度,减少单点服务故障导致的整体不稳定。

第五,通过开关及预案机制,保证代码的兼容性发布,业务降级容错。

第六,通过流量管控,防止雪崩,保证在正常情况或者某个服务集群能力波动时,整个交易系统不被压垮。

第七,通过在前端应用中做前后端解耦,通过约定的数据模型,前端开发只负责页面展示和交互,实现前端、后端的并行开发,也使得不同终端的自适应可以以较低成本实现。

InfoQ:新的交易系统是如何应对交易洪峰的?

王海亚:由于交易的调用链路比较长,从Web服务器到执行链路中的各个服务系统,包括缓存、DB等存储系统,请求都是以队列的方式被处理。各个系统如果没有处理好容量控制,就会导致请求的堆积,对外呈现的就是响应时长增加。

在处理链路比较长的情况下,这种异常会被放大,链路后面的一个点发生堆积,前面的各个点也会逐步出现堆积。页面应用又是一个用户强交互类型的应用,如果用户发现慢就会刷屏,而后面的系统无法感知接下来要处理的请求是否是有效的请求,这种情况下可能会导致整个网站的瘫痪。我们目前是在前后端应用中都引入流量管控机制,主动拒绝超出自己处理能力之外的请求,保证每个应用都不会被压垮,有多少能力就能把多少能力提供出来。

另外在前端应用处理流控时,主动引导用户到低成本/静态化的页面上,增强用户体验,也能提高网站其它部分的曝光率。整个流量管控体系,除了应用框架的能力之外,还有一些配套的机制,比如自动化压测系统、容量计算公式、自动化扩容/下线等,整个一套体系,确保我们轻松应对交易洪峰。

ArchSummit全球架构师峰会即将于7月18-19日在深圳举行,此次会议重点解析九个当前最受关注的领域,包括:SNS、 移动互联网、 金融、 大数据、 智能硬件、 游戏、 云计算、自动化运维、电商等专题。目前正在火热报名中,感兴趣的读者可以访问 网站主页了解更多信息。

作者:u012407273 发表于2014-6-26 14:07:24 原文链接
阅读:100 评论:0 查看评论

大学文凭还值钱吗?

$
0
0

对于那些大学刚毕业、正在为找工作发愁的大学生来说,有一个令人欣慰的消息,那就是大学文凭还是值学费钱的。

纽约联邦储备银行本周二发布报告称,“即使算上大学的花销,那些有学士学位人,一生的总收入也比那些没上过大学的人来的多”。这项研究是经济学家 Jaison R. Abel 和 Richard Deitz 一同发起的,他们还发现,对于大学毕业生来说,即使他们以后从事的工作不需要大学文凭,大学文凭依然是一个好的投资。目前大约有三分之一的毕业生还没做好就业准备。

相比只有高中学历的人来说,一个有学士学位的人在他22-64岁之间,预计会比没有学士学位的人多挣120万美元,甚至是更多。美国劳工统计局以及美国人口统计局为本研究提供了数据上的支持。

学费的不断上涨,杂多的学生债务,毕业生失业率的不断增长,这一系列问题让人不禁质疑高等教育的含金量。其实早在今年年初的时候,皮尤研究中心就报告称:“相比于只有高中文凭的人来说,拥有学士学位的年轻人会挣更多钱,有大学文凭的人失业率会更低,生活也会更加富裕”。

大学文凭还值钱吗?

美联储报道说在1970到2013这43年间,有学士学位的人平均每年挣6万4500美元,而那些拥有高中学历的人每年约挣4万1000美元。

研究人员称在2013年一个学士学位要花费12.2万美元。数据来源于美国劳工统计局,教育部门,以及学校的董事会。

虽然也有大学毕业生会找到对文凭要求不高的工作,例如在服装店做收银员等等,不过报告称这些大学毕业生挣钱的潜能要比高中毕业生更大。这表明即使是干同一份工作,大学毕业生也可能会比高中毕业生挣得多。

刚毕业的 Katie-Beth Vornberger 认为她的文凭最终会让她成功找到一份好工作。虽然这名来自乔治梅森大学的24岁毕业生一直在勤工俭学,不过到5月为止她还是有2万美元的债务没还。现在的她是一名咨询公司的暑期实习生,她主要负责帮助公司管理社交网络账户。她说她比大学毕业前每小时多挣4美元,而她认为这是她拿到文凭的功劳。

[ 仙剑守望者3 via Japantoday]

为什么 Web 前端开发不抛弃 HTML 和 CSS,用纯 JavaScript 开发?

$
0
0


首先要确定,即使抛开游戏不论,一般的Web应用或者网站,完全用JavaScript开发也是可行的。比如ExtJS、webOS的Enyo等。但是主流Web开发很少采用全JS的方案。原因大体有以下几点:


1. 注重考虑那些无法运行JS的用户代理。

用户使用不支持JS的浏览器(比如较老的手机浏览器),或者禁用脚本。当然你可以选择忽略这一小撮用户,尤其是现在绝大多数网站和应用也是如此选择的,但是至少我们应该对坚持考虑无JS情况的开发者予以基本的尊重。此外,如 Mobile Transcoder或某些手机浏览器的“极速模式”是基于服务器端对网页的解析和重组,是否能支持JS很够呛。

更重要的因素是SEO friendly。如果是全JS生成的网页,搜索引擎无法索引内容。这一点对于许多网站是性命攸关的。

注意,有人提到screen reader。但绝大多数读屏软件是根据DOM来的,因此全部由JS生成DOM也不会有问题。然而这前提是JS所生成的DOM是符合accessibility要求的。


2. 注重HTML/CSS本身的优点。

诚然JS本身也可以通过精心设计的框架和库来实现分离等所有HTML/CSS模型的优点。但是存在许多不确定因素:

1) 有足够好的框架和库吗?
要考虑是否能满足你的业务需求,还可能要考虑性能、可扩展性、之前提到的accessibility、学习曲线、工具链,乃至此框架和库的长久的生存(有人维护,修bug、加新功能比如对HTML5新API的支持之类的)。关键是,理论上说JavaScript具有更高的弹性,但是更大的自由度未必能得到更好的

2) 框架和库给出的抽象模型和HTML/CSS模型的阻抗是否匹配?
假如该框架或库本质上仍然使用HTML/CSS模型,只是改变了语法(比如从markup改为json),那么其提供的好处在哪里?仅仅是语法统一?
如果该框架或库有自己独立的抽象层,比如widget/component等,那么它是建筑在HTML/CSS之上的额外抽象层(即最终映射到HTML/CSS),还是仅仅以HTML/CSS为纯粹实现工具?对于前者,实际上最终会回归HTML/CSS模型。而后者,可以参考的经验教训就是 http://ASP.NET WebForm和JSF。

3) 框架和库所设定的约束能否在开发中一以贯之的执行?
无论是理论或者现实,HTML/CSS模型都算不上完美。但是至少是清晰和较容易被一致的执行的。但是单一语言即使提供分层机制,也容易被绕过——尤其是框架和库本身不够好的情况下,可能由于不能满足需求、有bug等情况而倾向于hack之,更不要说deadline紧迫时。


3. 注重性能。

须知,最终Web应用、页面是在浏览器中执行,而浏览器完全是按照HTML/CSS所设计。抛开Canvas不论,纯JS的实现最终还是要生成DOM。从性能的角度看,纯JS生成DOM自然赶不上直接的markup。同样的道理,就算用CSS预处理器也都会在部署时预先编译——尽管在运行时可以做出更牛逼的特性(然而实际上目前我不知道有任何CSS预处理器干了这样的事情——因为它们都是按照预编译的场景设计的),再如HTML/CSS是按照渐进显示优化的(页面不用全下载完就可以看部分),而纯JS的架构没有精心设计是很难做到的(比如json数据全部下载完你才能parse,数据才可用,DOM才能生成)。

[补充:尽管LESS是可以在运行时执行的,但是从性能的角度出发是不合适的,因为CSS通常必须在页面rendering之前就全部就位。而运行时产生CSS, 就要求在页面rending之前至少要先下载执行LESS的脚本,然后解析编译你的.less源代码。这个性能开销至少目前还不容忽视。]

[补充:性能优化的另一点是基于HTML/CSS的声明性特点,即只表明high-level的目标,浏览器才能获得更大的优化自由度。比如CSS transition/animation,与JavaScript通过修改style达到效果比,前者性能表现要好得多。]


4. 注重Web开发的独特特点。

1) HTML/CSS 都是声明式的,也就是其本身并不希望是程序员来编程。当然,一个编程语言能干所有的事情,但是即使考虑编程本身,为什么在通用编程语言之外还要有SQL、还有以各种语法写的配置文件?

2) HTML/CSS是基于标准的。这与 http://ASP.NET WebForm、JSF、Flash/Flex等私有技术或一个语言和平台下的标准有天壤之别。具体就不展开了。

3) Web开发和一般应用开发有个重大区别是,Web应用、网页的最终表现和行为,或者说Web的用户体验,并不是完全由开发者决定的,而是开发者和用户共同决定的。用户选择不同的设备、不同的浏览器、不同的浏览器设置、不同的浏览器扩展等,都能影响结果。这是缺点,也是优点。看你如何体会了。这里具体不展开。只是一点,纯JavaScript开发通常表示你想更多的控制用户体验,但这并非简单的多写代码就能做到。

[补充:举个例子,表单控件上的autofocus属性,乍一看脚本也可以做嘛。但是其实脚本要做对很难!比如页面已然加载一半,用户开始在某个输入框里输入了,但是后续载入的控件要求focus,如果是脚本实现,通常就武断的调用focus(),打断了用户输入(特别是东亚用户使用输入法时被打断很是受伤)。而HTML本身所定义的属性,是由浏览器实现,则可以做恰当的处理。特别注意的是,从老浏览器到新浏览器的升级,你自然就获得了用户体验的提升。另一方面,用户可以主动选择他想用的浏览器,来主动升级他自己的用户体验。这样的例子还有许多许多,不胜枚举。]

以上。

— 完 —
本文作者: 贺师俊

【知乎日报】 你都看到这啦,快来点我嘛 Σ(▼□▼メ)

此问题还有 55 个回答,查看全部。
延伸阅读:
用 HTML, CSS 和 JavaScript 写移动应用,有哪些值得推荐的框架、工具或者库?
学完了 HTML、CSS、JS 和 jQuery,怎样进一步巩固前端技术呢?

女性更喜欢那些有过前女友的男性

$
0
0

女性更喜欢那些有过前女友的男性

单身男性找到女友的最好方法是什么?

这可能有点难以置信 —— 一项研究的结果表明,女性更喜欢那些有过女朋友的男性,当然了有过太多就不好了。

事实上根据澳大利亚研究人员的调查发现有过太多女朋友的男性比屌丝还要不受欢迎。

这项研究发布在人性周刊上,并且标题是“她有的我也要有”。

在文章中,澳大利亚昆士兰詹姆斯库克大学(James Cook University)的 Ryan Anderson 和 Michele Surby 将人类的寻偶行为和其他动物进行了一下对比。他们注意到了动物更喜欢那些之前与雌性有过接触的雄性,这是一种被称作“配偶复制”的现象。“配偶复制”是一种在鸟类,鱼类等动物中被观测到的行为,这种行为可以帮助雌性挑选出品质更优良的雄性。

研究人员随后调查了人类是否也有这种配偶复制的行为,即女性是否更喜欢有经验的男人。在这项研究中,123名女大学生要求为照片中只有男性一人,或者照片中包含一名男性以及1,2或5名女性剪影的照片打分。这些剪影代表着这些男性过去四年中拥有的女朋友数量。

结果表明女性更喜欢那些有过一到两名女朋友的男性,当然了没有过女朋友的屌丝肯定是没戏的,但却逆袭了有过五位女朋友的男性,后者在这项调查中排名垫底。“或许这暗示着他(有过五位女朋友的男性)比较爱滥交或者不太爱负责,或者他就是有些不合常规——无论出于何种原因,他就是无法保持住一段关系,因此被女性们否决”,研究人员告诉ABC频道。

年龄也是一个选择配偶的因素,年轻的女性较年长的女性更容易发生“配偶复制”的行为。

“我们的研究结果表明女性并不总是独立选择配偶,因此那些曾经被其他女性选为配偶的男性便在新一轮的选择中有着更大的优势。”文章作者随后写到。

[ 636 via Dailymail]

程序员生存定律--升华成高手的可能方法

$
0
0

程序员生存定律这系列的目录在这里: 程序员生存定律--目录

喜欢从头瞄的,可以移步。

-------------------------------------------------------------------------------

一旦度过了初始阶段,做过了前面说的那些事情,那么一个人算是基本入行了,接下来的目标就非常简单,要在选定方向上成为高手。高手意味着专业,而在分工无限细化的年代里,专业则是生存、发展好最为重要的一个前提。

1 高手的定义和养成关键

我估计如果问100个人“什么样的程序员是高手?”,那答案会有100多个。因为同一个人还可能给高手下不同的定义。

在这里我们认为,在特定领域里能搞定大部分人搞不定事情的就是高手。从这样一个定义出发,我们会发现在技术人员和销售人员眼里,高手的内涵是有很大差异的。

纯技术人员更多的关注性能能不能提到极致,并发能不能处理的很好,内存溢出Bug能不能很快搞定,类库的机理熟悉不熟悉等等。而在销售人员的眼里,则在技术外还多看了些东西,比如业务流程熟不熟悉、使用性好不好、能否迅速对应变化、能否在限定工期和预算下搞定任务等。

考虑到职场和产品销售有着非常紧密的关系,我们这里使用后一个视角,而非是单纯的技术视角。

有几类本质上很不同的人都会被视为高手,比如说:

  • 能写出很牛的病毒的

这个不举例子,但当年读过CIH的代码,我是被其精巧给震住了。此外也许搞加密解密的也应该放在这个类别里。

  • 能把一堆3D图形放到64K的

以前专门有个比赛是干这个的,64K大小的EXE能给你放10几分钟很酷的3D动画,第一次见绝对会很震惊。

  • 能迅速调试出问题所在的

内存泄露、多线程同步这类问题往往让人纠缠很久也搞不定,但就是有人能很快的解决这类问题。

  • 能仅靠几个人就架起高并发网站的

新兴Web2.0网站如:Flickr,甚至还可以包括Google,在初期往往是几个人搞起来的,这些人名声不显,但绝对是高手。

  • 能主导开发出很牛的产品的

这个上可以想想Unix和Linux的作者等。

  • 能主持大规模软件设计的

这个往往更有商业价值,我们常说的Martin Fowler应该可以算在这个类别。

  • 能把一种语言研究的特别牛的

想想各个编程语言的创建者,想想C++的大牛们。当然创建某一门语言的也可以归到这个类别里。

  •  能开辟自己方法论的

比如搞CMMI的Watts S. Humphrey

  • 能写出很牛的书的

比如:Windows平台下写了Windows核心编程的Jeffry Richard

  • 能写出很牛的算法的

比如:Donald Knuth

 

这个表应该还可以加长很多,单以大家认可这个角度来看确实高手可以从各个方面冒出来。 

不管在那一方面,要想成为上面所描述的高手总是需要学习、思考、实践这些环节,这没什么可说的。但和软件相关的知识其实多如牛毛,完全不像小说里武功秘籍那么稀缺,几乎可以讲满地都是。这就使选择和集中成为难题。

软件的三个基本特征(技术更迭快、低介入门槛、多内部分野)就像铡刀一样,一旦选择出错,就会把个人的努力切的粉碎,一点价值也留不下来。而与此相对的,则是人的黄金学习时间其实并不多---不过是毕业后的10年左右的时间。

曾经有人希望自己能够从事嵌入式软件的开发,因此给自己买了ARM板,自己在家里花了很多时间来学习并实践相关知识,最终却因为其他的原因进入了一家做网络的公司。这个人等价于被软件的内部分野较多,而彼此间技能流动性较差这样的一个特质斩了一刀,被斩掉的倒不是ARM板,而是自己一年多的辛苦投入。这种情况下强调学的知识将来有用是没有太大意义的,因为还有两刀在等着:如果你三年都不做这个,你今天学到的知识可能会被更迭掉了,同时由于你年纪增长了,可能也不太适合与大批新介入这个行业的人员进行竞争。 

这类事情使软件行业中的成为高手这事变得复杂了。

为了在成为高手这条路上走的顺畅,事实上有三个关键点:一是要有一张全局性的地图,以便选好方向;二是要知道都有那些坑,好绕开它,免得掉进去。三是要有足够的热情和动力,能坚持走下去。下面将分别从这三个方面来说明成为高手途径和方法,而这种途径和方法会因为具体目标不同而有所微调。

2 全局性的地图 

清代著名学者曾对知识地图的必要性做过非常精确的表述:

凡读书最切要者,目录之学也。目录明,方可读书,不明,终是乱读。

---王鸣盛,《十七史商榷》

目录即是地图。

 

对于软件开发的知识,我更愿意使用下面的的“地图”,这不一定是最合理的,但确实对归纳各种软件开发知识有所帮助。

  • 通用的领域知识
  1. 编程语言(C/C++,Java,C#,Python,Perl,PHP等)
  2. 框架和类库(Struts,Spring,OSGi的某个具体实现,MFC,Boost等)
  3. 平台(Windows API,POSIX,.Net Framework※1,Java API,C/C++ Runtime Library等)。恰如Jeffry Richter所说,大多时候可以从内存机制、线程机制、错误处理、异常处理、组件构建、组件组合等方面来进一步考察一个平台。
  4. 计算机体系结构(CPU指令,虚拟存储等)
  5. 数据库
  6. 实用技巧(调试方法,代码生成器等 )
  7. ... ...

※1 有的时候子类别间的界限并不是很容易界定,其中一个主要原因就是存在着像.Net Framework这样涵盖了过多内容的概念。

  • 概念和逻辑创建和优化
  1. 面向对象分析和设计/结构化分析和设计
  2. 设计模式
  3. 重构
  4. 契约式编程
  5. UML ※2
  6. ... ... ※2  从形式上来看UML更近似于一种编程语言,但从其目的上来看也许归在这里是更合适的一种选择。
  • 专业领域知识
  1. 图形图像算法
  2. 网络协议
  3. 人工智能
  4. 数值/非数值类算法
  5. 财务知识
  6. 负载均衡
  7. ... ...

关于软件的间接知识:

  • 需求开发和描述
  • 估算
  1. 估算法。比如,COCOMO, FP等。
  2. 估算术。比如,使用计数等原始办法。

  • 软件工程和方法论
  1. 轻量型方法论。比如敏捷。
  2. 大方法论。比如CMMI
  3. 综合分析。比如,《人月神话》,《人件》所做的工作。 

随着待解决问题越来越复杂,通用的领域知识中,几种技术往往会组成一种技术Stack,他们更需要被看做一组必须一起掌握的知识,比如:LAMP(Linux+Apache+MySQL+Python/PHP)。

当然上面罗列的远不是全部,这种罗列更多的是展示一种分类的方法。通过对这种分类方法的补充和完善,大多可接触到知识都可以被归入特定的类别,比如说:WinRT可以看做一种新的平台,HTML5则可以看做是一种语言等。

每个人可以根据自己的情形,参照上面的分类建立属于自己的地图,有点问题没关系,有就比没有要好很多。接下来依据这样的地图就可以选一条自己的线路,持续累积,寻求实践机会,最终就很可能会成为真正的高手。

而关于增值所需的动力,所要避开的陷阱,将下面陆续提到。

增值、读书与大局观

单纯从达成某一目的而言,读书往往非是绝对必要条件。

秦始皇把书一把火烧了,刘邦项羽一样造反并取得胜利。但读书无疑的可以加速一个人增值的过程,记不得是谁说过:实践无疑是人类最好的老师,但只靠实践来认知世界无疑也是愚蠢的。这是非常精辟的。除此之外,要想培养大局观,那就非读书不可。

每个人的亲身经历,在大的时空背景中往往只是一个简单的截面,这一截面中绝不会包含可以归纳出所有真理的事实,因此只依赖于自身的实践也就必然限定了一个人的视野。 这一点随着一个人的责任范围变大往往会体现为一种制约和限制。所以培根讲:有实际经验的人虽能够处理个别性的事务,但若要综观整体,运筹全局,却唯有学识方能办到。 

即使从实践来看也是如此,要想培养出一种大局观,那就非读书不可。而大局观往往是成为将帅之才的必要条件。

具体到软件而言,有一本很有名的书对培养技术的大局观有帮助:《代码大全》。至于专业性较强的书,反倒是可以根据自己的情景比较容易的选择,这里就不提了。

 

基于上面这样的一张地图,我们就可以具体的去考虑几条进阶路径。

 路径一:由程序员而架构师

架构师是一个很火的职位名字,但你很难给它下精确的定义。

下面所陈述的一切是我个人的理解和体会,我无法保证它和其他人的解释完全吻合。因为架构师,乃至架构设计实在是一种非常模糊的概念,如果你用心去找,可以找到各种定义(甚至IEEE和SEI的定义也不一致),这就导致你只能参照别人,相信自己。

本质来讲架构设计也是设计,所以凡是做设计的都可以称自己为架构师。

当一个系统的规模变大的时候,设计上的决策就具有了特别的价值,并且也越来越需要专门的人来做,架构设计也就越来越像是一种特别的设计。比如说:考虑架构设计的时候,可能需要考虑选用什么样的数据库、选用那个开源框架、选用什么样的硬件平台,这些东西在小规模程序中往往是居于次要地位的。

假设说一个人已经掌握了一门或几门编程语言、面向对象、设计模式、能够很熟练的写出质量较高的代码,接下来他想成为架构师,这个时候他需要做什么?

我个人认为,这时候这个人首先要有一个“专业”。这个专业可以是“金融”,“财务”,“电商”,“管理”等等。这是一种属于某一专业的领域知识,而不是编程技术。如果把需求和最终的代码,看成描述同一事物的一体两面,那么设计始终是要架起这两者间的桥梁。而架桥的时候,怎么可能只知道一端而不知道另一端。

接下来是深化设计所需要的各种通用领域知识(UML、面向对象、性能确保等)。这时和一般所说的设计的一个关键区别是,那就是架构设计要分心思去考虑那些东西用别人的就好了,而那些东西要自己开发。而一般所说的设计技术中,比较侧重自己应该怎么干(面向对象、测试驱动等)。为达成这一目的,就需要对现有技术的优劣有相对比较清晰的认识,比如要能分清楚那些是成熟稳定的技术,那些是处在实验阶段的技术。Pinterest网站就曾经进行过下列这样的架构改进,在这样的改进过程中,不知道各种技术的优劣是代价很大的:

早期阶段:

  • Rackspace
  • 1 small web engine
  • 1 small MySQL DB

2011/1:

  • Amazon EC2 + S3 + CloudFront

  • 1 NGinX, 4 Web Engines (for redundancy, not really for load)

  • 1 MySQL DB + 1 Read Slave (in case master goes down)

  • 1 Task Queue + 2 Task Processors

  • 1 MongoDB (for counters)

  • 2 Engineers

2011/9:

  • Amazon EC2 + S3 + CloudFront

  • 2NGinX, 16 Web Engines + 2 API Engines

  • 5 Functionally sharded MySQL DB + 9 read slaves

  • 4 Cassandra Nodes

  • 15 Membase Nodes (3 separate clusters)

  • 8 Memcache Nodes

  • 10 Redis Nodes

  • 3 Task Routers + 4 Task Processors

  • 4 Elastic Search Nodes

  • 3 Mongo Clusters

  • 3 Engineers

2012/1:

  • Amazon EC2 + S3 + Akamai, ELB

  • 90 Web Engines + 50 API Engines

  • 66 MySQL DBs (m1.xlarge) + 1 slave each

  • 59 Redis Instances

  • 51 Memcache Instances

  • 1 Redis Task Manager + 25 Task Processors

  • Sharded Solr

  • 6 Engineers

2012/10:

  • Amazon EC2 + S3 + Edge Cast,Akamai, Level 3

  • 180 Web Engines + 240 API Engines

  • 88 MySQL DBs (cc2.8xlarge) + 1 slave each

  • 110 Redis Instances

  • 200 Memcache Instances

  • 4 Redis Task Manager + 80 Task Processors

  • Sharded Solr

  • 40 Engineers (and growing)

摘自:

http://highscalability.com/blog/2013/4/15/scaling-pinterest-from-0-to-10s-of-billions-of-page-views-a.html

这个过程比较真实,大家可以参照着想想如果自己来主导,那还欠缺什么。

最后一点要说的是,做架构设计已经相对于在做技术管理工作,至少要适当涉猎估算并能做出合适的任务分解,这样一旦日程紧张,则可以通过增加人手等手段来在质量、成本和进度之间进行均衡。

由于知识面已经扩的比较大,架构师在具体某个专业领域上的深度可能会有所欠缺,比如:在做一款电子消费产品时用到了TTS,但架构师不一定能很好的了解TTS的算法---这是CodeGuru的领域。

架构师所需要达成的最终目标可以形象的描述为:产品经理考虑用户和市场建立了一个模型,那么架构师要能把这东西映射到技术的世界里来。如果是在互联网行业,那么在你的主导设计下要可以做出高并发的网站。换到其他行业也与此类似,从产品的的角度往回看,架构师要能解决和技术相关的所有问题,主导完成商业上有价值的产品或项目的开发工作。实现手段上倒并无限制,可以是购买,可以是组织人员进行开发,只要能平衡短期和长期利益,解决特定的问题即可。

路径二:由程序员而CodeGuru

与架构师相对应,在某些智力密集型的程序中,也需要技能高超的程序员,这种程序员往往被称为Guru。

这条路线里,程序员并不把自己擅长的领域扩的太宽,但在指定领域上会挖掘的很深。驱动、字库、图形库、算法库、OCR等都偏向于这一领域。

假如说,一个程序员在掌握基本语言之后,想往这个方向发展,那么需要的技能和架构师差别很大。比如:一个人如果想往驱动方向发展,那么就需要了解CPU的基本结构、内核调试方式、操作系统中与相应驱动所对应的机制、硬件侧的规格、通讯协议等。

这时候很可能由于程序规模并不十分庞大,面向对象、设计模式这类东西没有太大发挥空间,而是需要处理的是大量或麻烦或艰深的细节。

2013年1月,ITeye发布了一条信息说:Intel面向学生免费提供 C++ 开发工具,并简单的介绍了一下是那些工具免费向学生提供:

  • Intel C++ Composer XE,其中包括:
  1.                Intel C++编译器(高度优化的编译器) 
  2.                Intel数学核心函数库(高性能数学库) 
  3.                Intel线程构建模块(C++任务模型、最流行的C++并行方法) 
  4.                Intel集成性能基元(多媒体基元库) 
  • Intel Advisor XE(推荐的并行开发建模方法)
  • Intel VTune Amplifier XE(非侵入性的性能分析工具)
  • Intel Inspector XE(先进的线程和内存调试工具)

看到这张列表,我们可以思考下要开发这类工具需要什么样的程序员。上面这些工具的开发都属于高难度的工作,和开发大规模的MIS系统完全不同,如果不是某方面的专家,基本不太可能负担起相应的责任。而这类领域则正是Guru的天下。

路径三:由程序员而纯管理

纯管理工作和技术管理工作可以用是否接触乃至编写代码来区分。纯管理工作往往需要把精力放在预算编制、人员职业路径、考评、度量、流程改善这些工作上。一定程度上讲,这等价于和编程工作说拜拜,当然前提是你得有编程经验,有一些通用领域知识和概念创建乃至逻辑优化的知识,否则的话和程序员没法沟通,进而给工作造成障碍。

从需要读的书来看,这时候可能要看过PMBOK,《项目管理修炼之道》,《管理的实践》,《基业长青》等等。

但如果一个人认为想做管理要从PMP开始,那大概是还没太明白管理这项工作的本质。管理本身是一种借势,虽然有技术性的一面,比如要理解挣值曲线这类,但这方面知识其实并没有想的那么复杂---至少没有C++11复杂,只要有时间正常智商的人都可以在不太长的时间内掌握。所以如果你想做管理,并使用了和学习C++语言一样的方法,那基本上是偏离了方向。

抛开机缘这类东西不论,做好管理工作有两点很关键:

一是要把技术工作做的相对比较好。这好像有点学而优则仕的意味,但大多时候人们更愿意相信“将军起于行伍,宰相拔于州郡”,而不愿意相信单只会耍嘴皮子的人。过度务实的人容易迷失于道路,过度务虚的人则容易飘的太高而丧失根基。管理者正应该身处在这两者之间的一个平衡点。

二是要能够借势。要情商比较好,能把很多人组织在一起。这个时候要知道那些东西需要规则化,那些东西需要灵活把握。过度偏向规则是教条,过度偏向灵活则是人治,平衡点始终要根据具体人员的状况,工作特质这些不可改变的事情来把握。这有点微妙。但即使程序员这个群体相对简单,但并不能推翻先人后事这类规则。这不知道是不是东方特色,当你想做管理并想推进事情的时候,终究要理清人际上的关系,否则就和可能会欲速则不达。这点会在第五章进一步展开来谈。

下面我们来看一个具体点的例子,这个例子出自郭致星老师的博客,是一个学员的真实疑问(文字上有修饰),X入职后的现状如下:

开发部现在26个人。基本组织架构是由开发组、需求组、测试组、运维部四个部门组成。需求组的人收集需求,再通过系统指派给开发组,进行开发。开发组的文档严重缺乏。

现在公司内有技术总监和开发部经理的岗位。眼下全公司就X一个项目经理,目前是跟着开发部经理,在熟悉一个核心系统,由于没有任何文档的遗留,所以现在是相当于一个开发人员在开发一些实际的功能,一边开发一边熟悉现有系统。

现在X并没有项目的实际权力,而且整个项目组也只有开发部经理,加上2个开发,再加上1个测试和X共5个人。其中X和其中一个开发都是新来的。

与此同时,业务部门在搞一些流程,但还没做完,没有在开发部进行实施。工作气氛比较沉闷。技术总监和开发部经理,都是技术型的人,比较偏向技术,平时工作也多偏向于具体执行。

在使用一个Redmine系统进行项目管理和BUG跟踪。

这里的系统大部分都类似于产品线制,属于需要长期开发维护的,需求源源不断的来,相应人员也就需要不停的做,没有版本制度,也没有计划和规划。

系统现在主要的问题是性能问题。 

问题就是在这样的一种环境下,X应该如何开始自己的管理工作?

这类问题通常并没有唯一答案,但确实有些通行的手段可供参考,最终做不做的好和个人能力乃至环境关联很紧:

1.了解现有系统的状况,包括规格、代码规模、代码质量、代码内部结构、工作流程、问题所在等。比如说:很可能这类系统缺乏一种整体设计,是靠单纯的增加代码的量堆积出来的,代码冗余非常厉害,数据库的表也创建的比较随意。

2.了解人员。包括人员的能力水平、工作意愿状况、性格。

3.了解公司。尤其是公司的运作风格,有的公司偏人治有的公司偏于规则。短期对这类现行秩序要考虑如何顺应,而不是如何改变。

4.对当前系统的状况和人的状况有所把握后,要对愿景进行描画,比如在功能上做那些改善,对速度做如何改善,目标的高低要适度,要能获得上司和下属的支持。这时候还要能平衡短期和长期目标,既不能长时间投入没有产出,也不能有产出但进步不可见。在这一步骤里最典型的忌讳是急功近利的做超出自己影响力范围的事情。比如:目标与现有人员的能力完全不匹配或者完全不顾及对销售可能产生的影响而单纯的做系统的优化。最理想的情形是,连续达成几个目标,提升自己的影响力。

5.搞清楚团队成员和公司的的基本诉求,在取得成绩的同时尽可能双赢的扩大自己的影响力,目标是确保团队的执行力。

6.逐步导入基本流程,使项目上轨道。但流程不能成为成绩的借口。

7.接下来进一步的规划愿景,看能否取得更大的成绩,比如:挑战是否能做出真正有特色比较优异的产品。

在不同类型的公司里,对应手段上会有不同。比如在规范性比较强的大公司,第4,5两步的权重就会比较低。在上述这样的场景下,PMP这类书籍中所提到的种种技术手段诚然是必要的,但和人打交道的部分(老板、直属上司、下属)往往会对最终的结果产生更大的影响,这是管理工作与纯粹技术工作不同的地方。

------------------------------------------------------------------------------

关于我自己的各种信息,在左边栏可找到,想了解下写这书的人是不是骗子和大忽悠的可以瞄。

最后希望感兴趣的支持 V众投,感觉上这应该是国内最靠谱的生活购物等的问答社区了吧,都是朋友给朋友做的答案,同时实行一人一号,一人一票制度,想找什么答案关注公众号:vzhongtou(左侧有二维码)就行了。
作者:leezy_2000 发表于2014-6-27 7:11:08 原文链接
阅读:0 评论:0 查看评论

NoSQL聚合数据模型 - 大CC

$
0
0

NoSQL聚合数据模型

特点

聚合数据模型的特点就是把经常访问的数据放在一起(聚合在一块);
这样带来的好处很明显,对于某个查询请求,能够在与数据库一次交互中将所有数据都取出来;
当然,以这种方式存储不可避免的会有重复,重复是为了更少的交互;

缺点

  • 聚合结构对某些交互有利,却阻碍另一些交互;
    比如:以学生学号聚合学生信息(含学生姓名、班级、年龄、等信息,甚至英语学科成绩),通过学号查询时,能够在一次交互中查询出该学生的所有信息,但如果想通过学生姓名来查询,就很困难;

  • 不支持跨越多个聚合的ACID事务
    聚合结构在事务方面的支持有限;有一些NOSQL产品实现了简单的事务支持,但对于跨越多个聚合结构的事务并不完善;

规划数据访问方式

选用NoSQL数据库,首要的工作就是设计键名及存放的数据;
设计的原则是尽量减少所需要访问的聚合个数,在尽量少的交互中拿到所需要的数据;
如果发现需要通过多种查询条件来获取数据,可能就选用NOSQL就不合适;关系数据库才是首选;

面向聚合的数据库

  • 键值数据库
    可以存储任意数据,存储的数据对用户不透明,从外面看,只是包含了没有太多意义的大块数据;

    访问方式:通过键来查找

  • 文档数据库
    文档数据库存储时定义了其允许的结构和数据类型,从外面看,可以看到内部结构;
    在存储时限制其中存放的数据,这样带来的好处是能够更灵活的访问数据;
    访问方式:
    1.可用键名查询
    2.可用聚合中的字段查询(定义存储的数据的结构所带来的好处)
    3.可按照聚合内容创建索引

相关:关系数据模型

对于数据模型,我们最熟悉的莫过于关系数据模型;
关系数据模型是一种“聚合无知模型”;
在组织数据时,使用E-R模型规划清晰;
这样带来的好处是很容易以不同的方式来查询数据(各种where条件甚至join)
关系型数据库都是使用关系数据模型,比如oracle;

附 思维导图

NoSQL:数据模型

 

参考

《NoSql精粹》

 

Posted by: 大CC | 27APR,2014
博客: blog.me115.com [ 订阅]
微博: 新浪微博


本文链接: NoSQL聚合数据模型,转载请注明。

Viewing all 15843 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>