您好,登錄后才能下訂單哦!
本篇內容介紹了“Redis分布式緩存與秒殺怎么實現”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
1、數據丟失問題
Redis數據持久化。
2、并發能力問題
大家主從集群,實現讀寫分離。
3、故障恢復問題
利用Redis哨兵,實現健康檢測和自動恢復。
4、存儲能力問題
搭建分片集群,利用插槽機制實現動態擴容。
RDB全稱Redis Database Backup file(Redis數據備份文件),也被叫做Redis數據快照。簡單來說就是把內存中的所有數據都記錄到磁盤中。當Redis實例故障重啟后,從磁盤讀取快照文件,恢復數據。
快照文件稱為RDB文件,默認是保存在當前運行目錄。
Redis內部有觸發RDB的機制,可以在redis.conf文件中找到,格式如下:
bgsave開始時會fork主進程得到子進程,子進程共享主進程的內存數據。完成fork后讀取內存數據并寫入 RDB 文件。
fork采用的是copy-on-write技術:
當主進程執行讀操作時,訪問共享內存;
當主進程執行寫操作時,則會拷貝一份數據,執行寫操作;
RDB方式bgsave的基本流程?
fork主進程得到一個子進程,共享內存空間;
子進程讀取內存數據并寫入新的RDB文件;
用新RDB文件替換舊的RDB文件;
RDB會在什么時候執行?save 60 1000代表什么含義?
默認是服務停止時;
代表60秒內至少執行1000次修改則觸發RDB;
RDB的缺點?
RDB執行間隔時間長,兩次RDB之間寫入數據有丟失的風險;
fork子進程、壓縮、寫出RDB文件都比較耗時;
AOF的命令記錄的頻率也可以通過redis.conf文件來配:
AOF全稱為Append Only File(追加文件)。Redis處理的每一個寫命令都會記錄在AOF文件,可以看做是命令日志文件。
AOF默認是關閉的,需要修改redis.conf配置文件來開啟AOF:
AOF的命令記錄的頻率也可以通過redis.conf文件來配:
配置項 | 刷盤時機 | 優點 | 缺點 |
---|---|---|---|
Always | 同步刷盤 | 可靠性高,幾乎不丟數據 | 性能影響大 |
everysec | 每秒刷盤 | 性能適中 | 最多丟失一分鐘的數據 |
no | 操作系統控制 | 性能最好 | 可靠性較差,可能丟失大量數據 |
因為是記錄命令,AOF文件會比RDB文件大的多。而且AOF會記錄對同一個key的多次寫操作,但只有最后一次寫操作才有意義。通過執行bgrewriteaof命令,可以讓AOF文件執行重寫功能,用最少的命令達到相同效果。
set id 1 set name nezha set id 2 bgrewriteaof mset name nezha id 2
Redis也會在觸發閾值時自動去重寫AOF文件。閾值也可以在redis.conf中配置:
# AOF文件比上次文件 增長超過多少百分比則觸發重寫auto-aof-rewrite-percentage 100# AOF文件體積最小多大以上才觸發重寫 auto-aof-rewrite-min-size 64mb
RDB和AOF各有自己的優缺點,如果對數據安全性要求較高,在實際開發中往往會結合兩者來使用。
RDB | AOF | |
---|---|---|
持久化方式 | 定時對整個內存做快照 | 記錄每一次執行的命令 |
數據完整性 | 不完整,兩次備份之間會丟失 | 相對完整,取決于刷盤策略 |
文件大小 | 會有壓縮,文件體積小 | 記錄命令,文件體積很大 |
宕機恢復速度 | 很快 | 慢 |
數據恢復優先級 | 低,因為數據完整性不低 | 高,因為數據完整性更高 |
系統資源占用 | 高,大量CPU和內存消耗 | 低,主要是磁盤IO資源,但AOF重寫時會占用大量CPU和內存資源 |
使用場景 | 可以容忍數分鐘的數據丟失,追求更快的啟動速度 | 對數據安全性要求較高常見 |
查詢優惠券;
判斷秒殺商品庫存;
查詢訂單
校驗一人一單;
減庫存;
創建訂單;
新增秒殺的優惠券,將優惠券信息保存到Redis中;
基于Lua腳本,判斷秒殺商品庫存,一人一單,決定用戶是否秒殺成功;
如果秒殺成功,將優惠券id、用戶id、商品id封裝到阻塞隊列中;
開啟異步任務,不斷從阻塞隊列中讀取信息,實現異步下單功能;
public Result seckillVoucher(Long voucherId) { Long userId = UserHolder.getUser().getId(); long orderId = redisIdWorker.nextId("order"); // 1.執行lua腳本 Long result = stringRedisTemplate.execute( SECKILL_SCRIPT, Collections.emptyList(), voucherId.toString(), userId.toString(), String.valueOf(orderId) ); int r = result.intValue(); // 2.判斷結果是否為0 if (r != 0) { // 2.1.不為0 ,代表沒有購買資格 return Result.fail(r == 1 ? "庫存不足" : "不能重復下單"); } // 3.返回訂單id return Result.ok(orderId); }
// 線程池 private static final ExecutorService SECKILL_ORDER_EXECUTOR = Executors.newSingleThreadExecutor(); /** * 在類初始化完成后執行 */ @PostConstruct private void init() { SECKILL_ORDER_EXECUTOR.submit(new VoucherOrderHandler()); } // 阻塞隊列 private BlockingQueue<VoucherOrder> orderTasks = new ArrayBlockingQueue<>(1024 * 1024); private class OrderHandler implements Runnable{ @Override public void run() { while (true){ try { doSomething(); } catch (Exception e) { log.error("處理訂單異常", e); } } } }
基于Redis實現共享session登錄
public class RefreshTokenInterceptor implements HandlerInterceptor { private StringRedisTemplate stringRedisTemplate; public RefreshTokenInterceptor(StringRedisTemplate stringRedisTemplate) { this.stringRedisTemplate = stringRedisTemplate; } @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 1、獲取請求頭中的token String token = request.getHeader("authorization"); if (StrUtil.isBlank(token)) { return true; } // 2、基于TOKEN獲取redis中的用戶 String key = LOGIN_USER_KEY + token; Map<Object, Object> userMap = stringRedisTemplate.opsForHash().entries(key); // 3、判斷用戶是否存在 if (userMap.isEmpty()) { return true; } // 5、將查詢到的hash數據轉為UserDTO UserDTO userDTO = BeanUtil.fillBeanWithMap(userMap, new UserDTO(), false); // 6、存在,保存用戶信息到 ThreadLocal UserHolder.saveUser(userDTO); // 7、刷新token有效期 stringRedisTemplate.expire(key, LOGIN_USER_TTL, TimeUnit.MINUTES); // 8、放行 return true; } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { // 移除用戶 UserHolder.removeUser(); } }
“Redis分布式緩存與秒殺怎么實現”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。