23-redis
23-redis
文章目錄
- 23-redis
- 今日內容
- Redis
- 1. 概念
- 1.1.什么是NOSQL
- 1.1.1. NOSQL和關系型數據庫比較
- 1.1.2. 非關系型數據庫的優勢:
- 1.1.3. 關系型數據庫的優勢:
- 1.1.4. 總結
- 1.2.主流的NOSQL產品
- 1.3 什么是Redis
- 1.3.1 redis的應用場景
- 2. 下載安裝
- 3. 命令操作
- 1. redis的數據結構:
- 2. 字符串類型 string
- 3. 哈希類型 hash
- 4. 列表類型 list:可以添加一個元素到列表的頭部(左邊)或者尾部(右邊)
- 5. 集合類型 set : 不允許重復元素
- 6. 有序集合類型 sortedset
- 7. 通用命令
- 4. 持久化
- 5. Java客戶端 Jedis
- Jedis操作各種redis中的數據結構
- 1) 字符串類型 string
- 2) 哈希類型 hash : map格式
- 3) 列表類型 list : linkedlist格式。支持重復元素
- 4) 集合類型 set : 不允許重復元素
- 5) 有序集合類型 sortedset:不允許重復元素,且元素有順序
- jedis連接池: JedisPool
- 案例:
- 案例需求:
- 案例目錄:
- 案例關鍵代碼部分
今日內容
1. redis1. 概念2. 下載安裝3. 命令操作1. 數據結構4. 持久化操作5. 使用Java客戶端操作redisRedis
1. 概念
: redis是一款高性能的NOSQL系列的非關系型數據庫
1.1.什么是NOSQL
NoSQL(NoSQL = Not Only SQL),意即“不僅僅是SQL”,是一項全新的數據庫理念,泛指非關系型的數據庫。隨著互聯網web2.0網站的興起,傳統的關系數據庫在應付web2.0網站,特別是超大規模和高并發的SNS類型的web2.0純動態網站已經顯得力不從心,暴露了很多難以克服的問題,而非關系型的數據庫則由于其本身的特點得到了非常迅速的發展。NoSQL數據庫的產生就是為了解決大規模數據集合多重數據種類帶來的挑戰,尤其是大數據應用難題。1.1.1. NOSQL和關系型數據庫比較
優點:1)成本:nosql數據庫簡單易部署,基本都是開源軟件,不需要像使用oracle那樣花費大量成本購買使用,相比關系型數據庫價格便宜。2)查詢速度:nosql數據庫將數據存儲于緩存之中,關系型數據庫將數據存儲在硬盤中,自然查詢速度遠不及nosql數據庫。3)存儲數據的格式:nosql的存儲格式是key,value形式、文檔形式、圖片形式等等,所以可以存儲基礎類型以及對象或者是集合等各種格式,而數據庫則只支持基礎類型。4)擴展性:關系型數據庫有類似join這樣的多表查詢機制的限制導致擴展很艱難。缺點:1)維護的工具和資料有限,因為nosql是屬于新的技術,不能和關系型數據庫10幾年的技術同日而語。2)不提供對sql的支持,如果不支持sql這樣的工業標準,將產生一定用戶的學習和使用成本。3)不提供關系型數據庫對事務的處理。1.1.2. 非關系型數據庫的優勢:
1)性能NOSQL是基于鍵值對的,可以想象成表中的主鍵和值的對應關系,而且不需要經過SQL層的解析,所以性能非常高。2)可擴展性同樣也是因為基于鍵值對,數據之間沒有耦合性,所以非常容易水平擴展。1.1.3. 關系型數據庫的優勢:
1)復雜查詢可以用SQL語句方便的在一個表以及多個表之間做非常復雜的數據查詢。 2)事務支持使得對于安全性能很高的數據訪問要求得以實現。對于這兩類數據庫,對方的優勢就是自己的弱勢,反之亦然。1.1.4. 總結
關系型數據庫與NoSQL數據庫并非對立而是互補的關系,即通常情況下使用關系型數據庫,在適合使用NoSQL的時候使用NoSQL數據庫, 讓NoSQL數據庫對關系型數據庫的不足進行彌補。 一般會將數據存儲在關系型數據庫中,在nosql數據庫中備份存儲關系型數據庫的數據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語言開發的一個開源的高性能鍵值對(key-value)數據庫,官方提供測試數據,50個并發執行100000個請求,讀的速度是110000次/s,寫的速度是81000次/s ,且Redis通過提供多種鍵值數據類型來適應不同場景下的存儲需求,目前為止Redis支持的鍵值數據類型如下:1) 字符串類型 string2) 哈希類型 hash3) 列表類型 list4) 集合類型 set5) 有序集合類型 sortedset1.3.1 redis的應用場景
? 緩存(數據查詢、短連接、新聞內容、商品內容等等)? 聊天室的在線好友列表? 任務隊列。(秒殺、搶購、12306等等)? 應用排行榜? 網站訪問統計? 數據過期處理(可以精確到毫秒? 分布式集群架構中的session分離2. 下載安裝
1. 官網:https://redis.io2. 中文網:http://www.redis.net.cn/3. 解壓直接可以使用:* redis.windows.conf:配置文件* redis-cli.exe:redis的客戶端* redis-server.exe:redis服務器端3. 命令操作
1. redis的數據結構:
* redis存儲的是:key,value格式的數據,其中key都是字符串,value有5種不同的數據結構
* value的數據結構:
1) 字符串類型 string
2) 哈希類型 hash : map格式
3) 列表類型 list : linkedlist格式。支持重復元素
4) 集合類型 set : 不允許重復元素
5) 有序集合類型 sortedset:不允許重復元素,且元素有順序
2. 字符串類型 string
1. 存儲: set key value127.0.0.1:6379> set username zhangsanOK2. 獲取: get key127.0.0.1:6379> get username"zhangsan"3. 刪除: del key127.0.0.1:6379> del age(integer) 13. 哈希類型 hash
1. 存儲: hset key field value127.0.0.1:6379> hset myhash username lisi(integer) 1127.0.0.1:6379> hset myhash password 123(integer) 12. 獲取: * hget key field: 獲取指定的field對應的值127.0.0.1:6379> hget myhash username"lisi"* hgetall key:獲取所有的field和value127.0.0.1:6379> hgetall myhash1) "username"2) "lisi"3) "password"4) "123"3. 刪除: hdel key field127.0.0.1:6379> hdel myhash username(integer) 14. 列表類型 list:可以添加一個元素到列表的頭部(左邊)或者尾部(右邊)
1. 添加:1. lpush key value: 將元素加入列表左表2. rpush key value:將元素加入列表右邊127.0.0.1:6379> lpush myList a(integer) 1127.0.0.1:6379> lpush myList b(integer) 2127.0.0.1:6379> rpush myList c(integer) 32. 獲取:* lrange key start end :范圍獲取127.0.0.1:6379> lrange myList 0 -11) "b"2) "a"3) "c"3. 刪除:* lpop key: 刪除列表最左邊的元素,并將元素返回* rpop key: 刪除列表最右邊的元素,并將元素返回5. 集合類型 set : 不允許重復元素
1. 存儲:sadd key value127.0.0.1:6379> sadd myset a(integer) 1127.0.0.1:6379> sadd myset a(integer) 02. 獲取:smembers key:獲取set集合中所有元素127.0.0.1:6379> smembers myset1) "a"3. 刪除:srem key value:刪除set集合中的某個元素 127.0.0.1:6379> srem myset a(integer) 16. 有序集合類型 sortedset
:不允許重復元素,且元素有順序.每個元素都會關聯一個double類型的分數。redis正是通過分數來為集合中的成員進行從小到大的排序。
1. 存儲:zadd key score value127.0.0.1:6379> zadd mysort 60 zhangsan(integer) 1127.0.0.1:6379> zadd mysort 50 lisi(integer) 1127.0.0.1:6379> zadd mysort 80 wangwu(integer) 12. 獲取:zrange key start end [withscores]127.0.0.1:6379> zrange mysort 0 -11) "lisi"2) "zhangsan"3) "wangwu"127.0.0.1:6379> zrange mysort 0 -1 withscores1) "zhangsan"2) "60"3) "wangwu"4) "80"5) "lisi"6) "500"3. 刪除:zrem key value127.0.0.1:6379> zrem mysort lisi(integer) 17. 通用命令
1. keys * : 查詢所有的鍵2. type key : 獲取鍵對應的value的類型3. del key:刪除指定的key value4. 持久化
- 在一定的間隔時間中,檢測key的變化情況,然后持久化數據
appendonly no(關閉aof) --> appendonly yes (開啟aof)
5. Java客戶端 Jedis
- Jedis: 一款java操作redis數據庫的工具.
- 使用步驟:
- 下載jedis的jar包
- 使用
?
Jedis操作各種redis中的數據結構
1) 字符串類型 string
set get//1. 獲取連接 Jedis jedis = new Jedis();//如果使用空參構造,默認值 "localhost",6379端口 //2. 操作 //存儲 jedis.set("username","zhangsan"); //獲取 String username = jedis.get("username"); System.out.println(username);//可以使用setex()方法存儲可以指定過期時間的 key value jedis.setex("activecode",20,"hehe");//將activecode:hehe鍵值對存入redis,并且20秒后自動刪除該鍵值對//3. 關閉連接 jedis.close();2) 哈希類型 hash : map格式
hset hget hgetAll //1. 獲取連接Jedis jedis = new Jedis();//如果使用空參構造,默認值 "localhost",6379端口//2. 操作// 存儲hashjedis.hset("user","name","lisi");jedis.hset("user","age","23");jedis.hset("user","gender","female");// 獲取hashString name = jedis.hget("user", "name");System.out.println(name);? // 獲取hash的所有map中的數據Map<String, String> user = jedis.hgetAll("user");// keysetSet<String> keySet = user.keySet();for (String key : keySet) {//獲取valueString value = user.get(key);System.out.println(key + ":" + value);}//3. 關閉連接jedis.close();3) 列表類型 list : linkedlist格式。支持重復元素
lpush / rpushlpop / rpoplrange start end : 范圍獲取//1. 獲取連接Jedis jedis = new Jedis();//如果使用空參構造,默認值 "localhost",6379端口//2. 操作// list 存儲jedis.lpush("mylist","a","b","c");//從左邊存jedis.rpush("mylist","a","b","c");//從右邊存// list 范圍獲取List<String> mylist = jedis.lrange("mylist", 0, -1);System.out.println(mylist);// list 彈出String element1 = jedis.lpop("mylist");//cSystem.out.println(element1);String element2 = jedis.rpop("mylist");//cSystem.out.println(element2);// list 范圍獲取List<String> mylist2 = jedis.lrange("mylist", 0, -1);System.out.println(mylist2);//3. 關閉連接jedis.close();4) 集合類型 set : 不允許重復元素
saddsmembers:獲取所有元素//1. 獲取連接Jedis jedis = new Jedis();//如果使用空參構造,默認值 "localhost",6379端口//2. 操作// set 存儲jedis.sadd("myset","java","php","c++");// set 獲取Set<String> myset = jedis.smembers("myset");System.out.println(myset);//3. 關閉連接jedis.close();?
5) 有序集合類型 sortedset:不允許重復元素,且元素有順序
zaddzrange//1. 獲取連接Jedis jedis = new Jedis();//如果使用空參構造,默認值 "localhost",6379端口//2. 操作// sortedset 存儲jedis.zadd("mysortedset",3,"亞瑟");jedis.zadd("mysortedset",30,"后裔");jedis.zadd("mysortedset",55,"孫悟空");// sortedset 獲取Set<String> mysortedset = jedis.zrange("mysortedset", 0, -1);System.out.println(mysortedset);//3. 關閉連接jedis.close();?
jedis連接池: JedisPool
* 使用:1. 創建JedisPool連接池對象2. 調用方法 getResource()方法獲取Jedis連接//0.創建一個配置對象JedisPoolConfig config = new JedisPoolConfig();config.setMaxTotal(50);config.setMaxIdle(10);//1.創建Jedis連接池對象JedisPool jedisPool = new JedisPool(config,"localhost",6379);//2.獲取連接Jedis jedis = jedisPool.getResource();//3. 使用jedis.set("hehe","heihei");//4. 關閉 歸還到連接池中jedis.close(); --------------------------------------------------------------------------------- * 連接池工具類 public class JedisPoolUtils {private static JedisPool jedisPool;static{//讀取配置文件InputStream is = JedisPoolUtils.class.getClassLoader().getResourceAsStream("jedis.properties");//創建Properties對象Properties pro = new Properties();//關聯文件try {pro.load(is);} catch (IOException e) {e.printStackTrace();}//獲取數據,設置到JedisPoolConfig中JedisPoolConfig config = new JedisPoolConfig();config.setMaxTotal(Integer.parseInt(pro.getProperty("maxTotal")));config.setMaxIdle(Integer.parseInt(pro.getProperty("maxIdle")));//初始化JedisPooljedisPool = new JedisPool(config,pro.getProperty("host"),Integer.parseInt(pro.getProperty("port")));}/*** 獲取連接方法*/public static Jedis getJedis(){return jedisPool.getResource();} }案例:
案例需求:
1. 提供index.html頁面,頁面中有一個省份 下拉列表 2. 當 頁面加載完成后 發送ajax請求,加載所有省份 <!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Title</title><script src="js/jquery-3.3.1.min.js"></script><script>$(function () {//發送ajax請求,加載所有省份數據$.get("provinceServlet",{},function (data) {//[{"id":1,"name":"北京"},{"id":2,"name":"上海"},{"id":3,"name":"廣州"},{"id":4,"name":"陜西"}]//1.獲取selectvar province = $("#province");//2.遍歷json數組$(data).each(function () {//3.創建<option>var option = "<option name='"+this.id+"'>"+this.name+"</option>";//4.調用select的append追加optionprovince.append(option);});}); }); </script> </head> <body><select id="province"><option>--請選擇省份--</option></select> </body> </html>案例目錄:
案例關鍵代碼部分
util包下的JedisPoolUtils:
package cn.itcast.jedis.util;import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisPoolConfig;import java.io.IOException; import java.io.InputStream; import java.util.Properties;/**JedisPool工具類加載配置文件,配置連接池的參數提供獲取連接的方法*/ public class JedisPoolUtils {private static JedisPool jedisPool;static{//讀取配置文件InputStream is = JedisPoolUtils.class.getClassLoader().getResourceAsStream("jedis.properties");//創建Properties對象Properties pro = new Properties();//關聯文件try {pro.load(is);} catch (IOException e) {e.printStackTrace();}//獲取數據,設置到JedisPoolConfig中JedisPoolConfig config = new JedisPoolConfig();config.setMaxTotal(Integer.parseInt(pro.getProperty("maxTotal")));config.setMaxIdle(Integer.parseInt(pro.getProperty("maxIdle")));//初始化JedisPooljedisPool = new JedisPool(config,pro.getProperty("host"),Integer.parseInt(pro.getProperty("port")));}/*** 獲取連接方法*/public static Jedis getJedis(){return jedisPool.getResource();} }daoImp:
package cn.itcast.dao.impl;import cn.itcast.dao.ProvinceDao; import cn.itcast.domain.Province; import cn.itcast.util.JDBCUtils; import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.JdbcTemplate;import java.util.List;//ProvinceDao 是接口類,自己定義的! public class ProvinceDaoImpl implements ProvinceDao {//1.聲明成員變量 jdbctemplementprivate JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());@Overridepublic List<Province> findAll() {//1.定義sqlString sql = "select * from province ";//2.執行sqlList<Province> list = template.query(sql, new BeanPropertyRowMapper<Province>(Province.class));return list;} }service包下的ProvinceServiceImp:
思路:
1.1獲取redis客戶端連接
2.1從數據中查詢
2.2將list序列化為json
2.3 將json數據存入redis
web包下的servlet
package cn.itcast.web.servlet;import cn.itcast.service.ProvinceService; import cn.itcast.service.impl.ProvinceServiceImpl;import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException;@WebServlet("/provinceServlet") public class ProvinceServlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {/* //1.調用service查詢ProvinceService service = new ProvinceServiceImpl();List<Province> list = service.findAll();//2.序列化list為jsonObjectMapper mapper = new ObjectMapper();String json = mapper.writeValueAsString(list);*///1.調用service查詢ProvinceService service = new ProvinceServiceImpl();String json = service.findAllJson();System.out.println(json);//3.響應結果response.setContentType("application/json;charset=utf-8");response.getWriter().write(json);}@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doPost(request, response);} }- 注意:使用redis緩存一些不經常發生變化的數據。
- 數據庫的數據一旦發生改變,則需要更新緩存。
- 數據庫的表執行 增刪改的相關操作,需要將redis緩存數據情況,再次存入
- 在service對應的增刪改方法中,將redis數據刪除。
- 數據庫的數據一旦發生改變,則需要更新緩存。
?
總結
- 上一篇: PowerCenter Designer
- 下一篇: 网站运作的几个阶段