Redis 從入門到起飛(上)

來源:http://t.cn/EwMvakT

1. Redis 介紹1.1 NoSQL 基本概念1.2 NoSQL 分類1.3 Redis 基本概念1.4 發展歷史1.5 應用場景2. Redis 安裝2.1 下載2.2 安裝2.3 redis 啓動3. Redis 客戶端3.1 自帶客戶端3.2 圖形界面客戶端3.3 jedis 客戶端4. 數據類型4.1 String 類型4.2 Hash 散列類型4.3 List 類型4.4 Set 類型4.5 Sortedset 類型


1. Redis 介紹

1.1 NoSQL 基本概念

爲了解決高併發、高可用、高可擴展,大數據存儲等一系列問題而產生的數據庫解決方案,就是NoSql。

NoSql,叫非關係型數據庫,它的全名Not only sql。它不能替代關係型數據庫,只能作爲關係型數據庫的一個良好補充。

1.2 NoSQL 分類

  • 鍵值(Key-Value)存儲數據庫 相關產品: Tokyo Cabinet/Tyrant、Redis、Voldemort、Berkeley DB 典型應用: 內容緩存,主要用於處理大量數據的高訪問負載。 數據模型: 一系列鍵值對 優勢: 快速查詢 劣勢: 存儲的數據缺少結構化
  • 列存儲數據庫 相關產品:Cassandra, HBase, Riak 典型應用:分佈式的文件系統 數據模型:以列簇式存儲,將同一列數據存在一起 優勢:查找速度快,可擴展性強,更容易進行分佈式擴展 劣勢:功能相對侷限
  • 文檔型數據庫 相關產品:CouchDB、MongoDB 典型應用:Web應用(與Key-Value類似,Value是結構化的) 數據模型: 一系列鍵值對 優勢:數據結構要求不嚴格 劣勢: 查詢性能不高,而且缺乏統一的查詢語法
  • 圖形(Graph)數據庫 相關數據庫:Neo4J、InfoGrid、Infinite Graph 典型應用:社交網絡 數據模型:圖結構 優勢:利用圖結構相關算法。 劣勢:需要對整個圖做計算才能得出結果,不容易做分佈式的集羣方案。

1.3 Redis 基本概念

Redis是使用c語言開發的一個高性能鍵值數據庫。Redis可以通過一些鍵值類型來存儲數據。 鍵值類型: String字符類型 map散列類型 list列表類型 set集合類型 sortedset有序集合類型

1.4 發展歷史

2008年,意大利的一家創業公司Merzia推出了一款基於MySQL的網站實時統計系統LLOOGG,然而沒過多久該公司的創始人 Salvatore Sanfilippo便 對MySQL的性能感到失望,於是他決定親自爲LLOOGG量身定做一個數據庫,並於2009年開發完成,這個數據庫就是Redis。 不過Salvatore Sanfilippo並不滿足只將Redis用於LLOOGG這一款產品,而是希望更多的人使用它,於是在同一年Salvatore Sanfilippo將Redis開源發佈,並開始和Redis的另一名主要的代碼貢獻者Pieter Noordhuis一起繼續着Redis的開發,直到今天。

Salvatore Sanfilippo自己也沒有想到,短短的幾年時間,Redis就擁有了龐大的用戶羣體。Hacker News在2012年發佈了一份數據庫的使用情況調查,結果顯示有近12%的公司在使用Redis。國內如新浪微博、街旁網、知乎網,國外如GitHub、Stack Overflow、Flickr等都是Redis的用戶。

VMware公司從2010年開始贊助Redis的開發, Salvatore Sanfilippo和Pieter Noordhuis也分別在3月和5月加入VMware,全職開發Redis。

1.5 應用場景

緩存(數據查詢、短連接、新聞內容、商品內容等等)。(最多使用) 分佈式集羣架構中的session分離。 聊天室的在線好友列表。 任務隊列。(秒殺、搶購、12306等等) 應用排行榜。 網站訪問統計。 數據過期處理(可以精確到毫秒)

2. Redis 安裝

2.1 下載

官網地址:http://redis.io/ 下載地址:http://download.redis.io/releases/redis-3.0.0.tar.gz

2.2 安裝

#sftp 上傳安裝包到linux
#解壓
tar -zxvf redis.3.0.0.tar.gz
#安裝c語言環境
sudo apt-get install gcc-c++
#編譯
cd redis-3.0.0
make
#安裝
make install PREFIX = /usr/local/redis
# 查看
cd /usr/local/redis
ls

2.3 redis 啓動

2.3.1 前端啓動

  • 前端啓動命令 ./redis-server
  • 前端啓動的關閉 強制關閉 ctrl+c 正常關閉 ./redis-cli shutdown

tips:一旦客戶端關閉,則redis服務也會停掉

2.3.2 後端啓動

  • 將 redis 源碼包中的 redis.conf 文件拷貝至 bin 目錄下 cp /root/redis-3.0.0/redis.conf
  • 修改 redis.conf 文件,將 daemonize 改爲 yes vim redis.conf
  • 使用後端命令啓動 redis ./redis-server redis.conf
  • 查看是否啓動成功 ps -aux | grep redis
  • 關閉後端啓動的方式 強制關閉: kill -9 進程號 正常關閉:./redis-cli shutdown

3. Redis 客戶端

3.1 自帶客戶端

  • 啓動 ./redis-cli -h 127.0.0.1 -p 6379 -h 指定訪問 redis 服務器的 ip 地址 -p 指定訪問的 redis 服務器的 port 端口 還可以寫成 ./redis-cli 使用默認配置,默認ip 127.0.0.1,默認端口 6379
  • 關閉 ctrl + c 127.0.0.1:6379>quit

3.2 圖形界面客戶端

redis-desktop-manager 打開如下:

img

img

選擇數據庫方式: select 加上數據庫的下標,就可以選擇指定的數據庫使用,下標從0開始。

127.0.0.1:6379> select 15
OK
127.0.0.1:6379[15]>

3.3 jedis 客戶端

3.3.1 介紹

Redis不僅是使用命令來操作,現在基本上主流的語言都有客戶端支持,比如java、C、C#、C++、php、Node.js、Go等。

在官方網站裏列一些Java的客戶端,有Jedis、Redisson、Jredis、JDBC-Redis、等其中官方推薦使用Jedis和Redisson。 在企業中用的最多的就是Jedis,下面我們就重點學習下Jedis。

Jedis同樣也是託管在github上,地址:https://github.com/xetorthio/jedis

3.3.2 工程搭建

  • 添加 jar commons-pool2-2.3.jar jedis-2.7.0.jar

3.3.2.1 單例連接 redis

img

3.3.2.2 使用連接池連接 redis

img

3.3.2.3 Spring 整合 jedisPool

添加 spring 的 jar 包 配置 spring 配置文件 applicationContext.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:mvc="http://www.springframework.org/schema/mvc"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.2.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx-3.2.xsd ">

    <!-- 連接池配置 -->
    <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <!-- 最大連接數 -->
        <property name="maxTotal" value="30" />
        <!-- 最大空閒連接數 -->
        <property name="maxIdle" value="10" />
        <!-- 每次釋放連接的最大數目 -->
        <property name="numTestsPerEvictionRun" value="1024" />
        <!-- 釋放連接的掃描間隔(毫秒) -->
        <property name="timeBetweenEvictionRunsMillis" value="30000" />
        <!-- 連接最小空閒時間 -->
        <property name="minEvictableIdleTimeMillis" value="1800000" />
        <!-- 連接空閒多久後釋放, 當空閒時間>該值 且 空閒連接>最大空閒連接數 時直接釋放 -->
        <property name="softMinEvictableIdleTimeMillis" value="10000" />
        <!-- 獲取連接時的最大等待毫秒數,小於零:阻塞不確定的時間,默認-1 -->
        <property name="maxWaitMillis" value="1500" />
        <!-- 在獲取連接的時候檢查有效性, 默認false -->
        <property name="testOnBorrow" value="false" />
        <!-- 在空閒時檢查有效性, 默認false -->
        <property name="testWhileIdle" value="true" />
        <!-- 連接耗盡時是否阻塞, false報異常,ture阻塞直到超時, 默認true -->
        <property name="blockWhenExhausted" value="false" />
    </bean>

    <!-- redis單機 通過連接池 -->
    <bean id="jedisPool" class="redis.clients.jedis.JedisPool"
        destroy-method="close">
        <constructor-arg name="poolConfig" ref="jedisPoolConfig" />
        <constructor-arg name="host" value="192.168.242.130" />
        <constructor-arg name="port" value="6379" />
    </bean>
</beans>

測試代碼

    @Test
    public void testJedisPool() {
        JedisPool pool = (JedisPool) applicationContext.getBean("jedisPool");
        Jedis jedis = null;
        try {
            jedis = pool.getResource();

            jedis.set("name", "lisi");
            String name = jedis.get("name");
            System.out.println(name);
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            if (jedis != null) {
                // 關閉連接
                jedis.close();
            }
        }
    }

4. 數據類型

4.1 String 類型

賦值 set key value

127.0.0.1:6379> set test 123
OK

取值 get key

127.0.0.1:6379> get test
"123"

取值並賦值 getset key value

127.0.0.1:6379> getset test 321
"123"
127.0.0.1:6379> get test
"321"

設置獲取多個鍵值 mset key value [key value…] mget key [key…]

127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3
OK
127.0.0.1:6379> mget k1 k2
1) "v1"
2) "v2"

刪除 del key

127.0.0.1:6379> del test
(integer) 1

數值增減

  • 遞增數字 當存儲的字符串是整數時,Redis提供了一個實用的命令INCR,其作用是讓當前鍵值遞增,並返回遞增後的值。 語法:incr key 127.0.0.1:6379> set num 1 OK 127.0.0.1:6379> incr num (integer) 2 127.0.0.1:6379> incr num (integer) 3 127.0.0.1:6379> incr num (integer) 4
  • 增加指定的整數 incrby key increment 127.0.0.1:6379> incrby num 2 (integer) 8 127.0.0.1:6379> incrby num 2 (integer) 10
  • 遞減數值 decr key 127.0.0.1:6379> decr num (integer) 9 127.0.0.1:6379> decr num (integer) 8
  • 減少指定的數值 decryby key decrement 127.0.0.1:6379> decrby num 2 (integer) 6 127.0.0.1:6379> decrby num 2 (integer) 4

向尾部追加值 APPEND的作用是向鍵值的末尾追加value。如果鍵不存在則將該鍵的值設置爲value,即相當於 SET key value。返回值是追加後字符串的總長度。 語法:append key value

127.0.0.1:6379> set str hello
OK
127.0.0.1:6379> append str "world"
(integer) 10
127.0.0.1:6379> get str
"helloworld"

獲取字符串長度 STRLEN命令返回鍵值的長度,如果鍵不存在則返回0。 語法:strlen key

127.0.0.1:6379> strlen str
(integer) 10

應用

  • 自增主鍵 商品編號、訂單號採用 string 的遞增數字特性生成

4.2 Hash 散列類型

4.2.1 使用 string 的問題

假設有User對象以JSON序列化的形式存儲到Redis中,User對象有id,username、password、age、name等屬性,存儲的過程如下: 保存、更新:User對象 json(string) redis

如果在業務上只是更新age屬性,其他的屬性並不做更新我應該怎麼做呢? 如果仍然採用上邊的方法在傳輸、處理時會造成資源浪費,下邊講的hash可以很好的解決這個問題。

4.2.2 介紹

hash叫散列類型,它提供了字段和字段值的映射。字段值只能是字符串類型,不支持散列類型、集合類型等其它類型。如下:

img

4.2.3 命令

賦值 HSET命令不區分插入和更新操作,當執行插入操作時HSET命令返回1,當執行更新操作時返回0。

  • 一次只設置一個字段值 語法:hset key field value 127.0.0.1:6379> hset user username zhangsan (integer) 1
  • 一次設置多個字段值 語法:hmset key field value [field value…] 127.0.0.1:6379> hmset user age 20 username lisi OK
  • 當字段不存在時賦值,類似hset,區別在於如果字段存在,該命令不執行任何操作。 語法:hsetnx key field value 127.0.0.1:6379> hsetnx user age 30 (integer) 0

取值

  • 一次獲取一個字段值 語法:hget key field 127.0.0.1:6379> hget user username "lisi"
  • 一次可以獲取多個字段值 語法:hmget key field [field…] 127.0.0.1:6379> hmget user age username 1) "20" 2) "lisi"
  • 獲取所有字段值 語法:hgetall key 127.0.0.1:6379> hgetall user 1) "username" 2) "lisi" 3) "age" 4) "20"

刪除字段 可以刪除一個或多個字段,返回值是被刪除的字段的個數。 語法:hdel key field [field…]

127.0.0.1:6379> hdel user age
(integer) 1
127.0.0.1:6379> hdel user age username
(integer) 1

增加數字 語法:hincrby key field increment

127.0.0.1:6379> hincrby user age 2
(integer) 2

判斷字段是否存在 語法:hexists key field

127.0.0.1:6379> hexists user age
(integer) 1

只獲取字段名或字段值 語法: hkeys key hvals key

127.0.0.1:6379> hkeys user
1) "age"

獲取字段數量 語法:hlen key

127.0.0.1:6379> hlen user
(integer) 1

應用 存儲商品信息

127.0.0.1:6379> hlen user
(integer) 1

獲取商品信息

127.0.0.1:6379> hgetall items:1001
1) "id"
2) "3"
3) "name"
4) "apple"
5) "price"
6) "5.00"

4.3 List 類型

4.3.1 ArrayList 和 LinkedList 的區別

Arraylist是使用數組來存儲數據,特點:查詢快、增刪慢

Linkedlist是使用雙向鏈表存儲數據,特點:增刪快、查詢慢,但是查詢鏈表兩端的數據也很快。

Redis的list是採用來鏈表來存儲的,所以對於redis的list數據類型的操作,是操作list的兩端數據來操作的。

4.3.2 命令

向列表兩端增加元素

  • 向列表左邊增加元素 語法:lpush key value [value…]
127.0.0.1:6379> lpush list:1 1 2 3
(integer) 3
  • 向列表右邊增加元素 語法:rpush key value [value…]
127.0.0.1:6379> rpush list:1 4 5 6
(integer) 6

查看列表 LRANGE命令是列表類型最常用的命令之一,獲取列表中的某一片段,將返回start、stop之間的所有元素(包含兩端的元素),索引從0開始。索引可以是負數,如:“-1”代表最後邊的一個元素。

語法:lrange key start stop

127.0.0.1:6379> lrange list:1 0 2
1) "3"
2) "2"
3) "1"
127.0.0.1:6379> lrange list:1 0 -1
1) "3"
2) "2"
3) "1"
4) "4"
5) "5"
6) "6"

從列表兩端彈出元素 LPOP命令從列表左邊彈出一個元素,會分兩步完成:

  • 第一步是將列表左邊的元素從列表中移除
  • 第二步是返回被移除的元素值。 語法: lpop key rpop key 127.0.0.1:6379> lpop list:1 "3" 127.0.0.1:6379> rpop list:1 "6"

獲取列表中元素的個數 語法:llen key

127.0.0.1:6379> llen list:1
(integer) 4

刪除列表中指定的值 LREM命令會刪除列表中前count個值爲value的元素,返回實際刪除的元素個數。根據count值的不同,該命令的執行方式會有所不同:

  • 當count>0時, LREM會從列表左邊開始刪除。
  • 當count<0時, LREM會從列表後邊開始刪除。
  • 當count=0時, LREM刪除所有值爲value的元素。

語法:lrem key count value

獲得/設置指定索引的元素值

  • 獲得指定索引的元素值 語法:lindex key index 127.0.0.1:6379> lindex list:1 2 "4"
  • 設置指定索引的元素值 語法:lset key index value 127.0.0.1:6379> lset list:1 2 2 OK

只保留列表指定片段 指定範圍和 lrange 一致 語法:ltrim key start stop

127.0.0.1:6379> lrange list:1 0 -1
1) "2"
2) "1"
3) "2"
4) "5"
127.0.0.1:6379> ltrim list:1 0 2
OK
127.0.0.1:6379> lrange list:1 0 -1
1) "2"
2) "1"
3) "2"

向列表中插入元素 該命令首先會在列表中從左到右查找值爲pivot的元素,然後根據第二個參數是BEFORE還是AFTER來決定將value插入到該元素的前面還是後面。 語法:linsert key before | after pivot value

127.0.0.1:6379> lrange list:1 0 -1
1) "2"
2) "1"
3) "2"
127.0.0.1:6379> linsert list:1 after 1 9
(integer) 4
127.0.0.1:6379> lrange list:1 0 -1
1) "2"
2) "1"
3) "9"
4) "2"

將元素從一個列表轉移到另一個列表 語法:rpoplpush source destination

127.0.0.1:6379> lrange list:1 0 -1
1) "2"
2) "1"
3) "9"
4) "2"
127.0.0.1:6379> rpoplpush list:1 newlist
"2"
127.0.0.1:6379> lrange newlist 0 -1
1) "2"
127.0.0.1:6379> lrange list:1 0 -1
1) "2"
2) "1"
3) "9"

應用 在Redis中創建商品評論列表 用戶發佈商品評論,將評論信息轉成json存儲到list中。 用戶在頁面查詢評論列表,從redis中取出json數據展示到頁面。

定義商品評論列表key: 商品編號爲1001的商品評論key【items: comment:1001】

4.4 Set 類型

集合類型:無序、不可重複 列表類型:有序、可重複

4.4.1 命令

增加/刪除元素 語法:sadd key member [member…]

127.0.0.1:6379> sadd set a b c
(integer) 3
127.0.0.1:6379> sadd set a
(integer) 0

語法:srem key member [member…]

127.0.0.1:6379> srem set c
(integer) 1

獲得集合中的所有元素 語法:smembers key

127.0.0.1:6379> smembers set
1) "b"
2) "a"

判斷元素是否在集合中 語法:sismember key member

127.0.0.1:6379> sismember set a
(integer) 1
127.0.0.1:6379> sismember set h
(integer) 0

4.4.2 運算命令

集合的差集運算 A-B 屬於 A 並且 不屬於 B 的元素構成的集合

img

語法:sdiff key [key…]

127.0.0.1:6379> sadd setA 1 2 3
(integer) 3
127.0.0.1:6379> sadd setB 2 3 4
(integer) 3
127.0.0.1:6379> sdiff setA setB
1) "1"
127.0.0.1:6379> sdiff setB setA
1) "4"

集合的交集運算 屬於A且屬於B的元素構成的集合

img

語法:sinter key [key…]

127.0.0.1:6379> sinter setA setB
1) "2"
2) "3"

集合的並集運算 屬於 A 或者 屬於 B 的元素構成的集合

img

語法:sunion key [key…]

127.0.0.1:6379> sunion setA setB
1) "1"
2) "2"
3) "3"
4) "4"

獲得集合中元素的個數 語法:scard key

127.0.0.1:6379> smembers setA
1) "1"
2) "2"
3) "3"
127.0.0.1:6379> scard setA
(integer) 3

從集合中彈出一個元素 注意:由於集合是無序的,所有spop命令會從集合中隨機選擇一個元素彈出。 語法:spop key

127.0.0.1:6379> spop setA
"2"

4.5 Sortedset 類型

Sortedset 又叫 zset Sortedset 是有序集合,可排序的,但是唯一。 Sortedset 和 set 的不同之處,會給 set 中元素添加一個分數,然後通過這個分數進行排序。

4.5.1 命令

4.5.1.1 增加元素

向有序集合中加入一個元素和該元素的分數,如果該元素已經存在則會用新的分數替換原有的分數。返回值是新加入到集合中的元素個數,不包含之前已經存在的元素。 語法:zadd key score member [score member…]

127.0.0.1:6379> zadd scoreboard 80 zhangsan 89 lisi 94 wangwu
(integer) 3
127.0.0.1:6379> zadd scoreboard 97 lisi
(integer) 0

4.5.1.2 獲取元素分數

語法:zscore key member

127.0.0.1:6379> zscore scoreboard lisi
"97"

4.5.1.3 刪除元素

移除有序集key中的一個或多個成員,不存在的成員將被忽略。 當key存在但不是有序集類型時,返回一個錯誤。

語法:zrem key member [member…]

127.0.0.1:6379> zrem scoreboard lisi
(integer) 1

4.5.1.4 獲得排名在某個範圍的元素列表

獲得排名在某個範圍的元素列表

  • 按照元素分數從小到大的順序返回索引從start到stop之間的所有元素(包含兩端的元素) 語法:zrange key start stop [withscores] 127.0.0.1:6379> zrange scoreboard 0 2 1) "zhangsan" 2) "wangwu"
  • 按照元素分數從大到小的順序返回索引從start到stop之間的所有元素(包含兩端的元素) 語法:zrevrange key start stop [withscores] 127.0.0.1:6379> zrevrange scoreboard 0 2 1) "wangwu" 2) "zhangsan" 如果需要獲得元素的分數可以在命令末尾加上 withscores 參數 ··· 127.0.0.1:6379> zrevrange scoreboard 0 2 withscores
  1. "wangwu"
  2. "94"
  3. "zhangsan"
  4. "80" ···

4.5.1.5 獲取元素的排名

  • 從小到大 語法:zrank key member
127.0.0.1:6379> zrank scoreboard zhangsan
(integer) 0
  • 從大到小 語法:zrevrank key member
127.0.0.1:6379> zrevrank scoreboard zhangsan
(integer) 1

4.5.1.6 獲得指定分數範圍的元素

語法:zrangebyscore key min max [withscores][limit offset count]

127.0.0.1:6379> ZRANGEBYSCORE scoreboard 90 97 WITHSCORES
1) "wangwu"
2) "94"
3) "lisi"
4) "97"
127.0.0.1:6379> ZRANGEBYSCORE scoreboard 70 100 limit 1 2
1) "wangwu"
2) "lisi"

4.5.1.7 增加某個元素的分數

返回值是更改後的分數 語法:zincrby key increment member

127.0.0.1:6379> ZINCRBY scoreboard 4 lisi
"101“

4.5.1.8 獲得集合中元素的數量

語法:zcard key

127.0.0.1:6379> zcard scoreboard
(integer) 3

4.5.1.9 獲得指定分數範圍內的元素個數

語法:zcount key min max

127.0.0.1:6379> zcount scoreboard 80 90
(integer) 1

4.5.1.10 按照排名範圍刪除元素

語法:zremrangebyrank key start stop

127.0.0.1:6379> zremrangebyrank scoreboard 0 1
(integer) 2
127.0.0.1:6379> zrange scoreboard 0 -1
1) "wangwu"

4.5.1.11 按照分數範圍刪除元素

語法:zremrangebyscore key min max

127.0.0.1:6379> zadd scoreboard 84 zhangsan
(integer) 1
127.0.0.1:6379> ZREMRANGEBYSCORE scoreboard 80 100
(integer) 1

4.5.1.12 應用

4.5.1.13 商品銷售排行榜

需求:根據商品銷售量對商品進行排行顯示 思路:定義商品銷售排行榜(sorted set集合),Key爲items:sellsort,分數爲商品銷售量。

寫入商品銷售量:

  • 商品編號1001的銷量是9,商品編號1002的銷量是10 192.168.101.3:7007> ZADD items:sellsort 9 1001 10 1002
  • 商品編號1001的銷量加1 192.168.101.3:7001> ZINCRBY items:sellsort 1 1001
  • 商品銷量前10名: 192.168.101.3:7001> ZRANGE items:sellsort 0 9 withscores
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章