redis入門
- Redis是一款基于鍵值對的NoSQL數(shù)據(jù)庫,它的值支持多種數(shù)據(jù)結構:
字符串(strings)、哈希(hashes)、列表(lists)、集合(sets)、有序集合(sorted sets)等。 - Redis將所有的數(shù)據(jù)都存放在內(nèi)存中,所以它的讀寫性能十分驚人。
同時,Redis還可以將內(nèi)存中的數(shù)據(jù)以快照或日志的形式保存到硬盤上,以保證數(shù)據(jù)的安全性。 - Redis典型的應用場景包括:緩存、排行榜、計數(shù)器、社交網(wǎng)絡、消息隊列等。
快照(RDB):優(yōu)點直接把內(nèi)存數(shù)據(jù)原原本本存,恢復數(shù)據(jù)速度塊。缺點是存硬盤耗時,存儲會阻塞,會影響業(yè)務性能。不適合實時去做,適合幾個小時做備份。
日志(aof):每執(zhí)行redis命令,就把命令存下來,追加形式,占磁盤空間,恢復的話,是把命令從頭到尾跑一遍,恢復速度比較慢,實時性好。
https://redis.io
https://github.com/microsoftarchive/redis
redis命令
- 內(nèi)置16個庫通過索引區(qū)分,通過下面代碼即可切換庫
select 0
select 15
- 刷新庫清空庫的數(shù)據(jù)
flushdb
- string類型
set key value
set test:count 1 //兩個單詞相連,中間用冒號,后面可以加超時時間等是可選的
get test:count //取到字符串
incr test:count //字符串值加一 increment
decr test:count //decrement 字符串值減一
4 hash類型
hset key field value
hset test:user id 1
hset test:user username zhangsan
hget test:user id
hget test:user username
- list列表,左右都可以添加和取出
lpush test:ids 101 102 103 //左進
llen test:ids //得到數(shù)據(jù)長度
lindex test:ids 0 //103 查到索引為0的值,
lrange test:ids 0 2 // 查到從0開始到2 的索引的值
rpop test:ids //101右側出隊一個值
- set集合 無序且唯一
sadd key number
sadd test:teachers aaa bbb ccc ddd eee //集合加入數(shù)據(jù)
scard test:teachers //統(tǒng)計集合元素個數(shù)
spop test:teachers // 集合中隨機彈出一個元素 ,可以實現(xiàn)抽獎功能
smembers test:teachers //查詢集合中的元素
- sortedset 有序集合 按照分數(shù)排序的功能
zadd test:students 10 aaa 20 bbb 30 ccc 40 ddd 50 eee //數(shù)字代表緊跟后面的成員分數(shù),按照這個分數(shù)給集合從小到大排序
zcard test:students //統(tǒng)計集合元素個數(shù)
zscore test:students ccc // 查詢某個元素的分數(shù)
zrank test:students ccc //2 返回某個元素的排名
zrange test:students 0 2 //取范圍的值,從小到大取三個
- 全局命令
keys * //查詢庫里的key
keys test* //查詢test開頭的key
type test:user //查詢某個key的數(shù)據(jù)類型
exists test:user // 1 表示存在 0 不存在 是否存在key
del test:user // 刪除key
expire test:students 10 //key 10秒過期
Spring整合redis
- 引入依賴
spring-boot-starter-data-redis - 配置Redis
配置數(shù)據(jù)庫參數(shù)
編寫配置類,構造RedisTemplate - 訪問Redis
redisTemplate.opsForValue()
redisTemplate.opsForHash()
redisTemplate.opsForList()
redisTemplate.opsForSet()
redisTemplate.opsForZSet()
- 導入包
-
配置參數(shù)
image.png - 定義RedisConfig
返回RedisTemplate對象,需要把RedisConnectionFactory注入進來才能創(chuàng)建連接
調(diào)用(setConnectionFactory())
spring會把這個參數(shù)自動注入進來,
然后指定數(shù)據(jù)轉(zhuǎn)換的方式,有工具類RedisSerializer
- 設置key的序列化方式,序列成string
- 設置value的序列化方式,可以序列成json
- 設置hash的key的序列化方式
-
設置hash的value的序列化方式
把這些設置生效(調(diào)用afterPropertiesSet())
image.png
- 用法,創(chuàng)建測試實例
簡化方案,不用每次都傳rediskey參數(shù)
通過BoundxxxOperations綁定key參數(shù)xxx表示參數(shù)類型。這樣就省略了這個參數(shù)。
image.png - redis事務
不完全滿足ACID這四個事務
開啟事務后,執(zhí)行redis命令會放到隊列里存起來,提交事務的時候,會把這些命令一起批量執(zhí)行。
注意事項:
不要在事務中查詢,這樣是查不到的。要在開啟事務之前或之后查詢
所以因為這個特性,在spring中最好不要用聲明式事務,而是用編程式事務。
public void testTransactional(){
Object obj = redisTemplate.execute(new SessionCallback(){
@Override
public Object execute(RedisOperations operations) throws DataAccessException{
String redisKey = "test:tx;
operations.multi(); //開啟事務
operations.opsForSet().add(redisKey, "zhangsan);
sout(operations.opsForSet.members(redisKey)); //[] 因為事務中間不要查詢,得不到結果
return operations.exec(); //關閉事務并返回結果
}
});
sout(obj); // [1, [zhangsan]] 返回的結果是很全的。
}
點贊功能

-
考慮復用,給rediskey復用
比如點贊,我們需要實現(xiàn)點贊的數(shù)量,但是如果我們擴展功能要找到點贊的人,那麼我們就不要直接存儲點贊的數(shù)量,而是存id這樣就能最大限度擴展功能。
image.png -
LikeService
點贊方法:要判斷是否點過贊,沒點過才能點,點過就取消
查詢贊數(shù)量:
查詢某人對某實體的點贊狀態(tài):返回int而不是boolean是因為未來可能會擴展,比如點個彩。具備擴展性
image.png
image.png -
LikeController
用戶權限問題以后會用Spring的安全來管理,所以不用判斷了
image.png -
異步請求 discuss-detail.html
把href屏蔽掉,like里面?zhèn)魅齻€參數(shù),this entitytype entityid, this是未了區(qū)分是在哪點的贊,好動態(tài)某一個位置的贊修改。同時要把贊和數(shù)字用標簽進行包裹以便于動態(tài)修改
image.png
回帖列表和回復里都有贊
-
單獨創(chuàng)建js文件 discuss.js
image.png 把首頁和顯示的贊的數(shù)量修改
顯示的時候贊的狀態(tài)要根用戶相關,因為,這個頁面不登錄也能看到,所以不登錄的話可能匯報空指針異常。
我收到的贊

-
修改我們rediskey
image.png -
LikeService
點贊重構
image.png
統(tǒng)計某個用戶獲得的贊,統(tǒng)計的不是本用戶的id而是傳進來的id
image.png - 表現(xiàn)層重構
- congroller 和discuss-detail三個點贊的參數(shù)傳遞方法
-
個人主頁和別人主頁
image.png
修改index.html profile路徑,剩下的自己完善
關注和取消關注
- 需求
開發(fā)關注、取消關注功能。
統(tǒng)計用戶的關注數(shù)、粉絲數(shù)。 - 關鍵
若A關注了B,則A是B的Follower(粉絲),B是A的Followee(目標)。
關注的目標可以是用戶、帖子、題目等,在實現(xiàn)時將這些目標抽象為實體。




在service和controller中補充關注數(shù)量,粉絲數(shù)量,當前用戶是否已經(jīng)關注。并且如果當前用戶不存在,直接返回false;


頁面顯示
不可以自己關注自己,而且不登錄不顯示

顏色顯示

關注列表和粉絲列表
- 業(yè)務層
查詢某個用戶關注的人,支持分頁。
查詢某個用戶的粉絲,支持分頁。 - 表現(xiàn)層
處理“查詢關注的人”、“查詢粉絲”請求。
編寫“查詢關注的人”、“查詢粉絲”模板。
關注時間倒序
-
Followservice
重點是設計返回數(shù)據(jù)的數(shù)據(jù)結構
以及時間倒序(最近時間優(yōu)先)的獲得方式。
List<Map<String, Object>>
image.png
粉絲和上面的基本相同。
-
FollowController
image.png
粉絲和上面基本相同
- 處理followee和followerhtml頁面
優(yōu)化登錄模塊
- 使用Redis存儲驗證碼
驗證碼需要頻繁的訪問與刷新,對性能要求較高。
驗證碼不需永久保存,通常在很短的時間后就會失效。
分布式部署時,存在Session共享的問題。 - 使用Redis存儲登錄憑證
處理每次請求時,都要查詢用戶的登錄憑證,訪問的頻率非常高。 - 使用Redis緩存用戶信息
處理每次請求時,都要根據(jù)憑證查詢用戶信息,訪問的頻率非常高。
驗證碼優(yōu)化
- 定義驗證碼key
因為登錄要標識登錄的用戶是誰,但是此時沒法標識,所以我們用生成的隨機字符串來標識,并把這個字符串通過cookie短暫的保存, -
LoginController
把存入session的驗證碼去掉
生成隨機字符串,并用cookie保存。并設置生存時間60秒,和路徑。驗證碼存入redis
image.png
在登錄具體驗證的時候要用
判斷cookie是否存在,存在從redis取值,不存在則返回驗證碼不正確
使用redis存儲登錄憑證
不要刪除永久保存,將來出個功能,對于登錄的次數(shù)天數(shù)等需要用到。
- 定義ticket的key;
- 把LoginTicketMapper定義@Deprecated
-
UserService
把LoginTicket對象存進去
image.png
修改logout方法
image.png
修改findLoginTicket方法
image.png
緩存用戶信息功能
重構UserService 的findUserById方法
先取緩存,取不到則取mysql的,如果用戶信息改變,有兩種方法,
- 修改緩存內(nèi)容,
- 直接刪除緩存。
第一種麻煩,還會可能遇到并發(fā)的問題。
- 步驟
- 定義key
- 優(yōu)先從緩存中取值
- 取不到時初始化緩存數(shù)據(jù)
- 數(shù)據(jù)變更時刪除緩存
后三個封裝成方法在UserService

- 修改findUserById
首先從catch查,如果沒有則初始化,
8.清理緩存的地方
激活的時候activation把緩存清理
updateHeader清理緩存,要更新后再清理


















