精华内容
下载资源
问答
  • 0900-1200 1200-1600 1600-2100 2100-0900 这四个时间段 意思就是相当于一天的开始是9点,然后最后的时间段是晚上9点到第二天早上9点 ,查询的数据都是9点到第二天9点的数据,求大神给点思路
  • 最近写项目,遇到一个将选中时间段平均分割为若干小段,然后根据小段时间在数据库查询求均值的问题,后台大哥犯懒,非说后台做不了,让我分好传给他ヾ(。 ̄□ ̄)ツ゜゜゜好气呦,但还要保持微笑,我就是这么懂礼貌的...

    最近写项目,遇到一个将选中时间段平均分割为若干小段,然后根据小段时间在数据库查询求均值的问题,后台大哥犯懒,非说后台做不了,让我分好传给他ヾ(。 ̄□ ̄)ツ゜゜゜好气呦,但还要保持微笑,我就是这么懂礼貌的好孩子ー( ̄~ ̄)ξ

     

    闲话不多说,来说实现过程

    最开始只是分固定时间段,每天两小时一分,也就直接全写了,后来需求变了,日期选择输入,想要多少天就要多少天,时间大了要求取到的数据量还是那么多

    我:不太好实现啊老板

    boss:啥?别人都能做到,你咋就做不到?你这技术水平怕是有点低了把?

    我:那我试试(MDZZ)

    先确定后台需要什么数据格式,按照存入格式,先写个方法

    1 function range(beginTime, endTime) {//存入格式
    2     this.beginTime = beginTime;
    3     this.endTime = endTime;
    4 }

    考虑到这是一个js文件,数据分割也是固定的等分,就写一个从外部获取参数的函数吧,TimeRange(startTime,endTime)函数用来供页面调用,只传入开始时间,结束时间,不写分多少组了,因为需要的数据总量一般都是固定的,分多少组也是固定的,哪里需要直接来js改就好了

    1  function TimeRange(startTime, endTime) { //传入开始时间var startTime 传入结束时间var endTime 传入格式xxxx-xx-xx 年月日
    2     var amount = 100; //定义分多少组
    3     var startTimes = startTime + " 00:00:00"; //日期添加时分秒 开始日期
    4     var endTimes = endTime + " 23:59:59"; //日期添加时分秒 结束日期
    5

     

    判断一波

    复制代码
    1 if(endTimes <= startTimes) {
    2         alert('结束日期必须大于开始日期!');
    3         return -1;
    4     }
    5 
    6     if(dataDiff > 15) {
    7         alert('单次查询日期不超过两周,请重新选择!');
    8         return -2;
    9     }
    复制代码

    既然平均分,那就得知道时间间隔,计算时间间隔,写个方法直接调用

    复制代码
     1 //计算天数差的函数,通用
     2 function DateDiff(sDate1, sDate2) { //sDate1和sDate2是2006-12-18格式  
     3     var aDate, oDate1, oDate2, iDays
     4     aDate = sDate1.split("-")
     5     oDate1 = new Date(aDate[1] + '-' + aDate[2] + '-' + aDate[0]) //转换为12-18-2006格式  
     6     aDate = sDate2.split("-")
     7     oDate2 = new Date(aDate[1] + '-' + aDate[2] + '-' + aDate[0])
     8     iDays = parseInt(Math.abs(oDate1 - oDate2) / 1000 / 60 / 60 / 24) //把相差的毫秒数转换为天数  
     9     return iDays
    10 }
    复制代码

     

    整理了一下逻辑,伪代码如下

    复制代码
     1     //计算时间段总时间,分割后每段时间间隔,单位(秒)
     2         var timeRange;//存储计算出的时间段
     3         var timeAll ; //总时间间隔
     4         var timeGap ; //分割后时间间隔
     5         var slidingTime = 0; //循环开始条件
     6         var momentTime_front; //时间段前一个值
     7         var momentTime_rear;//时间段后一个值
     8         for(slidingTime; slidingTime < timeAll; slidingTime += timeGap) {
     9             momentTime_front = 计算出的时间前半部分
    10             momentTime_rear = 计算出的时间后半部分
    11             timeRange.push(new range(momentTime_front, momentTime_rear));//将计算后的小段的开始时间和结束时间组合存入timeRange
    12         }
    13         return timeRange;
    14     } 
    复制代码

     

     

    实现后的TimeRange()方法如下:

    复制代码
     1 function TimeRange(startTime, endTime) { //传入开始时间var startTime 传入结束时间var endTime
     2     var amount = 100; //定义分多少组
     3     var timeRange = new Array(); //return数组初始化
     4     var dataDiff = DateDiff(startTime, endTime); //计算两个日期相差天数
     5     var startTimes = startTime + " 00:00:00"; //日期添加时分秒 开始日期
     6     var endTimes = endTime + " 23:59:59"; //日期添加时分秒 结束日期
     7 
     8     if(endTimes <= startTimes) {
     9         alert('结束日期必须大于开始日期!');
    10         return -1;
    11     }
    12 
    13     if(dataDiff > 15) {
    14         alert('单次查询日期不超过两周,请重新选择!');
    15         return -2;
    16     }
    17     if(1) {
    18         //计算时间段总时间,分割后每段时间间隔,单位(秒)
    19         var timeAll = (dataDiff + 1) * 24 * 3600; //总时间间隔
    20         var timeGap = timeAll / amount; //分割后时间间隔
    21         var slidingTime = 0; //循环开始
    22         var momentTime_front;  
    23         var momentTime_rear;
    24         for(slidingTime; slidingTime < timeAll; slidingTime += timeGap) {
    25             momentTime_front = addDatetime(startTimes, slidingTime)
    26             momentTime_rear = addDatetime(startTimes, (slidingTime + timeGap - 1))
    28             timeRange.push(new range(momentTime_front, momentTime_rear));
    29         }
    30         return timeRange;
    31     }
    32 }
    复制代码

     

    接下来的问题就是如何计算 momentTime_front 和 momentTime_rear 了

    我的思路是将开始时间加上秒数转换后的日时分秒等再相加,直接添加的语句或者方法没找到,那咋办?还把我难住了?找不到算了,技不如人,不如自己写一个方法,直接计算两个字符串类型的时间格式相加,哼╭(╯^╰)╮

    先想想怎么写,需要现将字符串转换成字符串类型的数组,将年月日时分秒都分开才能逐个击破,分开后的数组都是字符串类型,没法进行加减运算,强转!先写个将日期类型转换为整型数组的方法

    复制代码
     1 //传入'1970-01-01 00:00:00' 将其分成可计算的整形数组[1970,1,1,0,0,0]
     2 function getArray(dataTime) {
     3     dataTime = dataTime.replace(/ /, "-")
     4     var timesArray = dataTime.split("-");
     5     var timeArray = timesArray[3].split(":");
     6     timesArray[0] = parseInt(timesArray[0]);
     7     timesArray[1] = parseInt(timesArray[1]);
     8     timesArray[2] = parseInt(timesArray[2]);
     9     timesArray[3] = parseInt(timeArray[0]);
    10     timesArray[4] = parseInt(timeArray[1]);
    11     timesArray[5] = parseInt(timeArray[2]);
    12     return timesArray;
    13 }
    复制代码

     

    ok,能计算了,但是增加的时间是秒,还得把秒转换成年月日时分秒格式

    复制代码
     1 //将秒转换为日期格式(最高到天)
     2 function getDatetime(s) {
     3     var dataTime = new Array;
     4     //存入 秒
     5     dataTime[5] = parseInt((s / 1) % 60);
     6     //存入 分
     7     dataTime[4] = parseInt((s / 60) % 60);
     8     //存入 时
     9     dataTime[3] = parseInt((s / 60 / 60) % 24);
    10     //存入 日
    11     dataTime[2] = parseInt(s / 60 / 60 / 24);
    12     //存入 月
    13     dataTime[1] = parseInt(0);
    14     //存入 年
    15     dataTime[0] = parseInt(0);
    16     return dataTime;
    17 }
    复制代码

     

    好嘞,需要的类有了,可是时间相加,不是简单的数字相加啊,还要考虑闰年问题,大月小月问题,嗯....计算大月小月

    【本文由“java程序”发布,2017年10月14日】

    展开全文
  • * 根据段时间区间,按月份拆分成多个时间段 * @author lxg * * 2016年9月5日下午6:18:36 */ public class SplitDateUtil { @Test public void demo (){ List<KeyValueForDate> list = ...
    package com.changchong.util;
    
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.ArrayList;
    import java.util.Calendar;
    import java.util.Date;
    import java.util.List;
    
    import org.junit.Test;
    /**
     * 根据一段时间区间,按月份拆分成多个时间段
     * @author lxg
     *
     * 2016年9月5日下午6:18:36
     */
    public class SplitDateUtil {
    
        @Test
        public void demo(){
            List<KeyValueForDate> list = SplitDateUtil.getKeyValueForDate("2015-08-23","2016-06-10");
            System.out.println("开始日期--------------结束日期");
            for(KeyValueForDate date : list){
                System.out.println(date.getStartDate()+"-----"+date.getEndDate());
            }
        }
    
        /**
         * 根据一段时间区间,按月份拆分成多个时间段
         * @param startDate 开始日期
         * @param endDate  结束日期
         * @return
         */
        @SuppressWarnings("deprecation")
        public static List<KeyValueForDate> getKeyValueForDate(String startDate,String endDate) {
            List<KeyValueForDate> list = null;
            try {
                list = new ArrayList<KeyValueForDate>();
    
                String firstDay = "";
                String lastDay = "";
                Date d1 = new SimpleDateFormat("yyyy-MM-dd").parse(startDate);// 定义起始日期
    
                Date d2 = new SimpleDateFormat("yyyy-MM-dd").parse(endDate);// 定义结束日期
    
                Calendar dd = Calendar.getInstance();// 定义日期实例
                dd.setTime(d1);// 设置日期起始时间
                Calendar cale = Calendar.getInstance();
    
                Calendar c = Calendar.getInstance();
                c.setTime(d2);
    
                int startDay = d1.getDate();
                int endDay = d2.getDate();
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    
                KeyValueForDate keyValueForDate = null;
    
                while (dd.getTime().before(d2)) {// 判断是否到结束日期
                    keyValueForDate = new KeyValueForDate();
                    cale.setTime(dd.getTime());
    
                    if(dd.getTime().equals(d1)){
                        cale.set(Calendar.DAY_OF_MONTH, dd
                                .getActualMaximum(Calendar.DAY_OF_MONTH));
                        lastDay = sdf.format(cale.getTime());
                        keyValueForDate.setStartDate(sdf.format(d1));
                        keyValueForDate.setEndDate(lastDay);
    
                    }else if(dd.get(Calendar.MONTH) == d2.getMonth() && dd.get(Calendar.YEAR) == c.get(Calendar.YEAR)){
                        cale.set(Calendar.DAY_OF_MONTH,1);//取第一天
                        firstDay = sdf.format(cale.getTime());
    
                        keyValueForDate.setStartDate(firstDay);
                        keyValueForDate.setEndDate(sdf.format(d2));
    
                    }else {
                        cale.set(Calendar.DAY_OF_MONTH,1);//取第一天
                        firstDay = sdf.format(cale.getTime());
    
                        cale.set(Calendar.DAY_OF_MONTH, dd
                                .getActualMaximum(Calendar.DAY_OF_MONTH));
                        lastDay = sdf.format(cale.getTime());
    
                        keyValueForDate.setStartDate(firstDay);
                        keyValueForDate.setEndDate(lastDay);
    
                    }
                    list.add(keyValueForDate);
                    dd.add(Calendar.MONTH, 1);// 进行当前日期月份加1
    
                }
    
                if(endDay<startDay){
                    keyValueForDate = new KeyValueForDate();
    
                    cale.setTime(d2);
                    cale.set(Calendar.DAY_OF_MONTH,1);//取第一天
                    firstDay = sdf.format(cale.getTime());
    
                    keyValueForDate.setStartDate(firstDay);
                    keyValueForDate.setEndDate(sdf.format(d2));
                    list.add(keyValueForDate);
                }
            } catch (ParseException e) {
                return null;
            }
    
            return list;
        }
    
    }
    
    
    
    class KeyValueForDate{
        private String startDate;
        private String endDate;
        public String getStartDate() {
            return startDate;
        }
        public void setStartDate(String startDate) {
            this.startDate = startDate;
        }
        public String getEndDate() {
            return endDate;
        }
        public void setEndDate(String endDate) {
            this.endDate = endDate;
        }
    
    
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133

    这里写图片描述


    展开全文
  • 我在阿里工作的这段时间里,都学到了哪些东西

    万次阅读 多人点赞 2019-08-18 21:38:28
    段时间没写过原创了,想了各种理由,发现其实理由就一个,没时间。 我来阿里,已经几月了。这段时间,最大的感受就是累。我是在今年的月份加入阿里的。 当初我没有参加阿里巴巴的实习,而是选择了直接...

    1、

    有段时间没写过原创了,想了各种理由,发现其实理由就一个,没时间。

     

    我来阿里,已经几个月了。这段时间,最大的感受就是累。我是在今年的四月份加入阿里的。

     

    当初我没有参加阿里巴巴的实习,而是选择了直接进行校园招聘,这也是因为当时我对实习的部门不感兴趣,于是在校招的时候我就选择了自己感兴趣的部门,也就是现在我所在的蚂蚁金服。

     

    之前就听说过阿里的工作强度,可能会比较大,但是,当我在真正来到这家公司的时候,才发现996,并不是虚言,这倒不是说制度上规定的 996 ,而是因为,你手上的工作,是很难做完的,所以导致你不得不用加班的方式来完成,996 最终的目的只有一个,就是你要把手上的工作做完,对其他人有一个交代。

     

    刚来一个月的时候只其实我是非常不适应的,毕竟从学校到公司,整个变化是颠覆性的,虽然之前有过实习经历,但是是比较划水的,和正式工作差别还是比较大的,第一个月大抵的状态就是,每天九点多上班,晚上九点及以后下班,这是生活规律上的不适应。

     

    除此之外,在工作上也会有一些不适应,虽然前期给我的活儿都比较的零散,只要求这里修修补补,那里加点东西。这倒是其次。

     

     

    主要的原因还是因为我对业务线的研发流程不太了解,以及对大家在做的事情不太了解,这会导致我在工作上遇到很多困难。因为我会听不懂大家在说什么。所以第一个月,更多的是思考。

     

    如何去提高自己的效率,如何去融入这个公司,如何去熟悉部门的业务和技术战,自己感觉是一个比较外向的人,所以一旦有问题就会咨询,我的同事,我的师兄。

     

    阿里的师兄是一种文化。就像武侠小说里的同门师兄弟一样,师兄会带领着你去做那些工作,并且让你去熟悉整个部门的一些事情。我的师兄是一个寡言少语的人,但是技术能力非常强,也很有责任心。他总是对总是对工作要求特别高,不放过任何一个问题,不漏掉任何一行问题代码。

     

    在第一个月的时间里。我学习了很多阿里巴巴的一些中间件技术。其实这些技术。在学校复习的时候,多少也听说过一些,看过一些文章。只不过外面用的都是开源的东西,而在阿里内部,更多的是自研的产品,比如说,消息中间件,分布式事务,数据库中间件,等等等等。这些东西,在平时的学习和研发中,是经常会用到的,如果你在学校或者是在其他小公司,可能根本没有机会接触到这些东西。

     

     

    作为一个Java工程师,在这家公司的职责可不止是写代码,你需要熟悉整个研发流程,从系统设计,代码开发,测试联调,发布上线,问题排查都是你的职责,其实这很锻炼人,这也是为什么加班会这么多的原因,写代码只占你日常工作的一小部分时间,你需要花更多时间在解决各类问题上。

     

    阿里对校招生有一个培训,不同部门可能不太一样,蚂蚁的培训长达一个月,这个月应该也是我觉得成长最快,过得最快乐的一个月,其实无非就是上课,拓展和各类活动,这段时间认识了很多人,其中也有很多大牛,大家一起上课,一起做项目,同甘共苦度过一个月,这样的经历也是非常值得纪念的。

     

    培训结束后,我也开始承担更多的工作,当自己逐渐习惯这种节奏之后,才感觉自己逐渐在融入这家公司,每次搞懂一个业务问题或者技术问题都会觉得自己在成长,当肩头上承担更多责任的时候,同时也承担了更多压力,如果不能调整好自己的心态,我想在这家公司是很难待久的。

     

    可能你在其他互联网公司也会感受到相似的压力,但这就是大部分互联网公司的现状,追求效率,追求极致,我们身在其中,就必须适应环境,尊重游戏规则,马上又是新一年的校招季,去年这个时候,这个公众号才刚刚诞生,转眼一年时间,多的是更多思考,希望公众号的文章对你们有会有更多帮助

    2、

    来阿里也已经四个多月了,这段时间你学了很多东西,简单说起来,就是一个走出舒适区的过程,从一开始的新手入门,到逐渐熟悉业务和技术,再到慢慢的适应环境,胜任工作。

    总体来说,这几个月还是学到了很多东西,感觉成长的很快,但同时工作的压力也非常的大。总体来说,归纳几个点吧。

     

    第一点:就是阿里的技术。

    大家都知道阿里的java技术栈,在业内基本上是可以排第一的,这也归功于阿里的技术发展十分迅速,所以底层的技术才会如此的先进。

    阿里内部通常都会自己研发中间件,阿里也开源了一套中间件,但实际上内部又维护了好几套的中间件,蚂蚁也有自己独立的中间件体系,用于支撑蚂蚁金服里所有的业务线和技术线。

    其实简单来说,蚂蚁的这些中技术组件和阿里系的中间件、以及开源的一些组件都大同小异,只不过对于金融支付场景更加的适用,这也是我第一次接触大规模的分布式技术组件,不管是缓存、消息队列、定时任务等各种各样的组件,都会在日常的工作中使用到,所以在技术上的成长,主要还是体现在平时的日常工作中的。

     

    第二点就是:对职场的理解。

    在没有正式工作之前,我对职场的理解还停留在实习的阶段,实习相对正式工作来说,比较轻松,生活和工作的压力也没那么大,所以可能在实习阶段也比较散漫,没有特别努力认真,现在想想还真应该反思一下实习时候的状态,到了工作的时候就不一样了,你必须要胜任工作,必须要把每件事情做好。

    而且在阿里有一个比较蛋疼的地方就是你需要同时做很多事情,除了你的主要项目之外,你还需要并发去处理,很多琐碎的事情,同时你必须要主动去问主动去学习,没有人会告诉你应该怎么样才是对的,可能一开始师兄或者导师会指导你,如何熟悉这一套东西。

    但是当试用期一过,就要开始自己摸索了,首先是要尽快胜任自己的工作,其次,要尽快地适应并发的办事方式,提高自己的工作效率,第三,要学会职场中的一些规则,比如说要为要有团队精神,要有团队意识和责任心,保证项目和系统的稳定运行,关键时刻需要你的时候绝不能掉链子。

    毕竟是这么庞大的技术体系,一旦出了问题,有很多人会受到牵连。

     

    第三点:学会程序员的高效办事方式。

    说实话,在这里你必须要能够非常高效地办事,非常高效地完成工作。高效的前提是你要有一套方法论以及一套工具体系,让它们去支撑你的执行力。

    比如说你可能需要学会做笔记,学会记录项目,学会把平时常用到的一些技术进行归纳整理。

    同时,你还要学会整理平时经常用的工具,Linux、等等,你最好有一个每天的工作计划,安排好今天做哪些事情,有哪几项事情,按照什么样的顺序来做。

    阿里对员工的要求往往是综合性的,你需要有很好的编码能力和技术思维,除此之外,你要有很强的总结能力和思考能力,以及技术能力,除此之外,你还要有很强的学习能力,创新的能力。

    在阿里,没有人可以随随便便地应付工作。每个人都要精益求精,否则就有很可能会被淘汰

    3、

    在高速发展,快速迭代的互联网公司里,如何平衡自己的工作和生活。

    这对于很多互联网来人来说都是一个迫在眉睫的问题,很多人被工作压的喘不过气,难以找到这个平衡点,所以他们也无法达到自己想要的一个生活状态。

    有些人在这样的过程中逐渐迷失了自我,失去了对生活原本的追求。轻则失去斗志,逐渐沉沦,重则可能完全被工作压垮,成为了工作的奴隶。

     

    当然了,并不是对所有的互联网人来说都会有这样的压力,还是有一些少数的互联网公司可以让你追求真正的工作生活平衡,比如在google,亚马逊,微软等一系列外企,他们就有这样的特点。

    西方人更加注重生活和平衡,他们更加重视家庭生活,工作只是他们的一小部分,其实对于中国人来说,何尝又不是这样呢,但是中国的公司文化不一样,特别是互联网公司的文化,逐渐的养成了一种加班文化。

    从一开始还有一些人在抗拒,到后来慢慢形成一种传统,不正常的事情也变成了正常的事情,于是不加班反而会让人觉得奇怪,可能这是一种时代的倒退吧。

    但是,我们还是要说,既来之则安之,如果你无法习惯国内的互联网环境,那可能只有去一些比较稳定安逸的企业才能让你找到最初的工作与生活的平衡的,当然也有很多人选择出国,或者去一些外企,去达到这样的一个状态。

     

    其实我是非常羡慕这些。能够得到工作和生活平衡的人。毕竟对于他们来说。可以更好的享受生活。而不是整天为工作疲于奔命。

    当然,我也不是说国内的互联网公司的文化就一无是处,其实根本的原因,还是在于,国内互联网公司的发展速度是非常快的,他们需要不断创新,不断迭代去适应新产品新环境,新时代。

    而在国外这种压力,其实会相对比较小。所以说,每个互联网公司都希望通过让员工加班来加快效率,虽然本质上还是老板的意思,但时间一久员工自己也形成了一种认识,加班充就是电、生活和工作没办法平衡。

    特别是像 BAT 这样的企业,真的很少有人奢望工作和生活的平衡,这确实很悲哀,但是对于我们这些深陷其中的人来说,除了皆叹这个世道为何如此,还得去想想,如何去应对这样的现状。

    在阿里,我体验到了前所未有的工作压力,这是在我之前两段实习经历中都无法体验到的工作压力,996的生活都已经算是轻松的,有时候加班一多可能就是9107或者是9106,这样的一个节奏,怎么说呢?虽然确实成长很快,但是这样的节奏确实会让人喘不过气来。

    那当你面对重压时,应该如何去调整自己呢?其实能进到大厂的人来说,他们大部分都是很优秀的,他们也知道自己一路走来不容易,他们的每一段路程可能都不容易,所以进入大公司后,对于他们来说,只是又一次新的考验。可能很快他们就能习惯能适应,毕竟优秀的人身上总会有这样的一些闪光点。

    那对于我来说,优秀可能并不是特别适合我的一个词,因为我觉得我是需要不断在强化自己的,我仍然有很多不足,需要去弥补的,所以来这里我更加感到了前所未有的压力。除了工作上的责任之外,必须去了解自己的短板去弥补自己的弱势。

    而这也是在工作之外,我必须去思考的问题。所谓的生活和工作的平衡对于我来说,就是如何安排自己的时间,安排自己的生活。按照平时九点半点下班来算,我大概12点就要入睡,这两个小时是我一整天中唯一的放松时间我是如何安排的呢?

    其实最初的一个月我也没想通,我可能就每天看看电视,打打游戏也就过去了,后来发现,工作任务也多,这些时间可能不能这样随意挥霍?于是我开始利用这些时间锻炼身体,或者看看课程、写写文章。

    可能就是我每天晚上能做的一些稍微有意义的事情了。可能很多人无法理解,这样两个小时的放松时间也能叫生活吗?其实我也希望有那么多的时间去自己安排,但是现实是,你又想要熊掌又想要轻松,既想要要快速地改变自己,同时又想在舒适区里一直呆着,显然是不太现实的。

    于是我们就必须要走出去。去面对更多的挑战,去探索自己身上的可能性,于是我把这些时间用来做相对更有意义的事情。

    每当到了周末我又是另外一种状态,周末往往是更加需要规划的,这一段时间的周末我还会选择去游泳,去外面转转去跟朋友聚一聚,或者去参加一些户外活动。

    当然,如果没有的话,我会选择在家里写写文章,然后发表一些作品,或者利用这些时间充充电,然后做一些自己想做的事情。

    曾经刚入职那段时间周末还有时间打打游戏,现在基本上是没有这种时间了,只能忙里偷闲,听听听听广播看看电视剧,这对我来说就已经很满足了。

    当然,周末的时候我也希望能够有更多的时间可以去支配,比如我利用周末去整理房间,然后然后去制定下周的计划,把每到周末我也会制定一个简短的计划,比如这周末我要写几天文章,要发表多少作品么,怎么去规划公众号的接下来的发展。

    除此之外,我还要去看一下这周我的投资理财情况如何,然后可能就趁着周末可以比较晚睡觉,然后去听一些比较感兴趣的课程。所以基本上现在的我是一个满负荷运载的状态,休息的时间就是每天晚上的下班时间到睡觉的时间。

    说了这么多,要做到工作和生活平衡,我总结以下几点

    第一点:安排好自己的工作。尽量把你的工作在一周内做好一个计划,按照优先级排开,然后真的清楚自己一周内需要做哪些事情,然后能自己把控,这样你就会更加合理的规划自己的工作,避免他它们会占用你太多的时间。

    第二点:想想想清楚自己想要平衡的那部分生活是什么?真的有意义吗?等到的职场上其实你要的生活无非就是放松一下自己,或者是提高一下自己,然后放松自己,不一定要单纯的是去玩游戏,或者是看剧之类的,你也可以采取更加柔和的一些方式,比如说你可以去。运动去锻炼,然后去让自己的身体变得更好。

    第三点:当你的工作严重的侵蚀到你的生活时,要考虑清楚自己真的想要这样的生活吗,是不是放弃这份工作会更好?其实很多人都会深陷工作泥潭,然后就会丢失掉自己的生活。然后可能会慢慢的身体承受不住,或者是心理上变得非常脆弱,然后让自己整个人都处于一个不健康的状态。如果遇到这种情况,一定要找一段时间去想一下,你可能去请个年假出去玩一,看看这个世界,也许你就会放下。

    第四点:如果你的生活也会让你也会给你带来,不低于工作的压力时,你一定要学会分分分配自己的精力,可能家庭这方面你需要话费多少时间和工作,这方面必须要学会去平衡,家庭的事真的比工作的事情重要的太多了。千万不要拿工作上的事情去成为你忽略家庭责任的一个借口。

    以上四点就是我总结的,关于互联网人如何平衡自己工作和生活的建议,希望这些还不如早点离开这个工作岗位算了,希望这些内容能够帮到你们,不管如何,至少一定要让自己每天都过得开开心心的。

    个人公众号:程序员黄小斜

    微信公众号【程序员黄小斜】新生代青年聚集地,程序员成长充电站。作者黄小斜,职业是阿里程序员,身份是斜杠青年,希望和更多的程序员交朋友,一起进步和成长!专注于分享技术、面试、职场等成长干货,这一次,我们一起出发。

    关注公众号后回复“2019”领取我这两年整理的学习资料,涵盖自学编程、求职面试、算法刷题、Java技术学习、计算机基础和考研等8000G资料合集。

    技术公众号:Java技术江湖

    微信公众号【Java技术江湖】一位阿里 Java 工程师的技术小站,专注于 Java 相关技术:SSM、SpringBoot、MySQL、分布式、中间件、集群、Linux、网络、多线程,偶尔讲点Docker、ELK,同时也分享技术干货和学习经验,致力于Java全栈开发!

    关注公众号后回复“PDF”即可领取200+页的《Java工程师面试指南》强烈推荐,几乎涵盖所有Java工程师必知必会的知识点。

    展开全文
  • 亲密接触Redis-第一天

    万次阅读 多人点赞 2016-02-03 17:10:24
    Redis是一个NOSQL,NOSQL有许多种,它们分为: 列存储,如:Hbase、Cassandra这种 文档存储,如:MongoDB(首推) key-value存储,如:Berkeley DB、MemcacheDB、Redis,其中Redis最强 图存储,这块基本不用,有:...

    引言

    nosql,大规模分布式缓存遍天下,Internet的时代在中国由其走得前沿,这一切归功于我国特色的电商。因此nosql、大数据技术在中国应用的比国外还要前沿。从这一章开始我们将开始进入到真正的SOA、PAAS、SAAS、互联网的领域,因此每一篇我都会加入一小段业务的基础知识,让大家在学习技术的同时也可以了解一些业务,这边的业务不是指的business logic不是让大家去做业务人员,而是为大家带来IDEA,”没有做不到只有想不到“,阿里支付宝为什么发了。。。不是技术,而是它的IDEA。


    业务基础知识-国内国外电商比较以及为什么电商技术在中国走得这么前沿

    14年1月时在上海参加过一个MagentoCom召集的电商峰会。会上一群LAO WAI在那边大谈自己的电商经验,有LV,有ADIDAS,bla...bla...bla...听着听着,真是觉得好笑。休息时随便问一个LAO WAI一个问题:


    ”你们知道什么叫一元秒杀吗?“


    ”你们知道什么7天无理由退货吗?“


    ”你们知道什么叫0体验吗?“


    ”你们有没有双11,双12,有没有交易量过亿。。。“


    LAO WAI ”张嘴,流哈喇子,billions of transaction? billions“


    看着他这个样子,我是硬忍住后来到WC一边抽烟一边笑,笑得连手上的烟头都抖了,唉。。。。。。


    不是说国外的电商不这么干,而是经济体制决定了电商的发展道路不同,因为国外的电商是基于他们的”信任“式经济的模式下的,因此国外的电商基本都是信用卡、预先冲款、预售卡、充值卡这些,这也决定了国外没有什么1元秒杀。。。这些哄人气的东东。


    另外一点就是国外人口也少,呵呵,这算是一个理由。


    还有就是国外基本无”不是名牌“这一说,记得去法国onsite交流学习时,如果你穿的一件ADIDAS或者是NIKE或者是阿玛尼如果不是正宗名牌,是仿的话也会被警察抓住罚款,因此国外是个商品基本都有牌子。这是一种”互信“机制。


    中国的电商虽然也是走线上、线下但是它多了一个”第三方资金委托“即支付宝、易宝、微信(微信是后起之秀)这种东东,因此这样的体制决定了”先验货,后付钱“的这种游戏规则。


    加上中国人多,这下大数据、NOSQL、分布式这些技术当然成为了通向internet的重中之重了。


    进入Redis课程

    Redis是什么

    Redis是一个NOSQL,NOSQL有许多种,它们分为:

    • 列存储,如:Hbase、Cassandra这种
    • 文档存储,如:MongoDB(首推)
    • key-value存储,如:Berkeley DB、MemcacheDB、Redis,其中Redis最强
    • 图存储,这块基本不用,有:Neo4j、Versant
    • XML存储,如:Berkeley DB Xml还有XBASE,ORACLE很早已经支持这种存储方式了

    光知道这些NOSQL的名词是没有用的,关键在于要知道在哪种场景下选用哪种NOSQL才是我们真正要去掌握的。

    我们这边说Redis就拿Redis说事吧,它能干什么呢?


    Redis基础应用场景

    • web间session共享,即多个war工程共享一个session
    • 分布式缓存,因为redis为键值对,而且它提供了丰富的adapter可以支持到C、.net、java客户端,因此对于异质平台间进行数据交换起到了作用,因此它可以用作大型系统的分布式缓存,并且其setnx的锁常被用于”秒杀“,”抢红包“这种电商活动场景中。

    安装Redis

    我本来想在这儿写”Redis上的‘坑‘“,最后我还是觉得把它放到后面章节中去写吧,因为中国人的思维是先有感性再有理性的一种逆向思维,其实这点很像美国人,因此中国人在世界上是最聪明的民族之一,所以我们还是先从动手搭一个Redis的环境来说起吧,老规矩,红色加粗很重要。

    一定要使用Linux来布署Redis,请不要偷懒使用Redis 2.8.1 for windows那个版本,如果你使用了这个版本你将无法跟上这一系列教程的步伐。因为Redis为GCC+这样的东西开发出来的,它天生就是运行在LINUX/Unix环境下的,而那个windows版的Redis是一个”烟“割版,而且是一个unofficial的版本非官方授权的哈。

    先从Docker开始

    如果已经有Linux/Unix环境的同协们可以直接跳过这一章。

    我们这边要开始变态了,因为我们要真正开始踏上SOA、PAAS、互联网的脚步了。

    如果对于没有Linux/Unix环境的用户来说,我在这边推荐使用docker,即boot2docker windows版来安装,它下载后是一个这样的文件


    安装前把你的网络连接中的IPV6协议前的勾去掉

    双击它,在安装时记得选择Virtual-Box选项,因为docker本为linux/unix下之物,因此为了在windows下使用docker,boot2docker内嵌了一个virtualbox来虚拟docker的环境。
    装完后它会在你的桌面上生成一个蓝色的图标,双击它,它会打开一个绿色的字,黑色的背景像matrix电影里的那种命令行窗口,这就是Docker。

    装完后运行:
    docker@boot2docker:~$ docker run hello-world 

    看到下面这些提示


    Hello from Docker. 
    
    This message shows that your installation appears to be working correctly.
    
    To generate this message, Docker took the following steps: 
    1. The Docker client contacted the Docker daemon. 
    2. The Docker daemon pulled the “hello-world” image from the Docker Hub. 
    (Assuming it was not already locally available.) 
    3. The Docker daemon created a new container from that image which runs the 
    executable that produces the output you are currently reading. 
    4. The Docker daemon streamed that output to the Docker client, which sent it 
    to your terminal.
    
    To try something more ambitious, you can run an Ubuntu container with: 
    $ docker run -it ubuntu bash
    
    For more examples and ideas, visit: http://docs.docker.com/userguide/

    说明你的Docker安装成功了。

    在Docker中安装unix环境


    有了Docker我们就用Docker虚拟一个Ubuntu(UNIX)环境吧,在这边我们使用的是Ubuntu14。

    ubuntu14请下载这个包:戳: 下载Ubuntu14包

    下载后直接在docker下运行下面这条命令:

    cat ubuntu-14.04-x86_64.tar.gz |docker import - ubuntu:ubuntu14

    这个过程会很快,完成后查看自己的image:



    成功导入了ubuntu,这样我们就可以在docker中运行出一个自己的ubuntu了。


    docker run -i -t ubuntu:ubuntu14 /bin/bash

    以上运行后,进入了该ubuntu的bash环境。


    注:如果上述命令出错,可以使用下面这条命令:

    docker run -i -t ubuntu:ubuntu14 //bin/bash

    两个 “/” 

    如果你能看到类似于root@ubuntu14_这样的命令行界面说明你的ubuntu14也已经安装成功了,下面我们就要在这个docker->ubuntu14中安装和布署我们的Redis了,这个过程和在linux下一样。


    在ubuntu14下先安装SSHD,以便于我们使用WINSCP这样的SFTP工具来管理我们的ubuntu14中的文件系统


    在ubuntu14中安装SSHD

    第一步:

    docker run -t -i ubuntu/mk:v1 /bin/bash


    进入我们的ubuntu环境,这边的ubuntu/mk就是我本机的docker中ubuntu14 container(容器)的名字,如果按照上面的延续此处可以替换成ubuntu:ubuntu14这个名字吧。


    第二步:

    升级一下你的apt-get,它就是一个命令行IE下载工具,如果你不update,那么你apt-get的源、内核都为旧的,因此为了升级apt-get请键入下面的命令

    apt-get update


    这个过程很快(依赖于你的网络环境)


    第三步:


    下载和安装openssh组件

    apt-get install openssh-server openssh-client


    第四步:


    修改你的root密码

    passwd


    键入两次你的root密码,我这边都为6个小写的a


    第五步:

    退出容器,并保存以上修改,如果docker在退出后你接着退出docker环境或者是关机那么刚才的4步全部不生效,你一定要commit它才能生效,为此:

    • 你先要知道你刚才用docker run命令运行的ubuntu14的容器的ID,你可以使用
      docker ps -a
      来查到你latest的一次容器的ID,它是一组16进制一样的编码如:1edfb9aabde8890,有了这个container id我们就可以commit我们刚才装的openssh的环境了
    • commit刚才在容器中所做的修改
      docker commit 1edfb9aabde8890 ubuntu:ssh

    第六步:

    运行带有openssh的ubuntu14以便于我们使用winscp这样的SFTP工具连入我们的ubuntu14中去,依次输入下面的命令:

    docker kill $(docker ps -q)


    杀掉正在运行的所有的container的进程

    docker rm $(docker ps -a -q)


    删除所有在进程中的容器,以上2步又被称为docker大扫除


    Docker是这样的机制的,它可以开启多个容器,每个容器带着一堆的image(镜像),要删一个镜像必须先停止这个镜像所在的容器,再把这个镜像删除,因此我们使用上面这两条命令对于Docker来一个大扫除。


    接着我们先查一下我们目前手头有的镜像

    docker images
    你会看到一个images列表,里面有我们的ubuntu:14,有我们的ubuntu:ssh也有一个hello-world,我们把ubuntu:14这个镜像删了吧(为了保持干净哈)


    每个image也它自己的id,即image id,因此你用docker images命令查到该镜像的id后可以使用:


    docker rmi imageid
    这条命令把一个不用的镜像给删了。


    接下去我们要启动我们的ubuntu14:ssh了,可以使用下面这条命令:

    docker -d -p 122:22 ubuntu:ssh //usr/sbin/sshd -D

    这条命令的意思为:

    • -d即把我们的image启动在后台进程,它将会是一个daemon进程,而不会像刚才我们使用-t一样,一旦exit后该image进程也自动退出了
    • -p为端口映射,什么意思呢,这边要说一下docker的端口映射问题。我们知道docker安装后它会利用virtualbox中的vhost only的nat机制来建立一个虚拟的IP
    可以打开我们的virtualbox中在菜单”全局->设定->网络”中进行查找


    所以我们可以知道一旦boot2docker环境运行后它的地址为192.168.56.*这个段,一般为192.168.56.101这个地址,你可以在boot2docker启动后直接使用winscp边入这个docker环境。

    地址:192.168.56.101
    端口:22
    用户名:docker
    密码:tcuser

    以上为默认值,具体地址按照你的virtualbox中在boot2docker安装时自动给出的设置来做参考。

    而,
    我们在这个docker中安装了一个ubuntu14:ssh的image,然后用后台进程的方式打开了这个ubuntu14:ssh,因此它自己也有一个IP(可能是172也可能是169段),具体不得而知,一般来说它是每次启动镜像后自己变换的(可以使用动态网络域名绑定docker中镜像的ip来达到域名不变的目的-集群环境下有用)。

    我们都知道ssh是以端口22来进行TCP连接的,因此我们把ubuntu14的IP上的22端口映射到了我们的docker主机192.168.56.101上的122端口。

    • 参数//usr/sbin/sshd -D代表该镜像启动会的entrypoint即启动后再启动一个什么命令,在最后的-D(大写的D)告诉docker这是一个启动文件
    于是,一旦该命令发出后,显示image启动的提示后(启动后你会得到一个image id)你就可以直接打开你的winscp使用:


    地址:192.168.56.101
    端口:122 (此处是122,不是22,因为我们把image的22端口映射到了192.168.56.101-docker主机上的122端口了)
    用户名:root
    密码:aaaaaa

    即可以连入我们的ubuntu14环境了,如果此时你安装了putty还可以使用putty+winscp直接进入ubuntu14的命令行环境中去,于是你就有ubuntu14的试验环境了。





    在ubuntu14下安装redis

    网上很多在ubuntu14下安装redis的教程都不对的,大家看了要上当的,原因在于如下,请各位看完:

    1. 网上的redis环境搭建直接使用的是apt-get update完后用wget https://github.com/ijonas/dotfiles/raw/master/etc/init.d/redis-server 这样的方式来安装的,这样装固然方便,可是也因为方便所以取到的redis不是最新的redis版本,一般为2.8.x版或者是redis3.0.rc,这依赖于你的unit/linux所连接的wget库
    2. redis为c写成,它的2.4-2.8版都为不稳定版或者是缺少功能或者是有bug,而这些bug在你如果真正使用redis作为网站生产环境时将会因为这些bug而无法面对峰涌而来的巨大并发,因此当有这样的redis运行了一段时间后你的生产环境会面临着巨大的压力
    3. 还是redis不够新不够稳定的原因,由于在redis3前redis还不支持集群、主备高可用方案的功能,因此不得不依靠于繁杂的打补丁式的如:linux/unix-keepalive或者是haproxy这种系统级层面然后写一堆的复杂脚本去维护你的redis集群,还要用外部手段(Linux/Unix Shell脚本)去维护多个redis节点间的缓存数据同步。。。这这这。。。不复合我们的网站扩容、增量、运维和面对巨大用户(万级并发-最高支持百万用户如:新浪微博、微信)的场景
    因此,我在这边推荐大家使用下面我将要使用的“下载源码包结合你本机的Linux/Unix内核进行实时编译”的安装过程。

    第一步:下载redis目前最稳定版本也是功能最完善,集群支持最好并加入了sentinel(哨兵-高可用)功能的redis3.0.7版即redis-stable版,为此我们需要获取redis-stable版

    就是用的这个redis-stable.tar.gz包,这是我在写博客时目前最新最稳定版本,修复了大量的BUG和完善了功能。

    第二步:

    下载后我们把该包上传到我们的docker中的ubuntu14中,我们把它放在/opt目录下

    然后我们使用tar -zxvf redis-stable.tar.gz对它进行解压


    解压后它就会生成一个redis-stable目录,进入该目录 cd redis-stable


    别急,我们先一会编译和安装它


    第三步:编译安装redis

    我们先输入gcc -v 这个命令来查看我们的gcc版本,如果它低于4.2以下那么你在编译redis3.0.7时一定会碰到大量的出错信息,如前面所述,redis为gcc写成,最新的redis需要gcc4.2-5这个版本才能进行编译,而一般去年或者之前装的linux/unix 的 gcc都为4.0以下或者甚至是3.x版。

    升级GCC先

    apt-get install build-essential


    因此apt-get update显得很重要,要不然你获取的gcc也将不是最新的版本,目前我的gcc为5.3.1为这周刚做的升级。


    升级后我们开始编译redis3.0.7了,为此我们需要在redis-stable目录下


    键入如下命令:

    make PREFIX=/usr/local/redis1 install

    我们告知我们的GCC把redis-stable编译并同时安装在/usr/local/redis1目录下


    这个过程很快,可能只有10秒钟时间(依据你的机器来说,建议使用>=8gb, 4核CPU的PC机),然后我们就可以看到everything ok了。我们进入/usr/local/redis1就可以看到我们刚才安装的redis3.0.7稳定版了。


    我们进入我们的redis目录 cd /usr/local/redis1/bin


    在此目录下我们即可以运行我们的redis server了,不过请别急,在启动前我们需要对redis进行一些配置。


    我的博客面对的是“全栈式”工程师的,架构师只是成为全栈式工程师中的一个起点,如果你不会搭环境那么你就不能接触到最新的技术,因此这就是许多程序员工作了近5年,7年结果发觉也只会一个SSH的主要原因。

    Redis3配置要领

    使用winscp通过122连入docker下的ubuntu14,进行redis的配置。

    我们需要编辑的文件为/usr/local/redis1/bin/redis.conf这个文件

    daemonize yes
    
    # When running daemonized, Redis writes a pid file in /var/run/redis.pid by
    # default. You can specify a custom pid file location here.
    pidfile "/var/run/redis/redis1.pid"
    
    # Accept connections on the specified port, default is 6379.
    # If port 0 is specified Redis will not listen on a TCP socket.
    port 7001
    
    我们把:

    1. daemonize设为yes,使得redis以后台进程的方式来运行,你可以认为为“server”模式,如果redis以server模式运行的话它会生成一个pid文件 ,因此我们把它的路径放在/var/run/redis目录中,并命名它为redis1.pid文件 ,为此你需要在/var/run目录下建立redis这个目录
    2. 端口号我们把它设为7001,这样好辩识,因为将来我们会进一步做redis集群,所以我们的redis都为redis1, redis2, redis3那么我们的端口号也为7001, 7002, 7003。。。这样来延续。那么很多同协这时要问了,“为什么我们不把它命名成master, slave1, slave2这样的名字呢?”,理由很简单,无论是现在的hadoop还是zookeeper它们的集群是跨机房的,多个master间也有MASTER-SLAVE模式互为备份,因为一些大型网站不仅仅只有一个IDC机房,它们一般都会有2个,3个IDC机房,或者是在同一个IDC机房中有“跨机柜”的布署来形成超大规模集群,就和ALI的TAOBAO网一样,它在北美都有机房,因此当你需要在LOCAL NATIVE建一个IDC机房,在北美再做一个机房,你不要想把一个MASTER设在中国,SLAVE设到美国去,而是多地甚至是多机柜都有MASTER,一旦一个MASTER宕机了,这种集群会通过一个叫“选举策略”选出一个节点把这个节点作为当前“群”的MASTER,因此我们的命名才会是redis1, redis2, redis3...这样来命名的。


    此处把原来的:
    save 900 1
    save 300 10
    save 60 10000
    中的300 10 和60 10000注释掉。这边代表的是:

    redis以每900秒写一次、300秒写10次,60秒内写1万次这样的策略把缓存放入一个叫.rdb的磁盘文件中,这点和ehcache或者是memcache很像,以便于redis在重启时可以从本地持久化文件中找出关机前的数据记录。

    如果按照默认的话,此三个策略会轮流起效,在大并发环境中,这样的写策略将会对我们的性能造成巨大的影响,因此我们这边只保留900秒写1次这条策略,这边有人会问,如果你这样会有数据丢失怎么办。。。别急,这个问题我们后面会解答,这涉及到redis的“正确”使用,如果它只是一个缓存,我相信5分钟内缓存的丢失此时程序直接访问数据库也不会有太大问题,又要保证数据完整性又要保证性能这本身是一个矛与盾的问题,除非你钱多了烧那我会给出你一个烧钱的配置策略,连新浪都不会这么烧钱,呵呵。

    • dbfilename,此处我们维持redis原有的缓存磁盘文件的原名
    • dir "/usr/local/redis1/data"为rdb文件所在的目录
    这边大家要注意的是一个是只能写文件名,另一个地方只能写目录名。
    为此我们需要在/usr/local/redis1下建立 data目录。



    把此处的appendonly设为no,这样我们就关闭了Redis的AOF功能。

    • AOF 持久化记录服务器执行的所有写操作命令,并在服务器启动时,通过重新执行这些命令来还原数据集。AOF是redis在集群或者是高可用环境下的一个同步策略,它会不断的以APPEND的模式把redis的缓存中的数据从一个节点写给另一个节点,它对于数据的完整性保证是要高于rdb模式的。
    • RDB 是一个非常紧凑(compact)的文件,它保存了 Redis 在某个时间点上的数据集。 这种文件非常适合用于进行备份: 比如说,你可以在最近的 24 小时内,每小时备份一次 RDB 文件,并且在每个月的每一天,也备份一个 RDB 文件。 这样的话,即使遇上问题,也可以随时将数据集还原到不同的版本。RDB 非常适用于灾难恢复(disaster recovery):它只有一个文件,并且内容都非常紧凑,可以(在加密后)将它传送到别的数据中心如阿里的mysql异地机房间使用FTP传binlog的做法。
    按照官方的说法,启用AOF功能,可以在redis高可用环境中如果发生了故障客户的数据不会有高于2秒内的历史数据丢失,它换来的代价为高昂的I/O开销,有些开发者为了追求缓存中的数据100%的正确有时会碰到因为redis在AOF频繁刷新时整个环境如死机一的情况,并且你会看到恶梦一般的”Asynchronous AOF fsync is taking too long “警告信息,这是因为redis它是单线程的,它在进行I/O操作时会阻塞住所有的操作,包括登录。。。这个很可怕,不过这个BUG/ISSUE已经在最新redis中进行了优化,它启用了另一根进程来进行AOF刷新,包括优化了RDB持久化功能,这也是为什么我让大家一定一定要用最新最稳定版的redis的原因

    一般默认情况下redis内的rdb和AOF功能同为开启,

    如果RDB的数据不实时,同时使用两者时服务器重启也只会找AOF文件。

    因为RDB文件只用作后备用途,建议只在Slave上持久化RDB文件,而且只要15分钟备份一次就够了,所以我只保留save 900 1这条规则。


    如果Enalbe AOF:

    • 好处是在最恶劣情况下也只会丢失不超过两秒数据,启动脚本较简单只load自己的AOF文件就可以了。
    • 代价一是带来了持续的IO,二是AOF rewrite的最后将rewrite过程中产生的新数据写到新文件造成的阻塞几乎是不可避免的。只要硬盘许可,应该尽量减少AOF rewrite的频率,AOF重写的基础大小默认值64M太小了,可以设到5G以上。默认超过原大小100%大小时重写,这边可以设定一个适当的数值。


    如果不Enable AOF ,仅靠Master-Slave Replication 实现高可用性也可以。能省掉极大的IO也减少了rewrite时带来的系统波动。代价是如果Master/Slave同时倒掉(那你的网站基本也就歇了),会丢失十几分钟的数据,启动脚本也要比较两个Master/Slave中的RDB文件,载入较新的那个。新浪微博就选用了这种架构。



    最后我们不要忘了设一个redis的log文件,在此我们把它设到了/var/log/redis目录,为此我们需要在/var/log目录下建立一个redis目录。

    好了,保存后我们来启动我们的redis吧。

    我们使用以下这条命令来启动我们的redis server。



    然后我们在我们的windows机上装一个windows版的redis 2.8.1 for windows(只用它来作为redis的client端)

    然后我们在windows环境下使用:

    redis-cli -p 7001 -h 192.168.56.101

    咦,没反映,连不上,哈哈。。。。。。

    那是肯定连不上的,因为:

    1. 我们刚才在用docker启动ubuntu14时使用docker -d -p 122:22 ubuntu:ssh //usr/sbin/sshd -D来启动的,这边我们并未把redis服务的7001端口映射到192.168.56.101这台docker主机上,怎么可以通过windows主机(可能windows的ip为169.188.xx.xx)来访问docker内的进程服务呢?对吧,为此我们:先把刚才做了这么多的更改docker commit成一个新的image如:redis:basic吧。
    2. 然后我们对docker进行一次大扫除,然后我们启动redis:basic这个image并使用以下命令:
    docker -d -p 122:22 -p 7001:7001 redis:basic //usr/sbin/sshd -D

    看,此处我们可以使用多个-p来作docker内容器的多端口映射策略(它其实使用的就是iptables命令)。

    好了,用putty连入这个image的进程并启动redis服务,然后我们拿windows中的redis-cli命令来连。


    如果在linux环境下还是没有连通(可能的哦),那是因为你没有禁用linux下的防火墙,我们可以使用iptables -F来禁用linux的防火墙或者使用:


    vi /etc/selinux/config

    然后把

    SELINUX=enforcing     这句用”#“注释掉
    增加一句: SELINUX=disabled  #增加

    这样每次启动后linux都不会有iptables的困扰了(这是在本机环境下这么干哦,如果你是生产环境请自行加iptables策略以允许redis服务端口可以被访问)。


    看到下面这个PONG即代表你的redis服务已经在网络环境中起效了。



    下面我们要开始使用JAVA客户端来连我们的Redis Service了。


    使用Spring Data + JEDIS来连接Redis Service

    Spring+Session+Redis

    pom.xml

    在此我们需要使用spring data和jedis,下面给出相关的maven配置

    	<dependencies>
    		<!-- poi start -->
    		<dependency>
    			<groupId>org.apache.poi</groupId>
    			<artifactId>poi</artifactId>
    			<version>${poi_version}</version>
    		</dependency>
    		<dependency>
    			<groupId>org.apache.poi</groupId>
    			<artifactId>poi-ooxml-schemas</artifactId>
    			<version>${poi_version}</version>
    		</dependency>
    		<dependency>
    			<groupId>org.apache.poi</groupId>
    			<artifactId>poi-scratchpad</artifactId>
    			<version>${poi_version}</version>
    		</dependency>
    		<dependency>
    			<groupId>org.apache.poi</groupId>
    			<artifactId>poi-ooxml</artifactId>
    			<version>${poi_version}</version>
    		</dependency>
    		<!-- poi end -->
    		<!-- active mq start -->
    		<dependency>
    			<groupId>org.apache.activemq</groupId>
    			<artifactId>activemq-all</artifactId>
    			<version>5.8.0</version>
    		</dependency>
    
    		<dependency>
    			<groupId>org.apache.activemq</groupId>
    			<artifactId>activemq-pool</artifactId>
    			<version>${activemq_version}</version>
    		</dependency>
    
    		<dependency>
    			<groupId>org.apache.xbean</groupId>
    			<artifactId>xbean-spring</artifactId>
    			<version>3.16</version>
    		</dependency>
    		<!-- active mq end -->
    
    		<!-- servlet start -->
    		<dependency>
    			<groupId>javax.servlet</groupId>
    			<artifactId>servlet-api</artifactId>
    			<version>${javax.servlet-api.version}</version>
    			<scope>provided</scope>
    		</dependency>
    		<dependency>
    			<groupId>javax.servlet.jsp</groupId>
    			<artifactId>jsp-api</artifactId>
    			<version>2.1</version>
    			<scope>provided</scope>
    		</dependency>
    		<dependency>
    			<groupId>javax.servlet</groupId>
    			<artifactId>jstl</artifactId>
    			<version>1.2</version>
    		</dependency>
    		<!-- servlet end -->
    
    		<!-- redis start -->
    		<dependency>
    			<groupId>redis.clients</groupId>
    			<artifactId>jedis</artifactId>
    			<version>2.7.2</version>
    		</dependency>
    		<dependency>
    			<groupId>org.redisson</groupId>
    			<artifactId>redisson</artifactId>
    			<version>1.0.2</version>
    		</dependency>
    		<!-- redis end -->
    		<dependency>
    			<groupId>org.slf4j</groupId>
    			<artifactId>jcl-over-slf4j</artifactId>
    			<version>${slf4j.version}</version>
    		</dependency>
    		<dependency>
    			<groupId>org.slf4j</groupId>
    			<artifactId>slf4j-log4j12</artifactId>
    			<version>${slf4j.version}</version>
    		</dependency>
    
    		<!-- spring conf start -->
    		<dependency>
    			<groupId>org.springframework.data</groupId>
    			<artifactId>spring-data-redis</artifactId>
    			<version>1.6.2.RELEASE</version>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework</groupId>
    			<artifactId>spring-webmvc</artifactId>
    			<version>${spring.version}</version>
    			<exclusions>
    				<exclusion>
    					<groupId>commons-logging</groupId>
    					<artifactId>commons-logging</artifactId>
    				</exclusion>
    			</exclusions>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework</groupId>
    			<artifactId>spring-tx</artifactId>
    			<version>${spring.version}</version>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework</groupId>
    			<artifactId>spring-aop</artifactId>
    			<version>${spring.version}</version>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework</groupId>
    			<artifactId>spring-context-support</artifactId>
    			<version>${spring.version}</version>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework.data</groupId>
    			<artifactId>spring-data-redis</artifactId>
    			<version>1.6.2.RELEASE</version>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework</groupId>
    			<artifactId>spring-orm</artifactId>
    			<version>${spring.version}</version>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework</groupId>
    			<artifactId>spring-jms</artifactId>
    			<version>${spring.version}</version>
    		</dependency>
    
    		<dependency>
    			<groupId>org.springframework.session</groupId>
    			<artifactId>spring-session</artifactId>
    			<version>${spring.session.version}</version>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework</groupId>
    			<artifactId>spring-core</artifactId>
    			<version>${spring.version}</version>
    		</dependency>
    		<!-- spring conf end -->
    	</dependencies>


    redis-config.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
    	xmlns:context="http://www.springframework.org/schema/context"
    	xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
    	xmlns:aop="http://www.springframework.org/schema/aop"
    	xsi:schemaLocation="  
                http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd  
                http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    
    	<context:property-placeholder location="classpath:/spring/redis.properties" />
    	<context:component-scan base-package="org.sky.redis">
    	</context:component-scan>
    
    	<bean id="jedisConnectionFactory"
    		class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
    		<property name="hostName" value="${redis.host.ip}" />
    		<property name="port" value="${redis.host.port}" />
    		<property name="poolConfig" ref="jedisPoolConfig" />
    	</bean>
    
    	<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
    		<property name="maxTotal" value="${redis.maxTotal}" />
    		<property name="maxIdle" value="${redis.maxIdle}" />
    		<property name="maxWaitMillis" value="${redis.maxWait}" />
    		<property name="testOnBorrow" value="${redis.testOnBorrow}" />
    		<property name="testOnReturn" value="${redis.testOnReturn}" />
    	</bean>
    	<bean id="redisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate">
    		<property name="connectionFactory" ref="jedisConnectionFactory" />
    	</bean>
    
    	<!--将session放入redis -->
    	<bean id="redisHttpSessionConfiguration"
    		class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration">
    		<property name="maxInactiveIntervalInSeconds" value="1800" />
    	</bean>
    	<bean id="customExceptionHandler" class="sample.MyHandlerExceptionResolver" />
    </beans> 


    redis.properties

    redis.host.ip=192.168.0.101
    redis.host.port=6379
      
    
    redis.maxTotal=1000  
    redis.maxIdle=100
    redis.maxWait=2000
    redis.testOnBorrow=false
    redis.testOnReturn=true
    


    web.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
    	<!-- - Location of the XML file that defines the root application context 
    		- Applied by ContextLoaderListener. -->
    	<!-- tag::context-param[] -->
    	<context-param>
    		<param-name>contextConfigLocation</param-name>
    		<param-value>
    			classpath:/spring/redis-conf.xml
    		</param-value>
    	</context-param>
    	<!-- end::context-param[] -->
    
    	<!-- tag::springSessionRepositoryFilter[] -->
    	<filter>
    		<filter-name>springSessionRepositoryFilter</filter-name>
    		<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    	</filter>
    	<filter-mapping>
    		<filter-name>springSessionRepositoryFilter</filter-name>
    		<url-pattern>/*</url-pattern>
    	</filter-mapping>
    	<session-config>
    		<session-timeout>30</session-timeout>
    	</session-config>
    	<!-- end::springSessionRepositoryFilter[] -->
    	<filter>
    		<filter-name>encodingFilter</filter-name>
    		<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    		<init-param>
    			<param-name>encoding</param-name>
    			<param-value>UTF-8</param-value>
    		</init-param>
    		<init-param>
    			<param-name>forceEncoding</param-name>
    			<param-value>true</param-value>
    		</init-param>
    	</filter>
    
    	<filter-mapping>
    		<filter-name>encodingFilter</filter-name>
    		<url-pattern>/*</url-pattern>
    	</filter-mapping>
    
    	<servlet>
    		<servlet-name>dispatcher</servlet-name>
    		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    		<init-param>
    			<param-name>contextConfigLocation</param-name>
    			<param-value>classpath:/spring/spring-mvc.xml</param-value>
    		</init-param>
    		<load-on-startup>1</load-on-startup>
    	</servlet>
    	<servlet-mapping>
    		<servlet-name>dispatcher</servlet-name>
    		<url-pattern>/</url-pattern>
    	</servlet-mapping>
    
    	<!-- - Loads the root application context of this web app at startup. - 
    		The application context is then available via - WebApplicationContextUtils.getWebApplicationContext(servletContext). -->
    	<!-- tag::listeners[] -->
    	<listener>
    		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    	</listener>
    	<!-- end::listeners[] -->
    
    	<servlet>
    		<servlet-name>sessionServlet</servlet-name>
    		<servlet-class>sample.SessionServlet</servlet-class>
    	</servlet>
    
    	<servlet-mapping>
    		<servlet-name>sessionServlet</servlet-name>
    		<url-pattern>/servlet/session</url-pattern>
    	</servlet-mapping>
    
    	<welcome-file-list>
    		<welcome-file>index.jsp</welcome-file>
    	</welcome-file-list>
    
    </web-app>

    这边主要是一个:

            <filter>
    		<filter-name>springSessionRepositoryFilter</filter-name>
    		<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    	</filter>
    	<filter-mapping>
    		<filter-name>springSessionRepositoryFilter</filter-name>
    		<url-pattern>/*</url-pattern>
    	</filter-mapping>
    	<session-config>
    		<session-timeout>30</session-timeout>
    	</session-config>
    这个filter一定要写在一切filter之前


    SessionController

    package sample;
    
    import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpSession;
    
    /**
     * Created by mk on 15/1/7.
     */
    @Controller
    @EnableRedisHttpSession
    public class SessionController {
    	@RequestMapping("/mySession")
    	public String index(final Model model, final HttpServletRequest request) {
    		if (request.getSession().getAttribute("testSession") == null) {
    			System.out.println("session is null");
    			request.getSession().setAttribute("testSession", "yeah");
    		} else {
    			System.out.println("not null");
    		}
    		return "showSession";
    	}
    
    }
    

    showSession.jsp文件

    <%@ page language="java" contentType="text/html; charset=utf-8"
        pageEncoding="utf-8"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>showSession</title>
    </head>
    <body>
    <%
    	String sessionValue=(String)session.getAttribute("testSession");
    %>
    
    <h1>Session Value From Servlet is: <%=sessionValue%></h1>
    </body>
    </html>

    测试

    保证我们的redise-server是启动的,然后我们启动起这个web工程后使用:

    http://localhost:8080/webpoc/mySession访问一下这个controller

    此时我们使用redis客户端工具连入查看spring session是否已经进入到了redis中去。

    在redis客户端工具连入后我们可以在redis console中使用keys *来查看存入的key,LOOK,spring的session存入了redis中去了。


    再来看我们的eclipse后台,由于我们是第一次访问这个controller,因此这个session为空,因此它显示如下:


    我们在IE中再次访问该controller


    由于之前的session已经存在于redis了,因此当用户在1800秒(30分钟)内再次访问controller,它会从session中获取该session的key testSession的值,因此eclipse后台打印为not null。

    SpringRedisTemplate + Redis

    讲过了spring session+redis我们来讲使用spring data框架提供的redisTemplate来访问redis service吧。说实话,spring这个东西真强,什么都可以集成,cassandra, jms, jdbc...jpa...bla...bla...bla...Spring集成Barack Hussein Obama? LOL :)


    pom.xml

    不用列了,上面有了

    redis-conf.xml

    不用列了,上面有了

    web.xml

    也不用列了,上面也有了

    SentinelController.java

    我们就先用这个名字吧,后面我们会用它来做我们的redis sentinel(哨兵)的高可用(HA)集群测试

    package sample;
    
    import java.util.HashMap;
    import java.util.Map;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    import org.springframework.data.redis.core.BoundHashOperations;
    import org.springframework.data.redis.core.StringRedisTemplate;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    import redis.clients.jedis.Jedis;
    import redis.clients.jedis.JedisSentinelPool;
    import util.CountCreater;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpSession;
    
    /**
     * Created by xin on 15/1/7.
     */
    @Controller
    public class SentinelController {
    
    	@Autowired
    	private StringRedisTemplate redisTemplate;
    
    	@RequestMapping("/sentinelTest")
    	public String sentinelTest(final Model model,
    			final HttpServletRequest request, final String action) {
    		return "sentinelTest";
    	}
    
    	@ExceptionHandler(value = { java.lang.Exception.class })
    	@RequestMapping("/setValueToRedis")
    	public String setValueToRedis(final Model model,
    			final HttpServletRequest request, final String action)
    			throws Exception {
    		CountCreater.setCount();
    		String key = String.valueOf(CountCreater.getCount());
    		Map mapValue = new HashMap();
    		for (int i = 0; i < 1000; i++) {
    			mapValue.put(String.valueOf(i), String.valueOf(i));
    		}
    		try {
    			BoundHashOperations<String, String, String> boundHashOperations = redisTemplate
    					.boundHashOps(key);
    			boundHashOperations.putAll(mapValue);
    			System.out.println("put key into redis");
    		} catch (Exception e) {
    			e.printStackTrace();
    			throw new Exception(e);
    		}
    		
    		return "sentinelTest";
    	}
    
    
    }
    

    打开IE,输入:http://localhost:8080/webpoc/setValueToRedis

    观察我们的后台


    然后使用redis client连入后进行查看


    看。。。这个值key=1的,就是我们通过spring的redisTemplate存入进去的值,即使用下面这段代码进行存入的值:

     for (int i = 0; i < 1000; i++) {
    	mapValue.put(String.valueOf(i), String.valueOf(i));
    }
    try {
    	BoundHashOperations<String, String, String> boundHashOperations = redisTemplate.boundHashOps(key);
    	boundHashOperations.putAll(mapValue);


    如何你要存入一个简单的如key=test value=hello,你可以这样使用你的redisTemplate

    redisTemplate.execute(new RedisCallback<Object>() {
    
    			@Override
    			public Object doInRedis(RedisConnection connection)
    					throws DataAccessException {
    				connection.set(
    						redisTemplate.getStringSerializer().serialize(
    								"test"), redisTemplate
    								.getStringSerializer()
    								.serialize("hello"));
    				return null;
    			}
    });


    是不是很方便的哈?结束第一天的教程,明天开始搭建redis集群。



    展开全文
  • 向AI转型的程序员都关注了这号????????????大数据挖掘DT机器学习 公众号:datayx本博客分享新人第次参加天池比赛的实况记录,比较完整地给出了数据预处理,缺失值补全,...
  • 写在冬日的第一天--一女程序员第六年工作总结

    万次阅读 热门讨论 2010-11-07 02:54:00
    工作这些年,年年雷打不动一篇总结让初初参加工作的这一天刻在我的脑海中。到现在我已经记不得恋爱纪念日了,却依然知道在冬天到来的第一天敲下过去一年工作的点点滴滴。   似乎在每总结开篇都会说,我...
  • 伏枥突然觉得奇怪,为何伍定轩会突然提出这问题。    “你看我的仙人掌。”伍定轩指了指摆在电脑旁边的盆仙人掌。当初伍定轩决定买这小盆仙人掌的时候,也是从网上听人说,它可以防辐射。    伍定轩...
  • 用5字段代表5不同的时间单位(中间用空格隔开): 分 时 日 月 星期几 0 2 * * * 表示每天凌晨2点 */10 * * * * 每隔10分钟次 45 10 * * 1-5 每星期的星期到星期五的10:45分执行 · M-N 指定范围值 ·...
  • 之前看了许许多多保研经验帖,如今我也写下这篇文章,希望帮助到各位学弟学妹们。 曾经的我是想出国的,但是有位学长(真的很...一个是夏令营情况,一个是九推的情况。 夏令营一般5月就要关注并报名和投材料了,...
  • 这篇指引提供了一个简单的ext js介绍,我们会从讨论建立一个简单的hello world例子开始我们的体验。我们会接着讲解在extjs中代码是怎样的结构,这指导同样也会包括一些其他可以使用的资源的链接,所以,你应该尽...
  • ![转换前](https://img-ask.csdn.net/upload/201509/25/1443171467_472728.png) ![转换后](https://img-ask.csdn.net/upload/201509/25/1443171635_685550.png)...我不想用case when 因为现在我写的sql已经很长了。。。
  • 制作一个App的完整流程是哪些

    万次阅读 多人点赞 2018-08-10 22:15:20
    一般移动APP开发都离不开UI设计师、前端开发、后端开发、测试专员、产品经理等,由于他们的工作性质都不一样,我们且先把APP软件开发项目分为阶段:  、功能需求阶段  1.功能需求讨论:前期需要产品经理跟...
  • 产品流程规划的8阶段

    万次阅读 2013-06-03 21:50:48
    很多公司都希望将自己的产品流程化,正规化,希望按照一定的流程走下去,想的是哪哪个职位出现空缺了,直接找合适的人可以顶替。同时也为以后的产品工作或项目进程都提供一个模版。特别是对于中小型公
  • 一代、二代、三代测序技术原理与比较

    万次阅读 多人点赞 2017-11-10 14:08:02
    从1977年第代DNA测序技术(Sanger法)1,发展至今三十多年时间,测序技术已取得了相当大的发展,从第代到第三代乃至第四代,测序读长从长到短...在这里我主要对当前的测序技术以及它们的测序原理做一个简单的小结。
  • 你可能第次见到这么长的总结文,有点硬核,耐心阅读
  • 3.1.3时间 用户可以给某个键设置生存时间,过期时间一个UNIX时间戳,到时间自动删除这键。 redisdb结构的expires字典保存了所有的键的过期时间,我们称这字典为过期字典。 3.1.4三种过期键删除策略 1)定时...
  • 世界上人真的分三六九等,你信吗?

    万次阅读 多人点赞 2020-02-04 22:16:21
    一时间,勾起了我深深的回忆。 以前在厂里打过两次工,做过家教,干过辅导班,做过中介。零下几度的晚上,贴过广告,满脸、满手地长冻疮。 再回首那岁月,虽然苦,但让我学会了坚持和忍耐。让我明白了,在这...
  • 61  让天平失去平衡,并不需要多大的重量,只需要一个轻微的小物体,就足以让优势倾向于另一方。对于此时处于矛盾中的伏枥来说,也... 这还要从前一段时间说起,也就是武总找伏枥聊天后的第三。和往常一样,
  • 是由一个或者多区组成的。不要看是Oracle数据库中一个不起眼的角色,其实,在其中,仍然隐藏着许多不为人知的管理技巧。若数据库管理员能够掌握这些内容,或许,其工作会变得轻松许多。  技巧:对大表执行...
  • 科普文章-另一个视角解读计算机编码(修订版)

    万次阅读 多人点赞 2017-06-17 17:59:55
    我不知道本文该作为原创发布还是作为转载发布,因为本文是《另一个视角解读计算机编码-补码编码》的“排版后的版本”,内容几乎没有变,除了...为什么要整理这篇文章时间过得太快,在我写下《另一个视角解读计算机编
  • 软件开发过程包括哪几阶段

    千次阅读 2013-09-23 22:53:41
    软件开发过程包括哪几阶段 Boehm:运用现代科学技术知识来设计并构造计算机程序及为开发、运行和维护这些程序所必需的相关文件资料。 IEEE:软件工程是开发、运行、维护和修复软件的系统方法。 ...
  • 软件工程分哪几阶段

    千次阅读 2007-04-23 14:27:00
    软件生存周期每阶段的...”如果不知道问题是什么就试图解决这问题,显然是盲目的,只会白白浪费时间和金钱,最终得出的结果很可能是毫无意义的。尽管确切地定义问题的必要性是十分明显的,但是在实践中它却可能是
  •  之前LZ写过篇《回答阿里社招面试如何准备,顺便谈谈对于Java程序猿学习当中各个阶段的建议》,那篇文章LZ主要介绍了如何应对社招面试,以及如何进行Java学习。  文章的反响还不错,不少猿友都感叹,“如果早...
  •  本以为英汉字典的程序已经没有什么大问题了,没想到今天伏枥想查一个单词,却发现事情根本就不是自己所料想的那么顺利:单词的查找速度太慢!这就奇怪了,之前为什么没有发现呢?说起来也让人啼笑皆非。之前之...
  • 在扩容时,将其中一个dictht上的键值对rehash到另一个dictht上面,完成之后释放空间并交换两dictht的角色。 typedef struct dict { dictType *type; void *privdata; dictht ht[2]; long rehashidx; /* rehashing ...
  • Python大数据分析系列博客,包括网络爬虫、可视化分析、GIS地图显示、情感分析...这篇文章将抓取微博话题及评论信息,采用SnowNLP进行简单的情感分析及文本挖掘,包括随时间的情感分布。希望这篇基础性文章对您有所帮助
  • 设备上的应用程序倒是五花八门,因为时间比较短,小黑弄了主界面,周波改了下播放器,其它的用的都是telechips的demo程序。这玩意看就是拼凑货,用来演示一下还可以,如果真作为产品开卖,还真不知有哪个傻子会...
  • 71  伏枥拿的这块Telechips的开发板所用的主控芯片是TCC7901,相对于AU1200而言,是好得很多了。姑且不说那简单易懂的编译安装环境,光是硬件的...这过程对于浸淫多年的老手来说,并不是件很困难的事情,对于其
  •  LZ会分为四个部分来谈论这个问题,由于LZ本身是Java出身,因此关于主语言的问题,都是与Java相关,其它语言的同学可以选择性忽略。此外,面试的时候一般面试官的问题都是环环相扣,逐渐深入的,这点在下面大家可以...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 89,801
精华内容 35,920
关键字:

一天分为四个时间段