主頁 >  其他 > Redis 學習筆記

Redis 學習筆記

2021-02-18 10:18:04 其他

Redis 學習筆記

    • NoSQL 概述
    • 什么是NoSQL
    • 阿里巴巴演進分析
    • NoSQL 四大分類
    • Redis 入門
      • Docker 安裝
      • Redis-benchmark 性能測驗工具
      • 基礎知識
    • 五大基本資料型別
      • redis-key
      • String(字串)
      • List(串列)
      • Set(集合)
      • Hash(哈希)
      • Zset(有序集合)
    • 三種特殊資料型別
      • geospatial 地理位置
      • hyperloglogs
      • Bitmaps
    • 事務
      • 編譯型例外
      • 運行時例外
      • 監控
    • Jedis
      • 常用Api
      • 事務
    • redis.conf 詳情
    • Redis 持久化
      • RDB
      • AOF
      • 總結
    • Redis 訂閱發布
      • 命令
    • 主從復制

NoSQL 概述

  1. 單機 MySQL 年代

    1. 資料量太大
    2. 資料索引太大
    3. 訪問量(讀寫混合)過高
    
  2. Memcached(快取)+ MySQL + 垂直拆分(讀寫分離)

發展程序:優化資料結構和索引 -> 檔案快取 -> Memcached

解決 讀 的操作壓力

  1. 分庫分表 + 水平拆分(集群)

解決 寫 的操作壓力

  1. 現在時代

資料量太大,關系型資料庫不夠用

用戶自己產生的資訊,地理位置,博客,視頻等

什么是NoSQL

關系型資料庫:表格,行,列

非關系型資料庫:一些資料不需要固定格式,不需要多余的操作就可以橫向擴展

特點:

  1. 方便擴展,資料之間沒有關系
  2. 大資料量,高性能(Redis 一秒寫8萬次,讀11萬次,是一種細粒度快取,性能比較高)
  3. 資料型別多樣(不需要事先設計資料庫)
  4. 傳統 RDBMS 和 NoSQL
傳統的 RDBMS
    - 結構化組織
  - SQL
  - 資料和關系都存在單獨的表
  - 操作,資料定義語言
  - 嚴格的一致性
  - 基礎的事務
  - ......
NoSQL
    - 不僅僅是資料
  - 沒有固定的查詢語言
  - 鍵值對存盤,列存盤,檔案存盤,圖形資料庫
  - 最終一致性
  - CAP 定理和 BASE(異地多活)初級架構師!
  - 高性能,高可用,高可擴
  - ......

(大資料時代)了解 3V + 3高:

3V 主要描述問題:

  • 海量
  • 多樣
  • 實時

3高 主要描述對程式問題

  • 高并發
  • 高可擴
  • 高性能

阿里巴巴演進分析

推薦書籍:(王堅:阿里云的這群瘋子)

如果未來當一個架構師:沒有什么是加一層解決不了的

# 1. 商品基本資訊
        名稱、價格、商家資訊
    關系型資料庫:MySQL / Oracle (淘寶早年就去IOE(在阿里巴巴的IT架構中,去掉IBM的小型機、Oracle資料庫、EMC存盤設備,代之以自己在開源軟體基礎上開發的系統)!)
    淘寶內部的 MySQL 不是大家用的 MySQL,他根據自己的需求做了相應修改
    
# 2. 商品描述、評論(文字比較多)
        檔案資料庫 MangoDB
    
# 3. 圖片
        分布式檔案系統 FastDFS
    - 淘寶自己的 TFS
    - Google GFS
    - Hadoop HDFS
    - 阿里云 OSS
    
# 4. 商品關鍵詞(搜索)
        - 搜索引擎 solr elasticsearch
    - ISerach 淘寶 多隆
    
# 5. 商品熱門的波段資訊
        - 記憶體資料庫
        - redis tair memache
    
# 6. 商品的交易,外部的支付介面
        - 三方應用

大型互聯網應用問題

  • 資料型別太多
  • 資料源多,經常重構
  • 資料要改造,大面積改造

解決方案:UDSL(統一資料服務平臺)

NoSQL 四大分類

鍵值對

  • 新浪:redis
  • 美團:redis + Tair
  • 阿里、百度:Redis + memecache

檔案資料庫

  • MongoDB

    • 是一個基于分布式檔案存盤的資料庫,c++撰寫,主要用來處理大量檔案!
    • 是一個介于關系型資料庫和非關系型資料庫之間的中間產品,MongoDB是關系型資料庫中功能最豐富,最像關系型資料庫的

圖關系資料庫

  • 放的是關系,如:朋友圈社交網路,廣告推薦等

列存盤資料庫

  • Hbase
  • 分布式檔案系統

Redis 入門

什么是 Redis

遠程字典服務(Remote Dictionary Server)

是一個由 Salvatore Sanfilippo 寫的 key-value 存盤系統,是跨平臺的非關系型資料庫,

Redis 是一個開源的使用 ANSI C 語言撰寫、遵守 BSD 協議、支持網路、可基于記憶體、分布式、可選持久性的鍵值對(Key-Value)存盤資料庫,并提供多種語言的 API,

Redis 通常被稱為資料結構服務器,因為值(value)可以是字串(String)、哈希(Hash)、串列(list)、集合(sets)和有序集合(sorted sets)等型別

能干什么

記憶體存盤、持久化、記憶體中斷電即失,所以持久化很重要(RDB、AOF)

發布訂閱系統

地圖資訊分析

計數器,計時器

特性

多樣化資料型別

持久化

集群

官網:http://www.redis.cn/

Docker 安裝

  1. 創建外部掛載目錄:
mkdir -p /root/docker/redis/data
mkdir -p /root/docker/redis/conf
  1. 下載 redis.conf 組態檔到 conf 目錄下,后給檔案授權
wget http://download.redis.io/redis-stable/redis.conf
chmod 777 redis.conf
  1. 修改配置資訊
bind 127.0.0.1 通過#注釋掉,解除本地連接限制
protected-mode yes 默認no,保護模式,限制為本地訪問,修改后解除保護模式
daemonize yes 注釋掉
appendonly yes 持久化
requirepass 123456 密碼
  1. 啟動命令
docker run -p 6379:6379 -v /root/docker/redis/data:/data -v /root/docker/redis/conf/redis.conf:/etc/redis/redis.conf --name myredis -d redis redis-server /etc/redis/redis.conf --appendonly yes --requirepass 123456

# 命令決議
    -p 6379:6379    埠映射
  --name myredis 指定容器名稱
  -d redis 后臺啟動
  --appendonly yes 開啟持久化
  --requirepass 123456 設定密碼
  -v /root/docker/redis/data:/data 
  -v /root/docker/redis/conf/redis.conf:/etc/redis/redis.conf --name myredis  資料卷映射

進入容器

# docker exec -it myredis bash
# redis-cli
127.0.0.1>auth 123456   // 認證用戶,不然無法使用

Redis-benchmark 性能測驗工具

# 命令
redis-benchmark -h localhost -p 6379 -c 100 -n 100000
# 運行結果
====== SET ======
  100000 requests completed in 3.12 seconds  // 10萬個請求在3.12秒內完成
  100 parallel clients  // 100 個并發客戶端
  3 bytes payload  // 每次寫入3個位元組
  keep alive: 1  // 只有一臺服務器來處理這些請求,單機性能
  multi-thread: no

0.09% <= 1 milliseconds
99.54% <= 2 milliseconds
99.86% <= 3 milliseconds
99.96% <= 4 milliseconds
100.00% <= 4 milliseconds
32061.56 requests per second  // 每秒處理3萬2千請求

基礎知識

默認有16個資料庫 在組態檔中 database 關鍵字中配置

  1. 切換資料庫
127.0.0.1:6379> select 3   // 切換資料庫
OK
127.0.0.1:6379[3]>DBSIZE   // 回傳當前資料庫內 keys 數量
(integer) 0
127.0.0.1:6379[3]> set name 'xiong' // 添加鍵值
OK
127.0.0.1:6379[3]> get name  // 根據 key 查詢 value
"xiong"
127.0.0.1:6379[3]> DBSIZE
(integer) 1
127.0.0.1:6379[3]> keys *  // 查看所有鍵
1) "name"
127.0.0.1:6379[3]>flushdb  // 清空本資料庫
127.0.0.1:6379[3]>flushall // 清空所有資料庫
  1. redis 是單執行緒的

redis 基于記憶體操作,CPU 不是 redis 性能瓶頸,reids 的瓶頸為機器記憶體和網路帶寬

redis 為單執行緒還這么快?

誤區1:高性能服務器一定是多執行緒

誤區2:多執行緒(CPU背景關系切換)一定比單執行緒效率高

CPU > 記憶體 > 硬碟

核心:redis 是將所有的資料放在記憶體中,所以說使用單執行緒操作是效率最高的,多執行緒(CPU背景關系切換)耗時間,對于記憶體來說沒有背景關系切換效率就是最高的!多次讀寫都是在一個CPU上

五大基本資料型別

Redis 是一個開源(BSD許可)的,記憶體中的資料結構存盤系統,它可以用作資料庫、快取和訊息中間件, 它支持多種型別的資料結構,如 字串(strings), 散列(hashes), 串列(lists), 集合(sets), 有序集合(sorted sets) 與范圍查詢, bitmaps, hyperloglogs 和 地理空間(geospatial) 索引半徑查詢, Redis 內置了 復制(replication),LUA腳本(Lua scripting), LRU驅動事件(LRU eviction),事務(transactions) 和不同級別的 磁盤持久化(persistence), 并通過 Redis哨兵(Sentinel)和自動 磁區(Cluster)提供高可用性(high availability),

redis-key

基礎命令:http://www.redis.cn/commands.html

判斷是否存在exists name
移除一個鍵move name 1 (1 代表當前資料庫)
設定過期時間expire name 10 (設定為10s 過期)
查看當前資料型別type name

String(字串)

追加字符append key ‘hello’ (如果key不存在,則新建)
獲取資料長度strlen key 查看資料長度
自增1incr view
自減1decr view
setex // 設定過期時間setex name 30 ‘xiong’ (30 秒后過期)
setnx // 不存在再設定setnx name ‘xiong’ (如果存在,不設定,不存在就設定)
mset // 設定多個值mset k1 v1 k2 v2
mget // 獲取多個值mget k1 k2
getsetgetset name redis # 如果不存在值,則回傳 nil;如果存在,則回傳原來的值再修改
設定物件set user:1:{name:zhang,age:3} // 設定一個user:1 物件值為 json 字串mset user:1:name zhang user:1:age:3 // 批量設定的方法

使用場景:

  • 計數器 (博客瀏覽量等)
  • 統計多單位的數量
  • 粉絲數
  • 物件快取存盤!

List(串列)

基本資料型別:串列

在 Redis 內可以實作:堆疊、佇列

127.0.0.1:6379> lpush list one  // 向串列內插入值(頭部插入,類似堆疊)
(integer) 1
127.0.0.1:6379> lpush list two 
(integer) 2
127.0.0.1:6379> lrange list 0 -1  // 獲取指定范圍內的值
1) "two"
2) "one"
127.0.0.1:6379> rpush list three  // 向右插入(尾部插入)
(integer) 3
127.0.0.1:6379> lrange list 0 -1
1) "two"
2) "one"
3) "three"
==================================================
pop # 移除操作 
127.0.0.1:6379> lpop list   // 移除頭部的值
"two"
127.0.0.1:6379> lrange list 0 -1
1) "one"
2) "three"
127.0.0.1:6379> rpop list   // 移除尾部的值
"three"
127.0.0.1:6379> lrange list 0 -1
1) "one"
===================================================
lindex # 獲取下標某個值
127.0.0.1:6379> lindex list 1
"two"
==================================================
# 獲取長度 llen
127.0.0.1:6379> llen list
(integer) 3
==================================================
lrem # 移除指定個數的 value 
127.0.0.1:6379> lrem list 1 one  # lrem key count value
(integer) 1
==================================================
ltrim # 截取范圍內的值 
127.0.0.1:6379> rpush mylist 'hello'
(integer) 1
127.0.0.1:6379> rpush mylist 'hello1'
(integer) 2
127.0.0.1:6379> rpush mylist 'hello2'
(integer) 3
127.0.0.1:6379> rpush mylist 'hello3'
(integer) 4
127.0.0.1:6379> lrange mylist 0 -1
1) "hello"
2) "hello1"
3) "hello2"
4) "hello3"
127.0.0.1:6379> ltrim mylist 1 2    # ltrim mylist start end
OK
127.0.0.1:6379> lrange mylist 0 -1
1) "hello1"
2) "hello2"
======================================================
rpoplpush # 移除最后一個元素并保存到其他串列  
127.0.0.1:6379> rpush list 'hello' 'hello1' 'hello2' 'hello3'
(integer) 4
127.0.0.1:6379> rpoplpush list otherlist
"hello3"
127.0.0.1:6379> lrange list 0 -1
1) "hello"
2) "hello1"
3) "hello2"
127.0.0.1:6379> lrange otherlist 0 -1
1) "hello3"
========================================================
lset # 修改串列內的值 (不存在的值會報錯)
127.0.0.1:6379> rpush list 'hello'
(integer) 1
127.0.0.1:6379> lrange list 0 -1
1) "hello"
127.0.0.1:6379> lset list 0 'item'  # lset key index element
OK
127.0.0.1:6379> lrange list 0 -1
1) "item"
=========================================================
linsert # 插入一個值,定位為串列中的 value
127.0.0.1:6379> linsert list before item 'new'  # 向前插入
(integer) 2
127.0.0.1:6379> lrange list 0 -1
1) "new"
2) "item"
127.0.0.1:6379> linsert list after item 'new' # 向后插入
(integer) 3
127.0.0.1:6379> lrange list 0 -1
1) "new"
2) "item"
3) "new"

小結

  • 實際上是一個鏈表,before Node after,left right 都可以插入值
  • 如果key 不存在,創建新的鏈表
  • 如果key 存在,新增內容
  • 如果移除所有值,空鏈表,也代表不存在
  • 兩邊插入或者改動值,效率最高!中間元素效率相對較低

Set(集合)

set 中的值不能重復

127.0.0.1:6379> sadd myset 'hello' 'xiong' 'love'   # 向集合中添加值
(integer) 3
127.0.0.1:6379> SMEMBERS set
(empty array)
127.0.0.1:6379> SMEMBERS myset      # 查看集合中所有值
1) "xiong"
2) "hello"
3) "love"
127.0.0.1:6379> SISMEMBER myset xiong  # 判斷一個值是否在集合中
(integer) 1
127.0.0.1:6379> SISMEMBER myset love
(integer) 1
127.0.0.1:6379> SISMEMBER myset world
(integer) 0
========================================================
scard # 獲取集合中元素個數
127.0.0.1:6379> scard myset
(integer) 3
========================================================
srem # 移除某個值
127.0.0.1:6379> srem myset xiong
(integer) 1
127.0.0.1:6379> SMEMBERS myset
1) "hello"
2) "love"
========================================================
SRANDMEMBER # 隨機抽選一個值
127.0.0.1:6379> SRANDMEMBER myset    # SRANDMEMBER set count
"love"
127.0.0.1:6379> SRANDMEMBER myset
"hello"
========================================================
spop # 隨機洗掉一個元素
127.0.0.1:6379> spop myset # spop set count
"love"
========================================================
# sdiff # 求取差集
========================================================
sinter # 求取交集
========================================================
sunion # 求取并集

用途:

  • 微博,B站的 共同關注 (交集)

Hash(哈希)

Map 集合,key-Map ,本質和 string 沒有區別

127.0.0.1:6379> hset myhash filed1 xionog       # 存值
(integer) 1
127.0.0.1:6379> hget myhash filed1      # 取值
"xionog"
========================================================
取值
hmget   # 獲取多個
hgetall # 獲取全部
========================================================
洗掉
hdel
========================================================
hlen # 獲取 hash 表的欄位數量
========================================================
hexists # 判斷 hash 表的欄位是否存在
========================================================
hkeys # 獲取 hash 表的所有值

應用

  • 更適合物件的存盤

Zset(有序集合)

在 set 的基礎上,增加了一個值

127.0.0.1:6379> zadd myset 1 one    # 添加一個值 zadd key score value
(integer) 1
127.0.0.1:6379> zadd myset 2 two
(integer) 1
127.0.0.1:6379> zadd myset 3 three
(integer) 1
127.0.0.1:6379> ZRANGE myset 0 -1  # 查看值
1) "one"
2) "two"
3) "three"
========================================================
ZRANGEBYSCORE # 排序
127.0.0.1:6379> zadd saraly 300 xiong 200 xin 400 qiang
(integer) 3
127.0.0.1:6379> zrange saraly 0 -1
1) "xin"
2) "xiong"
3) "qiang"
127.0.0.1:6379> ZRANGEBYSCORE saraly -inf +inf withscores  # 排序,只能從小到大,在設定值的時候就已經排好序了
1) "xin"
2) "200"
3) "xiong"
4) "300"
5) "qiang"
6) "400"
127.0.0.1:6379> zrevrange saraly 0 -1  # 排序從大到小
1) "qiang"
2) "xiong"
3) "xin"
========================================================
zrem # 移除元素
========================================================
zcard # 獲取集合中元素個數
========================================================
zcount # 獲取指定區間內的元素個數

應用

  • 存盤班級程式表
  • 普通訊息和重要訊息區分,按權重進行判斷
  • 排行榜實作

三種特殊資料型別

geospatial 地理位置

朋友的定位,附近的人,打車距離計算

redis 的 Geo 在 Redis 3.2 版本就推出了,可以推算地理位置資訊

測驗資料連接:http://www.jsons.cn/lngcode/

相關命令:http://www.redis.cn/commands/geoadd.html

  • GEOADD
  • GEODIST
  • GEOHASH
  • GEOPOS
  • GEORADIUS
  • GEORADIUSBYMEMBER
geoadd # 添加地理位置 (兩級-南極北極,無法直接添加)
127.0.0.1:6379> geoadd china:city 116.40 39.90 beijin
(integer) 1
127.0.0.1:6379> geoadd china:city 121.47 31.23 shanghai
(integer) 1
127.0.0.1:6379> geoadd china:city 106.50 29.53 chongqing 114.05 22.52 shengzheng
(integer) 2
========================================================
由EPSG:900913 / EPSG:3785 / OSGEO:41001 規定如下:
有效的經度從-180度到180度
有效的緯度從-85.05112878度到85.05112878度
========================================================
GEODIST key member1 member2
回傳兩個給定位置之間的距離,
如果兩個位置之間的其中一個不存在, 那么命令回傳空值,
指定單位的引數 unit 必須是以下單位的其中一個:
    - m 表示單位為米,
    - km 表示單位為千米,
    - mi 表示單位為英里,
    - ft 表示單位為英尺,
如果用戶沒有顯式地指定單位引數, 那么 GEODIST 默認使用米作為單位,
GEODIST 命令在計算距離時會假設地球為完美的球形, 在極限情況下, 這一假設最大會造成 0.5% 的誤差,
127.0.0.1:6379> geodist china:city shanghai beijin
"1067378.7564"
========================================================
GEOPOS key member [member ...]
從key里回傳所有給定位置元素的位置(經度和緯度),
給定一個sorted set表示的空間索引,密集使用 geoadd 命令,它以獲得指定成員的坐標往往是有益的,當空間索引填充通過 geoadd 的坐標轉換成一個52位Geohash,
所以回傳的坐標可能不完全以添加元素的,但小的錯誤可能會出臺,
因為 GEOPOS 命令接受可變數量的位置元素作為輸入, 所以即使用戶只給定了一個位置元素, 命令也會回傳陣列回復,
========================================================
GEORADIUS key longitude latitude radius m|km|ft|mi
以給定的經緯度為中心, 回傳鍵包含的位置元素當中, 與中心的距離不超過給定最大距離的所有位置元素,

案例,獲取附近的人:
127.0.0.1:6379> georadius china:city 110 30 500 km
1) "chongqing"
127.0.0.1:6379> georadius china:city 110 30 500 km withcoord  # 查詢他人的經緯度
1) 1) "chongqing"
   2) 1) "106.49999767541885376"
      2) "29.52999957900659211"
127.0.0.1:6379> georadius china:city 110 30 500 km withdist # 查詢顯示到中心距離的位置
1) 1) "chongqing"
   2) "341.9374"
========================================================
GEORADIUSBYMEMBER key member radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count]
GEORADIUSBYMEMBER 的中心點是由給定的位置元素決定的, 而不是像 GEORADIUS 那樣, 使用輸入的經度和緯度來決定中心點指定成員的位置被用作查詢的中心

127.0.0.1:6379> GEORADIUSBYMEMBER china:city shanghai 1000 km
1) "shanghai"
========================================================
GEOHASH key member [member ...]
該命令回傳11個字符的字串
127.0.0.1:6379> geohash china:city shanghai chongqing
1) "wtw3sj5zbj0"
2) "wm5xzrybty0"
# 將二維經緯度轉換為一維字串,如果兩個字串越接近,則距離越近

GEO 底層為 zset 集合所以可以用 zset 命令

hyperloglogs

什么是基數:

一個集合中不重復元素的個數

優點:占用的記憶體是固定的,2^64 不同的元素基數,只需要廢12kb記憶體!如果要從記憶體角度來比驕傲的話 hyperloglog 首選

應用:網頁的 UV (一個人訪問一個網站多次,訪問量為1)

傳統方式:使用 set 集合儲存用戶id,然后統計 set 集合中的元素個數作為標準判斷

127.0.0.1:6379> pfadd mykey a b c d e f g h i j  # 添加元素
(integer) 1
127.0.0.1:6379> pfcount mykey       # 統計基數個數
(integer) 10
127.0.0.1:6379> pfadd mykey2 i j a l n m e c x
(integer) 1
127.0.0.1:6379> pfmerge mykey3 mykey mykey2  # 合并兩個集合,并集
OK
127.0.0.1:6379> pfcount mykey3
(integer) 14

如果允許容錯,則使用 hyperloglog,出錯率為 0.81%

Bitmaps

位存盤(只有 0 和 1)都是操作二進制為來進行記錄,就只有0和1兩個狀態

應用:

統計用戶資訊:活躍,不活躍;登陸,未登錄;打卡

127.0.0.1:6379> setbit sign 0 1  # 存值
(integer) 0
127.0.0.1:6379> setbit sign 1 0
(integer) 0
127.0.0.1:6379> setbit sign 2 0
(integer) 0
127.0.0.1:6379> setbit sign 3 0
(integer) 0
127.0.0.1:6379> setbit sign 4 1
(integer) 0
127.0.0.1:6379> getbit sign 3       # 取值
(integer) 0
127.0.0.1:6379> bitcount sign   # 統計
(integer) 2

事務

Redis 單條命令保證原子性,但是事務不保證原子性!

本質: 一組命令的集合!一個事務中的所有命令都會被序列化,在事務執行程序中,按順序執行

所有命令在事務中,并沒有直接被執行!只有發起執行命令的時候才會執行!

Redis 事務

  • 開啟事務
  • 命令入隊
  • 執行事務
127.0.0.1:6379> multi               # 開啟事務
OK
127.0.0.1:6379> set k1 v1       # 命令入隊
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> set k3 v3
QUEUED
127.0.0.1:6379> get k2
QUEUED
127.0.0.1:6379> exec                # 執行事務
1) OK
2) OK
3) OK
4) "v2"
=============================================================
127.0.0.1:6379> multi               # 開啟事務
OK
127.0.0.1:6379> set k4 v4
QUEUED
127.0.0.1:6379> discard         # 取消事務
OK
127.0.0.1:6379> get k4          # 事務佇列中的命令不會執行
(nil)
127.0.0.1:6379>

編譯型例外

代碼有問題,命令有錯誤

127.0.0.1:6379> multi
OK
127.0.0.1:6379> set k1 v1
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> set k3 v3
QUEUED
127.0.0.1:6379> getset k3
(error) ERR wrong number of arguments for 'getset' command
127.0.0.1:6379> set k4 v4
QUEUED
127.0.0.1:6379> exec
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> get k4
(nil)
127.0.0.1:6379> get k2
(nil)

命令都不會運行,整個事務都取消

運行時例外

語法型問題,其他命令正常執行,錯誤出拋出例外

127.0.0.1:6379> multi
OK
127.0.0.1:6379> set k1 v1
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> incr k1
QUEUED
127.0.0.1:6379> set k3 v3
QUEUED
127.0.0.1:6379> exec
1) OK
2) OK
3) (error) ERR value is not an integer or out of range
4) OK

監控

悲觀鎖

  • 很悲觀,什么時候都會出問題,無論做什么都加鎖

樂觀鎖

  • 很樂觀,什么時候都不會出問題,所以不會上鎖!更新資料的時候去判斷一下,在此期間是否有人修改過這個資料
  • 獲取 version
  • 更新的時候比較 version

Redis 監控測驗

127.0.0.1:6379> set money 100
OK
127.0.0.1:6379> set out 0
OK
127.0.0.1:6379> watch money             # 監視 money 物件
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> DECRBY money 20
QUEUED
127.0.0.1:6379> INCRBY out 20
QUEUED
127.0.0.1:6379> exec        # 正常執行  成功后監控會自動取消
1) (integer) 80
2) (integer) 20
=============================================================
# 測驗多執行緒修改值,使用 watch 可以當作 reids 的樂觀鎖操作
127.0.0.1:6379> watch money
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> DECRBY money 10
QUEUED
127.0.0.1:6379> INCRBY out 10
QUEUED
                # 另一主機連接并修改監控的值后
        127.0.0.1:6379> get money
        "80"
        127.0.0.1:6379> set money 1000
        OK
127.0.0.1:6379> exec        # 監視失敗,事務取消
(nil)

失敗后的步驟

  1. 放棄監視 unwatch
  2. 重新監視 watch key
  3. 事務執行是比對監視的值是否變化,如果沒有變化則執行,如果有變化則放棄監視,重新監視執行

Jedis

是官方推薦的 java 連接開發工具!使用 java 操作的Redis 中間件!

構建專案:

創建一個空專案:

構建 maven 專案 -> 修改:

image.pngimage.png

匯入對應依賴

<dependency>
  <groupId>redis.clients</groupId>
  <artifactId>jedis</artifactId>
  <version>3.3.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
  <groupId>com.alibaba</groupId>
  <artifactId>fastjson</artifactId>
  <version>1.2.68</version>
</dependency>

測驗連接

public class TestPing {
    public static void main(String[] args) {
        // 1. new jedis 物件
        Jedis jedis = new Jedis("ip",6379);
        // 認證
        jedis.auth("123456");
        // 測驗連接
        System.out.println(jedis.ping());
        jedis.close(); // 關閉連接
    }
}

常用Api

與常用基礎型別的命令基本同,特殊型別也相同,只不過換成了方法

事務

public class TestPing {
    public static void main(String[] args) {
        // 1. new jedis 物件
        Jedis jedis = new Jedis("159.75.113.81",6379);
        // 認證
        jedis.auth("123456");

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("hello","world");
        jsonObject.put("name","xiong");
        // 開啟事務
        Transaction multi = jedis.multi();
        String result = jsonObject.toJSONString();

        try {
            multi.set("user1", result);
            multi.set("user2", result);

            multi.exec();  // 執行事務
        } catch (Exception e) {
            multi.discard();  // 出例外放棄事務
        } finally {
            System.out.println(jedis.get("user1"));
            System.out.println(jedis.get("user2"));
            jedis.close();  // 關閉連接
        }
    }
}

輸出:
{"name":"xiong","hello":"world"}
{"name":"xiong","hello":"world"}

redis.conf 詳情

組態檔對大小寫不敏感

網路配置:

bind 127.0.0.1      # 系結 ip
protected-mode no       # 保護模式
port 6379                       # 埠號

通用配置:

# By default Redis does not run as a daemon. Use 'yes' if you need it.
# Note that Redis will write a pid file in /var/run/redis.pid when daemonized.
daemonize yes  # 以守護行程方式運行,默認是 no 

pidfile /var/run/redis_6379.pid # 如果以后臺方式運行,我們就需要指定一個 pid 檔案

日志級別:
# Specify the server verbosity level.
# This can be one of:
# debug (a lot of information, useful for development/testing)
# verbose (many rarely useful info, but not a mess like the debug level)
# notice (moderately verbose, what you want in production probably)
# warning (only very important / critical messages are logged)
loglevel notice

logfile ""  # 日志保存檔案名,如果為空,則為輸出

databases 16 # 資料庫數量
======================================================================================
快照  (持久化使用)
    在規定時間內,執行了多少次操作,則會持久化到檔案 rdb aof
  如果沒有持久化,則 redis 斷電會丟失資料
#   save <seconds> <changes>
#
#   Will save the DB if both the given number of seconds and the given
#   number of write operations against the DB occurred.
#
#   In the example below the behavior will be to save:
#   after 900 sec (15 min) if at least 1 key changed
#   after 300 sec (5 min) if at least 10 keys changed
#   after 60 sec if at least 10000 keys changed
#
#   Note: you can disable saving completely by commenting out all "save" lines.
#
#   It is also possible to remove all the previously configured save
#   points by adding a save directive with a single empty string argument
#   like in the following example:
#
#   save ""
save 900 1 # 如果900 秒內有一個 key 值改變就進行持久化操作
save 300 10 # 如果300 秒內有 10 個 key 值改變就進行持久化操作
save 60 10000 # 如果 60 秒內,有 10000 個 key 值改變就進行持久化操作

stop-writes-on-bgsave-error yes # 持久化出錯,是否繼續作業

rdbchecksum yes     # 保存壓縮rdb 檔案的時候,進行錯誤校驗

rdbcompression yes # 是否壓縮 rdb 檔案,需要消耗 cpu 資源

dir ./ # rdb 檔案保存路徑

主從復制:

安全:

requirepass 123456      # 設定密碼,默認沒有
=========================================
通過命令設定密碼:
127.0.0.1:6379> config set requirepass "123456"
獲取密碼
127.0.0.1:6379> config get requirepass

客戶端限制:

maxclients 10000        # 設定能連接的redis 最大客戶端數量
maxmemory <bytes>       # redis 配置最大的記憶體

# volatile-lru -> Evict using approximated LRU, only keys with an expire set.
# allkeys-lru -> Evict any key using approximated LRU.
    # volatile-lfu -> Evict using approximated LFU, only keys with an expire set.       只對設定了過時間的key 進行lru(默認值)
    # allkeys-lfu -> Evict any key using approximated LFU.                                                  洗掉lru 演算法的key
    # volatile-random -> Remove a random key having an expire set.                                  隨機洗掉即將過期的key
    # allkeys-random -> Remove a random key, any key.                                                               隨機洗掉key
    # volatile-ttl -> Remove the key with the nearest expire time (minor TTL)               洗掉即將過期的key
    # noeviction -> Don't evict anything, just return an error on write operations. 永不過期,報錯
#
# LRU means Least Recently Used
# LFU means Least Frequently Used
#
# Both LRU, LFU and volatile-ttl are implemented using approximated
# randomized algorithms.
#
# Note: with any of the above policies, Redis will return an error on write
#       operations, when there are no suitable keys for eviction.
#
#       At the date of writing these commands are: set setnx setex append
#       incr decr rpush lpush rpushx lpushx linsert lset rpoplpush sadd
#       sinter sinterstore sunion sunionstore sdiff sdiffstore zadd zincrby
#       zunionstore zinterstore hset hsetnx hmset hincrby incrby decrby
#       getset mset msetnx exec sort
#
# The default is:
#
# maxmemory-policy noeviction  # 記憶體滿后的策略

AOF 配置:

appendonly yes  # 默認為 no,默認使用 rdb 方式持久化,在大部分情況下, rdb 完全夠用

# The name of the append only file (default: "appendonly.aof")

appendfilename "appendonly.aof" # 檔案名
自動持久化方式:
# appendfsync always        # 每次修改都追加同步,消耗性能
appendfsync everysec        # 每秒一次
# appendfsync no                # 系統自動同步資料,不追加同步,速度最快

Redis 持久化

RDB

持久化操作流程圖:

img

rdb 保存檔案為 dump.rdb(在bin 檔案夾中)該檔案是一個壓縮過的二進制檔案,可以通過該檔案還原快照時的資料庫狀態,即生成該RDB檔案時的服務器資料

有時候在生產環境中會進行備份

觸發規則:

  1. save 規則(組態檔中寫的)情況下自動觸發保存
  2. 執行savebgsave命令

執行savebgsave命令,可以手動觸發快照,生成RDB檔案,兩者的區別如下

使用save命令會阻塞Redis服務器行程,服務器行程在RDB檔案創建完成之前是不能處理任何的命令請求

127.0.0.1:6379> save
OK
復制代碼

而使用bgsave命令不同的是,bgsave命令會fork一個子行程,然后該子行程會負責創建RDB檔案,而服務器行程會繼續處理命令請求

127.0.0.1:6379> bgsave
Background saving started
  1. 執行 flushall 命令,也會觸發保存
  2. 退出 redis,也會觸發保存

恢復:

  1. 只需要將 rdb 檔案放在 redis 啟動目錄就可以,redis 啟動時會自動檢查 dump.rdb 并恢復其中資料!
  2. 查看需要存在的位置 config get dir

優點

  • RDB快照是一個壓縮過的非常緊湊的檔案,保存著某個時間點的資料集,適合做資料的備份,災難恢復
  • 可以最大化Redis的性能,在保存RDB檔案,服務器行程只需fork一個子行程來完成RDB檔案的創建,父行程不需要做IO操作
  • 與AOF相比,恢復大資料集的時候會更快

缺點

  • RDB的資料安全性是不如AOF的,保存整個資料集的程序是比繁重的,根據配置可能要幾分鐘才快照一次,如果服務器宕機,那么就可能丟失幾分鐘的資料
  • Redis資料集較大時,fork的子行程要完成快斬訓比較耗CPU、耗時

AOF

將我們的所有命令都記錄下來(在大量資料時效率很慢)

開啟:將 appendonly 改為 yes

如果 AOF 檔案超過 64mb ,會 fork 一個新的行程來將我們的檔案進行重寫

image.png

觸發保存規則時會將所寫入的命令記錄進 appendonly.aof 檔案中

如果 aof 檔案有錯誤,redis 就無法啟動

可以通過 redis-check-aof --fix appendonly.aof 進行修復(通過洗掉錯誤命令進行修復)

優點:

  • 資料更完整,安全性更高,秒級資料丟失(取決fsync策略,如果是everysec,最多丟失1秒的資料)
  • AOF檔案是一個只進行追加的日志檔案,且寫入操作是以Redis協議的格式保存的,內容是可讀的,適合誤刪緊急恢復

缺點:

  • 對于相同的資料集,AOF檔案的體積要大于RDB檔案,資料恢復也會比較慢
  • 根據所使用的 fsync 策略,AOF 的速度可能會慢于 RDB, 不過在一般情況下, 每秒 fsync 的性能依然非常高

總結

  • 如果是資料不那么敏感,且可以從其他地方重新生成補回的,那么可以關閉持久化
  • 如果是資料比較重要,不想再從其他地方獲取,且可以承受數分鐘的資料丟失,比如快取等,那么可以只使用RDB
  • 如果是用做記憶體資料庫,要使用Redis的持久化,建議是RDB和AOF都開啟,或者定期執行bgsave做快照備份,RDB方式更適合做資料的備份,AOF可以保證資料的不丟失

Redis 訂閱發布

Redis 發布訂閱(pub/sub)是一種訊息通信模式:發送者(pub)發送訊息,訂閱者(sub)接收訊息

Redis 客戶端可以訂閱任意適量的頻道

訊息發布圖

img

測驗:

127.0.0.1:6379> subscribe xiongxinq     // 訂閱頻道
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "xiongxinq"
3) (integer) 1
        # 第二個客戶端
    127.0.0.1:6379> publish xiongxinq "hello wirld"     // 向指定頻道發送訊息
    (integer) 1
    127.0.0.1:6379>
1) "message"
2) "xiongxinq"
3) "hello wirld"

命令

1[PSUBSCRIBE pattern pattern …] 訂閱一個或多個符合給定模式的頻道,
2[PUBSUB subcommand argument [argument …]] 查看訂閱與發布系統狀態,
3PUBLISH channel message 將資訊發送到指定的頻道,
4[PUNSUBSCRIBE pattern [pattern …]] 退訂所有給定模式的頻道,
5[SUBSCRIBE channel channel …] 訂閱給定的一個或多個頻道的資訊,
6[UNSUBSCRIBE channel [channel …]] 指退訂給定的頻道,

原理 Redis 使用 c 實作的們可以通過 pubsub.c 檔案了解

使用場景:

  • 實時訊息系統
  • 實時聊天(聊天室)
  • 訂閱、關注系統

稍微復雜的場景會使用訊息中間件

主從復制

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/260542.html

標籤:其他

上一篇:【vim】你的背包里,缺不缺一份vim簡明教程嘞?

下一篇:Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:2.7:resources

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 網閘典型架構簡述

    網閘架構一般分為兩種:三主機的三系統架構網閘和雙主機的2+1架構網閘。 三主機架構分別為內端機、外端機和仲裁機。三機無論從軟體和硬體上均各自獨立。首先從硬體上來看,三機都用各自獨立的主板、記憶體及存盤設備。從軟體上來看,三機有各自獨立的作業系統。這樣能達到完全的三機獨立。對于“2+1”系統,“2”分為 ......

    uj5u.com 2020-09-10 02:00:44 more
  • 如何從xshell上傳檔案到centos linux虛擬機里

    如何從xshell上傳檔案到centos linux虛擬機里及:虛擬機CentOs下執行 yum -y install lrzsz命令,出現錯誤:鏡像無法找到軟體包 前言 一、安裝lrzsz步驟 二、上傳檔案 三、遇到的問題及解決方案 總結 前言 提示:其實很簡單,往虛擬機上安裝一個上傳檔案的工具 ......

    uj5u.com 2020-09-10 02:00:47 more
  • 一、SQLMAP入門

    一、SQLMAP入門 1、判斷是否存在注入 sqlmap.py -u 網址/id=1 id=1不可缺少。當注入點后面的引數大于兩個時。需要加雙引號, sqlmap.py -u "網址/id=1&uid=1" 2、判斷文本中的請求是否存在注入 從文本中加載http請求,SQLMAP可以從一個文本檔案中 ......

    uj5u.com 2020-09-10 02:00:50 more
  • Metasploit 簡單使用教程

    metasploit 簡單使用教程 浩先生, 2020-08-28 16:18:25 分類專欄: kail 網路安全 linux 文章標簽: linux資訊安全 編輯 著作權 metasploit 使用教程 前言 一、Metasploit是什么? 二、準備作業 三、具體步驟 前言 Msfconsole ......

    uj5u.com 2020-09-10 02:00:53 more
  • 游戲逆向之驅動層與用戶層通訊

    驅動層代碼: #pragma once #include <ntifs.h> #define add_code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) /* 更多游戲逆向視頻www.yxfzedu.com ......

    uj5u.com 2020-09-10 02:00:56 more
  • 北斗電力時鐘(北斗授時服務器)讓網路資料更精準

    北斗電力時鐘(北斗授時服務器)讓網路資料更精準 北斗電力時鐘(北斗授時服務器)讓網路資料更精準 京準電子科技官微——ahjzsz 近幾年,資訊技術的得了快速發展,互聯網在逐漸普及,其在人們生活和生產中都得到了廣泛應用,并且取得了不錯的應用效果。計算機網路資訊在電力系統中的應用,一方面使電力系統的運行 ......

    uj5u.com 2020-09-10 02:01:03 more
  • 【CTF】CTFHub 技能樹 彩蛋 writeup

    ?碎碎念 CTFHub:https://www.ctfhub.com/ 筆者入門CTF時時剛開始刷的是bugku的舊平臺,后來才有了CTFHub。 感覺不論是網頁UI設計,還是題目質量,賽事跟蹤,工具軟體都做得很不錯。 而且因為獨到的金幣制度的確讓人有一種想去刷題賺金幣的感覺。 個人還是非常喜歡這個 ......

    uj5u.com 2020-09-10 02:04:05 more
  • 02windows基礎操作

    我學到了一下幾點 Windows系統目錄結構與滲透的作用 常見Windows的服務詳解 Windows埠詳解 常用的Windows注冊表詳解 hacker DOS命令詳解(net user / type /md /rd/ dir /cd /net use copy、批處理 等) 利用dos命令制作 ......

    uj5u.com 2020-09-10 02:04:18 more
  • 03.Linux基礎操作

    我學到了以下幾點 01Linux系統介紹02系統安裝,密碼啊破解03Linux常用命令04LAMP 01LINUX windows: win03 8 12 16 19 配置不繁瑣 Linux:redhat,centos(紅帽社區版),Ubuntu server,suse unix:金融機構,證券,銀 ......

    uj5u.com 2020-09-10 02:04:30 more
  • 05HTML

    01HTML介紹 02頭部標簽講解03基礎標簽講解04表單標簽講解 HTML前段語言 js1.了解代碼2.根據代碼 懂得挖掘漏洞 (POST注入/XSS漏洞上傳)3.黑帽seo 白帽seo 客戶網站被黑帽植入劫持代碼如何處理4.熟悉html表單 <html><head><title>TDK標題,描述 ......

    uj5u.com 2020-09-10 02:04:36 more
最新发布
  • 2023年最新微信小程式抓包教程

    01 開門見山 隔一個月發一篇文章,不過分。 首先回顧一下《微信系結手機號資料庫被脫庫事件》,我也是第一時間得知了這個訊息,然后跟蹤了整件事情的經過。下面是這起事件的相關截圖以及近日流出的一萬條資料樣本: 個人認為這件事也沒什么,還不如關注一下之前45億快遞資料查詢渠道疑似在近日復活的訊息。 訊息是 ......

    uj5u.com 2023-04-20 08:48:24 more
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:47:46 more
  • vulnhub_Earth

    前言 靶機地址->>>vulnhub_Earth 攻擊機ip:192.168.20.121 靶機ip:192.168.20.122 參考文章 https://www.cnblogs.com/Jing-X/archive/2022/04/03/16097695.html https://www.cnb ......

    uj5u.com 2023-04-20 07:46:20 more
  • 從4k到42k,軟體測驗工程師的漲薪史,給我看哭了

    清明節一過,盲猜大家已經無心上班,在數著日子準備過五一,但一想到銀行卡里的余額……瞬間心情就不美麗了。最近,2023年高校畢業生就業調查顯示,本科畢業月平均起薪為5825元。調查一出,便有很多同學表示自己又被平均了。看著這一資料,不免讓人想到前不久中國青年報的一項調查:近六成大學生認為畢業10年內會 ......

    uj5u.com 2023-04-20 07:44:00 more
  • 最新版本 Stable Diffusion 開源 AI 繪畫工具之中文自動提詞篇

    🎈 標簽生成器 由于輸入正向提示詞 prompt 和反向提示詞 negative prompt 都是使用英文,所以對學習母語的我們非常不友好 使用網址:https://tinygeeker.github.io/p/ai-prompt-generator 這個網址是為了讓大家在使用 AI 繪畫的時候 ......

    uj5u.com 2023-04-20 07:43:36 more
  • 漫談前端自動化測驗演進之路及測驗工具分析

    隨著前端技術的不斷發展和應用程式的日益復雜,前端自動化測驗也在不斷演進。隨著 Web 應用程式變得越來越復雜,自動化測驗的需求也越來越高。如今,自動化測驗已經成為 Web 應用程式開發程序中不可或缺的一部分,它們可以幫助開發人員更快地發現和修復錯誤,提高應用程式的性能和可靠性。 ......

    uj5u.com 2023-04-20 07:43:16 more
  • CANN開發實踐:4個DVPP記憶體問題的典型案例解讀

    摘要:由于DVPP媒體資料處理功能對存放輸入、輸出資料的記憶體有更高的要求(例如,記憶體首地址128位元組對齊),因此需呼叫專用的記憶體申請介面,那么本期就分享幾個關于DVPP記憶體問題的典型案例,并給出原因分析及解決方法。 本文分享自華為云社區《FAQ_DVPP記憶體問題案例》,作者:昇騰CANN。 DVPP ......

    uj5u.com 2023-04-20 07:43:03 more
  • msf學習

    msf學習 以kali自帶的msf為例 一、msf核心模塊與功能 msf模塊都放在/usr/share/metasploit-framework/modules目錄下 1、auxiliary 輔助模塊,輔助滲透(埠掃描、登錄密碼爆破、漏洞驗證等) 2、encoders 編碼器模塊,主要包含各種編碼 ......

    uj5u.com 2023-04-20 07:42:59 more
  • Halcon軟體安裝與界面簡介

    1. 下載Halcon17版本到到本地 2. 雙擊安裝包后 3. 步驟如下 1.2 Halcon軟體安裝 界面分為四大塊 1. Halcon的五個助手 1) 影像采集助手:與相機連接,設定相機引數,采集影像 2) 標定助手:九點標定或是其它的標定,生成標定檔案及內參外參,可以將像素單位轉換為長度單位 ......

    uj5u.com 2023-04-20 07:42:17 more
  • 在MacOS下使用Unity3D開發游戲

    第一次發博客,先發一下我的游戲開發環境吧。 去年2月份買了一臺MacBookPro2021 M1pro(以下簡稱mbp),這一年來一直在用mbp開發游戲。我大致分享一下我的開發工具以及使用體驗。 1、Unity 官網鏈接: https://unity.cn/releases 我一般使用的Apple ......

    uj5u.com 2023-04-20 07:40:19 more