sadd key element #向集合key新增element(如果element存在,新增失敗) o(1) srem key element #從集合中的element移除掉 o(1) scard key #計算集合大小 sismember key element #判斷element是否在集合中 srandmember key count #從集合中隨機取出count個元素,不會破壞集合中的元素 (抽獎) spop key #從集合中隨機彈出一個元素 smembers key #獲取集合中所有元素 ,無序,小心使用,會阻塞住 sdiff user:1:follow user:2:follow #計算user:1:follow和user:2:follow的差集 sinter user:1:follow user:2:follow #計算user:1:follow和user:2:follow的交集 sunion user:1:follow user:2:follow #計算user:1:follow和user:2:follow的並集 sdiff|sinter|suion + store destkey... #將差集,交集,並集結果儲存在destkey集合中 sdiffstore xxx number1 number2 SUNIONSTORE myset myset1 myset2 ### 總結 ### 實戰 抽獎系統 :透過spop來彈出使用者的id,活動取消,直接刪除 點贊,點踩,喜歡等,使用者如果點了贊,就把使用者id放到該條記錄的集合中 標籤:給使用者/文章等新增標籤,sadd user:1:tags 標籤1 標籤2 標籤3 給標籤新增使用者,關注該標籤的人有哪些 共同好友:集合間的操作 # 總結4 sadd:可以做標籤相關 spop/srandmember:可以做隨機數相關 sadd/sinter:社交相關
#### 特點 有一個分值欄位,來保證順序 key score value user:ranking 1 lqz user:ranking 99 lqz2 user:ranking 88 lqz3 #集合有序集合 集合:無重複元素,無序,element 有序集合:無重複元素,有序,element+score #列表和有序集合 列表:可以重複,有序,element 有序集合:無重複元素,有序,element+score # API使用 zset zadd key score element #score可以重複,可以多個同時新增,element不能重複 o(logN) zrem key element #刪除元素,可以多個同時刪除 o(1) zscore key element #獲取元素的分數 o(1) zincrby key increScore element #增加或減少元素的分數 o(1) zcard key #返回元素總個數 o(1) zrank key element #返回element元素的排名(從小到大排) zrange key 0 -1 #返回排名,不帶分數 o(log(n)+m) n是元素個數,m是要獲取的值 zrange player:rank 0 -1 withscores #返回排名,帶分數 zrangebyscore key minScore maxScore #返回指定分數範圍內的升序元素 o(log(n)+m) n是元素個數,m是要獲取的值 zrangebyscore user:1:ranking 90 210 withscores #獲取90分到210分的元素 zcount key minScore maxScore #返回有序集合內在指定分數範圍內的個數 o(log(n)+m) zremrangebyrank key start end #刪除指定排名內的升序元素 o(log(n)+m) zremrangebyrank user:1:rangking 1 2 #刪除升序排名中1到2的元素 zremrangebyscore key minScore maxScore #刪除指定分數內的升序元素 o(log(n)+m) zremrangebyscore user:1:ranking 90 210 #刪除分數90到210之間的元素 # 其他操作 zrevrank #從高到低排序 zrevrange #從高到低排序取一定範圍 zrevrangebyscore #返回指定分數範圍內的降序元素 zinterstore #對兩個有序集合交集 zunionstore #對兩個有序集合求並集 # 實戰 排行榜:音樂排行榜,銷售榜,關注榜,遊戲排行榜
# MySQL 中的 7 種日誌介紹 # 生命週期 客戶端編寫命令 get name---》透過網路 ---》到服務端---》服務端執行命令【查詢,修改。。】---》返回資料透過網路返回給客戶端 我們配置一個時間,如果查詢時間超過了我們設定的時間,我們就認為這是一個慢查詢. 慢查詢發生在第三階段 客戶端超時不一定慢查詢,但慢查詢是客戶端超時的一個可能因素 # 兩個配置 配置慢查詢 -只要是超過慢查詢時間的命令,都會被記錄 -後期透過記錄分析,哪些命令是慢的,儘量在生成環境中避免 -慢查詢是一個佇列,裡面記錄了,超過你設定時間的命令 - 透過兩個配置: slowlog-log-slower-than 慢於多少微秒的都會被記錄 slowlog-max-len 佇列長度是多少 -配置檔案直接配置 # 設定記錄所有命令 config set slowlog-log-slower-than 0 # 最多記錄100條 config set slowlog-max-len 100 # 持久化到本地配置檔案 config rewrite -檢視慢查詢佇列 slowlog get 100 slowlog len #獲取慢查詢佇列長度 slowlog reset #清空慢查詢佇列 # 總結: 開啟慢查詢記錄後---》只要超過某個時間的命令,都會被記錄到慢查詢佇列中 後期我們可以透過慢查詢佇列中的命令,最佳化程式,提高redis使用效率
# redis 其實不支援事務,但是可以透過pipline來模擬事務,pipline只支援單例項redis,如果做叢集,沒有pipiline # redis 支援事務嗎? 不支援,可以透過pipline實現,但是叢集環境不能用pipline ### python客戶端實現 import redis pool = redis.ConnectionPool(host='10.0.0.111', port=6379) r = redis.Redis(connection_pool=pool) # pipe = r.pipeline(transaction=False) #建立pipeline pipe = r.pipeline(transaction=True) #開啟事務 pipe.multi() pipe.set('name', 'lqz') #其他程式碼,可能出異常 pipe.set('role', 'nb') pipe.execute() ####### 原生redis操作,模擬事務########## # 0 開啟兩個客戶端 # 在第一個客戶端執行 mutil 開啟事務,放到管道中一次性執行 multi # 開啟事務 set name lqz set age 18 exec # 在第二個客戶端去查詢,如果第一個客戶端沒有執行exec ,查詢不到第一個事務未提交的資料 # 隔離級別---》讀已提交級別 ########## 原生redis 透過watch+pipline(multi) 模擬樂觀鎖########## ### 0 開啟兩個客戶端 ### 1 第一個客戶端上 在開啟事務之前,先watch wathc age # 看了一眼,是10 multi decr age # 它有可能被別人操作了 exec # 另一臺機器 multi decr age exec # 先執行,上面的執行就會失敗(樂觀鎖,被wathc的事務不會執行成功) #### 整合到python專案中實現基於redis利用redis的樂觀鎖,實現秒殺系統的資料同步(基於watch實現), import redis from threading import Thread def choose(name, conn): # conn.set('count',10) with conn.pipeline() as pipe: # 先監視,自己的值沒有被修改過 conn.watch('count') # 事務開始 pipe.multi() old_count = conn.get('count') count = int(old_count) # input('我考慮一下') # time.sleep(random.randint(1, 2)) if count > 0: # 有庫存 pipe.set('count', count - 1) # 執行,把所有命令一次性推送過去 ret = pipe.execute() print(ret) if len(ret) > 0: print('第%s個人搶購成功' % name) else: print('第%s個人搶購失敗' % name) if __name__ == '__main__': conn = redis.Redis(host='10.0.0.111', port=6379,password='654321') for i in range(100): t = Thread(target=choose, args=(i, conn)) t.start()
# 釋出者釋出了訊息,所有的訂閱者都可以收到,就是生產者消費者模型(後訂閱了,無法獲取歷史訊息) # 如果是訊息佇列 生產者生產了一條訊息---》只會有一個消費者消費 # 如果是釋出定義---》釋出訂閱---》觀察者模式 生產者生產了一條訊息---》所有訂閱生產者的消費者都會收到訊息 # 實際操作 -釋出者釋出訊息 publish channel01 "hello world" -訂閱者01訂閱頻道 channel01 subscribe channel01 -訂閱者02訂閱頻道 channel01 subscribe channel01 # 實際用途 -只要設計到,一個人發生變化,其他人都收到通知的情況,就可以使用釋出訂閱 -如何用,python? 員工1 ,員工2 關注了 張三 張三傳送一篇文章---》文章儲存到資料庫了---》訊號繫結一個函式--》在函式中釋出訊息 conn.publish('user_zhangsan_new_article','文章id') 啟動一個程式---》等待別人釋出訊息---》只要別人釋出了訊息---》取出頻道--》去mysql檢視哪些員工訂閱了這個頻道---[員工1 ,員工2]--->發郵件通知
# 操作位元位 c i g 01100011 01101001 01100111 set hello big #放入key位hello 值為big的字串 getbit hello 0 #取點陣圖的第0個位置,返回0 getbit hello 1 #取點陣圖的第1個位置,返回1 如上圖 # 我們可以直接操縱位 setbit key offset value #給點陣圖指定索引設定值 setbit hello 7 1 #把hello的第7個位置設為1 這樣,big就變成了cig # 獨立使用者統計---》統計日活---》使用者量足夠大--》節約記憶體 -10億使用者 使用者id1 2 3 10億 -統計日活,只要使用者登入,只要使用者登入,就把使用者id放到集合中 -晚上只需要統計一下 集合大小---》就能統計出日活 -使用集合儲存---》1--》32位--》1億使用者 5千萬左右---》需要 200MB空間 int8個位元位表示範圍 -128--127之間 int16 int32 個位元位表示範圍 -2的31次方---2的31次方 2147483648 -使用點陣圖---》12.5MB空間
基於HyperLogLog演算法:極小的空間完成獨立數量統計,極小記憶體實現去重 pfadd urls "www.baidu.com" "www.cnblogs.com" "www.lqz.com" pfcount urls pfadd urls 值 # 返回0表示在,返回1 表示不在 # 總結 百萬級別獨立使用者統計,百萬條資料只佔15k 錯誤率 0.81% 無法取出單條資料,只能統計個數
# GEO(地理資訊定位):儲存經緯度,計算兩地距離,範圍等 # 經緯度如何獲取? -不是後端做的 -手機端---》手機有定位--》申請了定位---》手機端能拿到經緯度---》提供介面--->提交到後端 -web端---》js獲取經緯度---》提供介面---》提交到後端 # 後端只需要儲存 geoadd key longitude latitude member #增加地理位置資訊 geoadd cities:locations 116.28 39.55 beijing #把北京地理資訊天津到cities:locations中 geoadd cities:locations 117.12 39.08 tianjin geoadd cities:locations 114.29 38.02 shijiazhuang geoadd cities:locations 118.01 39.38 tangshan geoadd cities:locations 115.29 38.51 baoding # 統計兩個經緯度距離 geodist cities:locations beijing baoding km # 統計北京方圓 100公里內的城市 georadiusbymember cities:locations beijing 100 km