<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    聶永的博客

    記錄工作/學(xué)習(xí)的點(diǎn)點(diǎn)滴滴。

    Servlet 3.0筆記之Redis操作示范Retwis JAVA版

    最近學(xué)習(xí)Redis,一個目前風(fēng)頭正勁的KEY-VALUE NOSQL,支持LIST、SET、MAP等格式存儲,某些操作竟然是原子級別,比如incr命令,相當(dāng)驚艷。官方提供的一個Retwis(simple clone of Twitter)示范,證明了完全可以使用redis替代SQL數(shù)據(jù)庫存儲數(shù)據(jù),真是一大開創(chuàng)性創(chuàng)新,挑戰(zhàn)人們的傳統(tǒng)思維模式,為之驚嘆!

    不過那是一個PHP版本,我下載到本地PHP但無法部署成功;還好有一個Retwis-RB示范,還提供一個在線版,試用之后,再下載源代碼,RUBY + Sinatra MVC結(jié)構(gòu),看的流口水,代碼那般簡潔。

    為體驗(yàn)Redis,同時也為對比Ruby代碼,因此誕生了Retwis-JAVA,Retwis-RB的山寨版,因此其邏輯和HTML資源一致,再次表示對原作者Dan Lucraft的感謝。

    Retwis-JAVA,基于Servlet 3.0 + UrlRewrite + Freemarker + Jedis。示范運(yùn)行在Tomcat 7中,redis為最新的2.22版本,jedis為redis的java客戶端操作框架。在Servlet 3.0規(guī)范中,對Url映射處理依然沒有進(jìn)步,因此只能使用UrlRewrite框架讓部分url看起來友好一些。另外,項目沒有使用IOC容器框架,沒有使用MVC框架,代碼量稍微多些,代碼相對耦合一些。若使用Struts2 + Spring 代碼量會少一些。

    對涉及到的redis存儲結(jié)構(gòu),大致如下:


    涉及到的兩個對象很簡單:


    序列化后以二進(jìn)制數(shù)據(jù)保存到redis中:

        private byte[] object2Bytes(V value) {
            
    if (value == null)
                
    return null;

            ByteArrayOutputStream arrayOutputStream 
    = new ByteArrayOutputStream();
            ObjectOutputStream outputStream;
            
    try {
                outputStream 
    = new ObjectOutputStream(arrayOutputStream);

                outputStream.writeObject(value);
            } 
    catch (IOException e) {
                e.printStackTrace();
            } 
    finally {
                
    try {
                    arrayOutputStream.close();
                } 
    catch (IOException e) {
                    e.printStackTrace();
                }
            }

            
    return arrayOutputStream.toByteArray();
        }


        
    public void save(String key, V value) {
            jedis.set(getKey(key), object2Bytes(value));
        }

    獲取用戶的timeline時,redis的LRANGE命令提供對list類型數(shù)據(jù)提供分頁操作:

        private List<Status> timeline(String targetId, int page) {
            
    if (page < 1)
                page 
    = 1;

            
    int startIndex = (page - 1* 10;
            
    int endIndex = page * 10;

            List
    <String> idList = super.jedis
                    .lrange(targetId, startIndex, endIndex);

            
    if (idList.isEmpty())
                
    return new ArrayList<Status>(0);

            List
    <Status> statusList = new ArrayList<Status>(idList.size());
            
    for (String id : idList) {
                Status status 
    = load(Long.valueOf(id));

                
    if (status == null)
                    
    continue;

                status.setUser(userService.load(status.getUid()));

                statusList.add(status);
            }

            
    return statusList;
        }

    很顯然,LRANGE取出了Status對象的ID,然后我們需要再次根據(jù)ID獲取對應(yīng)的Status對象二進(jìn)制數(shù)據(jù),然后反序列化:

        public Status load(long id) {
            
    return super.get(getFormatId(id));
        }

        
    private String getFormatId(long id) {
            
    return String.format(STATUS_ID_FORMAT, id);
        }

        
    private static final String STATUS_ID_FORMAT = "status:id:%d";

        
    public V get(String key) {
            
    return byte2Object(jedis.get(getKey(key)));
        }

        @SuppressWarnings(
    "unchecked")
        
    private V byte2Object(byte[] bytes) {
            
    if (bytes == null || bytes.length == 0)
                
    return null;

            
    try {
                ObjectInputStream inputStream;
                inputStream 
    = new ObjectInputStream(new ByteArrayInputStream(bytes));
                Object obj 
    = inputStream.readObject();

                
    return (V) obj;
            } 
    catch (IOException e) {
                e.printStackTrace();
            } 
    catch (ClassNotFoundException e) {
                e.printStackTrace();
            }

            
    return null;
        }

    以上使用JDK內(nèi)置的序列化支持;更多序列化,可參考hessian、google protobuf等序列化框架,后者提供業(yè)界更為成熟的跨平臺、更為高效的序列化方案。更多代碼請參見附件。

    一些總結(jié)和思考:

    1. 不僅僅是緩存,替代SQL數(shù)據(jù)庫已完全成為可能,更高效,更經(jīng)濟(jì);雖然只是打開了一扇小的窗戶,但說不準(zhǔn)以后人們會把大門打開。
    2. 實(shí)際環(huán)境中,可能最佳方式為SQL + NOSQL配合使用,互相彌補(bǔ)不足;還好,redis指令不算多,可速查,簡單易記。
    3. JAVA和RUBY代碼相比,有些重

    另:

    在線版,請參考 http://retwisrb.danlucraft.com/。那個誰誰,要運(yùn)行范例,保證redis運(yùn)行才行。

    Retwis-JAVA下載

    參考資料:

    Writing a simple Twitter clone with PHP and Redis

    https://github.com/xetorthio/jedis

    http://redis.io/commands

    posted on 2011-04-06 09:42 nieyong 閱讀(6128) 評論(0)  編輯  收藏 所屬分類: Servlet3

    公告

    所有文章皆為原創(chuàng),若轉(zhuǎn)載請標(biāo)明出處,謝謝~

    新浪微博,歡迎關(guān)注:

    導(dǎo)航

    <2011年4月>
    272829303112
    3456789
    10111213141516
    17181920212223
    24252627282930
    1234567

    統(tǒng)計

    常用鏈接

    留言簿(58)

    隨筆分類(130)

    隨筆檔案(151)

    個人收藏

    最新隨筆

    搜索

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 久久精品免费一区二区喷潮| a级精品九九九大片免费看| 亚洲无砖砖区免费| 国产亚洲精品观看91在线| 无码色偷偷亚洲国内自拍| 免费无码黄网站在线观看| 亚洲伦理中文字幕| 国产一卡二卡四卡免费| 久久久久亚洲av无码专区导航 | 国产成人精品日本亚洲专区6| 久久久久国产精品免费网站| 亚洲成AV人片在线观看ww| 中国一级特黄的片子免费 | 免费在线观看污网站| 亚洲成a人片在线观看天堂无码| 最近中文字幕免费mv视频7| 亚洲黄色激情视频| 四虎成人免费网址在线| 亚洲乱码av中文一区二区| 日韩伦理片电影在线免费观看| 亚洲爆乳精品无码一区二区| 日本大片在线看黄a∨免费| 亚洲爆乳少妇无码激情| 全黄a免费一级毛片人人爱| 免费无码婬片aaa直播表情| 亚洲一区二区精品视频| 国产无遮挡色视频免费观看性色 | 亚洲另类无码专区首页| 国产一区二区三区在线观看免费 | 桃子视频在线观看高清免费视频| 亚洲精品免费在线观看| 亚洲精品在线免费看| 亚洲欧洲精品成人久久曰| 亚洲国产精品尤物YW在线观看| 中国在线观看免费的www| 亚洲视频在线观看一区| 毛片免费视频观看| 一区二区免费国产在线观看| 国产亚洲日韩一区二区三区| 最近中文字幕完整免费视频ww | 亚洲香蕉免费有线视频|