- https://blog.csdn.net/heihaozi/article/details/123394487
- https://i6448038.github.io/2019/12/01/redis-data-struct/
- https://www.cnblogs.com/kuangtf/articles/15459957.html
- https://pdai.tech/md/db/nosql-redis/db-redis-x-redis-ds.html
- https://gitee.com/mirrors/redis/tree/unstable/src
- hash 怎么覆蓋數據
---
有個統計頁面的頁面, 數據是存在redis有序集合里, score 是日期, 成員是統計的結果。 現在遇到一個問題, 當天的統計結果需要每隔幾秒要更新一次。 但是有序集合不能根據score去更新成員的值, 需要根據socre找到成員, 然后再刪除成員,再添加回score 和成員。再刪除成員期間,還未添加回更新的值時, 有客戶端查詢的話, 就會少看到一條統計結果, 這要怎么解決?
```
script := `
local zset_key = KEYS[1]
local score = ARGV[1]
local new_member = ARGV[2]
-- 獲取指定 score 的所有成員
local members = redis.call('ZRANGEBYSCORE', zset_key, score, score)
-- 刪除所有這些成員
for i = 1, #members do
redis.call('ZREM', zset_key, members[i])
end
-- 添加新的成員
redis.call('ZADD', zset_key, score, new_member)
return true
`
_, err := g.Redis("cache4").Do("EVAL", script, 1, key, score, m)
```
- 如果需要 `ZRANGEBYSCORE` 返回的結果順序相反,可以使用 `ZREVRANGEBYSCORE` 命令,它會按分數從高到低的順序返回結果。
### 關鍵點
1. **原子性**:Lua 腳本在 Redis 內部執行時是原子操作,這意味著所有命令會連續執行,期間不會被其他操作打斷。
2. **避免不一致性**:通過將 `ZREM` 和 `ZADD` 封裝在同一個腳本中執行,可以避免刪除成員期間有客戶端查詢到不完整數據的情況。
### Lua 腳本的工作流程:
1. 先執行 `ZREM` 刪除舊成員。
2. 然后執行 `ZADD` 添加新成員,確保刪除和添加操作在同一個原子操作中執行。
由于 Lua 腳本執行期間沒有任何其他命令能夠干擾,因此你可以確保沒有其他客戶端會在刪除和重新添加成員的時間點進行查詢,從而避免數據不一致。
---
- 可視化工具: Redis Insight
- Redis Desktop Manager
---
- 刪除一個score
- DoVar("ZRANGEBYSCORE", "ladder:limit_up_count", score, score)
取出對應score的成員
- 刪除成員
- DoVar("ZREM", "ladder:limit_up_count", delSCORE.Maps()[0])
---
- ZRANGEBYSCORE ladder:limit_up_count:1110 (20240911 +inf LIMIT 0 1
- ZREVRANGEBYSCORE ladder:limit_up_count:1110 (20240911 -inf LIMIT 0 1
~~~
data1, err := g.Redis("cache4").DoVar("ZRANGEBYSCORE", "ladder:limit_up_count:"+binaryStr, "+inf", "("+score, "LIMIT", 0, 1)
if err != nil {
return nil, nil, nil, nil, err
}
data2, err := g.Redis("cache4").DoVar("ZREVRANGEBYSCORE", "ladder:limit_up_count:"+binaryStr, score, "-inf", "LIMIT", 0, 11)
if err != nil {
return nil, nil, nil, nil, err
}
~~~
在 Go 中,`float32` 類型的值可以是 `NaN`(Not-a-Number),表示一個未定義或無法表示的數字。這通常會出現在無效的數學操作中,例如:
1. 0 除以 0 (`0/0`)
2. 開平方負數 (`math.Sqrt(-1)`)
3. 對 `NaN` 進行數學操作
### 檢查 `NaN` 的情況
Go 提供了內置函數 `math.IsNaN` 來判斷一個 `float32` 或 `float64` 值是否為 `NaN`。不過,對于 `float32` 你可以先將它轉換為 `float64` 再使用此方法。
### 例子:
~~~
go復制代碼package main
import (
"fmt"
"math"
)
func main() {
// 引發 NaN 的情況
var a float32 = float32(0) / float32(0)
fmt.Println("a:", a)
// 檢查是否是 NaN
if math.IsNaN(float64(a)) {
fmt.Println("a 是 NaN")
} else {
fmt.Println("a 不是 NaN")
}
}
~~~
### 輸出:
~~~
r復制代碼a: NaN
a 是 NaN
~~~
### 觸發 `NaN` 的常見情況:
1. **除以零:**
~~~
go復制代碼var a float32 = 0 / 0
~~~
2. **負數的平方根:**
~~~
go復制代碼var a float32 = float32(math.Sqrt(-1))
~~~
3. **`NaN` 傳播:** 如果你對 `NaN` 進行任何數學操作,結果也會是 `NaN`。比如:
~~~
go復制代碼var a float32 = float32(0) / float32(0)
var b float32 = a + 1 // b 也是 NaN
~~~
請注意,當進行一些無效數學運算時,`NaN` 是一個標準表示,程序本身不會崩潰或拋出異常,但計算結果會產生 `NaN`。
---
---
~~~go
type Person struct {
age int
}
func main() {
person := &Person{28}
// 1.
defer fmt.Println(person.age)
// 2.
defer func(p *Person) {
fmt.Println(p.age)
}(person)
// 3.
defer func() {
fmt.Println(person.age)
}()
person.age = 29
}
~~~
```
### 答案解析:
參考答案及解析:29 29 28。變量 person 是一個指針變量 。
1.person.age 此時是將 28 當做 defer 函數的參數,會把 28 緩存在棧中,等到最后執行該 defer 語句的時候取出,即輸出 28;
2.defer 緩存的是結構體 Person{28} 的地址,最終 Person{28} 的 age 被重新賦值為 29,所以 defer 語句最后執行的時候,依靠緩存的地址取出的 age 便是 29,即輸出 29;
3.很簡單,閉包引用,輸出 29;
又由于 defer 的執行順序為先進后出,即 3 2 1,所以輸出 29 29 28。
```
- 草稿
- Golang
- 切片 slice
- 數組和切片的區別
- 左閉右開
- make([]int, 5) 和 make([]int, 0, 5) 區別
- 切片非線程安全,并發操作為啥不會像map一樣報錯
- []struct{} 如何遍歷
- 切片如何刪除某個元素
- append 一個nil 切片
- 哈希表 map
- 并發操作
- 并發寫報錯
- 并發讀不會報錯
- 并發讀有寫報錯
- 并發迭代有寫報錯
- 自制并發安全字典
- 官方并發安全字典
- 對未初始化的 map 進行賦值操作
- map的底層
- 無序輸出
- 等量擴容
- 實現集合
- map的key可以使哪些值
- 協程 go
- 協程相關閱讀
- 進程、線程、協程
- 協程 (捕獲異常 和 協程池)
- GPM 模型
- CSP模型
- channel
- channel 相關操作
- 交替打印
- 如何讓channel 只能接收/只能發送
- channel 常見報錯
- channel 死鎖
- nil channel 和 已關閉的 channel
- 使用 select 來多路復用 channel
- channel 的使用
- 接口和結構體
- 簡單使用
- 兩個結構體能否比較
- 工廠模式
- 概念
- 簡單工廠
- 方法工廠
- 堆和棧,值類型和引用類型,內存逃逸,垃圾回收
- 棧和堆
- 內存逃逸
- 值類型和引用類型
- 垃圾回收方式
- 性能優化分析工具 pprof
- golang 代碼片段
- 片段一 defer
- 片段二 channel
- Golang 相關
- Golang 相關閱讀
- Golang 1-10
- make 和 new 的區別
- 使用指針的場景
- Go語言的context包
- 位運算
- Copy 是淺拷貝還是深拷貝
- init 函數 和 sync.Once
- select 多路復用
- Golang 其它
- MongoDB
- 可比較類型 與 可轉json 類型
- Gorm
- 面向對象和面向過程
- go語言實現-面向對象
- go語言實現-面向過程
- 限流,熔斷,降級
- 了解
- 熔斷配置
- 熔斷例子
- 服務降級
- github.com/alibaba/sentinel-golang
- 互斥鎖 讀寫鎖 原子鎖
- 為什么需要鎖
- 互斥鎖
- 讀寫鎖
- 原子鎖
- 互斥鎖性能對比
- 原子鎖性能對比
- 互斥鎖 or 原子鎖?
- 條件鎖
- 計數器
- GoFrame
- GF1.16版本
- 修改使用的表
- 按天、周、月、年
- GoFrame 文檔
- 配置文件
- 生成腳本
- 排序算法
- 相關排序
- 冒泡排序
- 選擇排序
- 插入排序
- 快速排序
- 歸并排序
- 堆排序
- 數據庫
- 分布式怎么保證線程安全
- 數據庫實現方式
- 基于表記錄
- 樂觀鎖
- 悲觀鎖
- Redis實現方式
- Zookeeper實現方式
- Mysql 相關
- group_concat
- 索引優化
- 索引優化1
- 定期分析和優化索引
- 覆蓋索引
- 組合索引
- 聚簇索引和非聚簇索引
- 索引類型與方式、聚簇與非聚簇索引
- 事務特征和隔離級別
- 查詢優化
- mysql自增表插入數據時,Id不連續問題
- InnoDB引擎 和 MyISAM引擎區別
- 鎖
- 悲觀鎖和樂觀鎖
- 查詢,更新,插入語句
- 什么是死鎖
- 怎么處理死鎖
- MySQL 隔離級別
- 事務特征
- 隔離級別
- 廢棄3
- 索引
- 索引類型和方式、聚簇和非聚簇索引(上)
- 索引類型和方式、聚簇和非聚簇索引(下)
- 回表、覆蓋索引、最左前綴、聯合索引、索引下推、索引合并
- Mysql 優化
- 索引的原理
- 千萬級表修改表結構
- Redis
- 獲取隨機三條數據
- Redis 持久化方式
- 全量模式 RDB 冷備份(內存快照)
- 增量模式 AOF 熱備份(文件追加)
- 過期key的刪除策略、內存淘汰機制
- 數據結構
- 位圖
- 網絡
- 網絡相關
- 游戲同步方式:幀同步和狀態同步
- Websocket
- OSI模型
- TCP 與 UDP
- 三次握手四次揮手
- Http 狀態碼
- 1xx(信息性狀態碼)
- 101 服務端代碼
- 101 客戶端代碼
- 2xx(成功狀態碼)
- 3xx(重定向狀態碼)
- 302 服務端代碼
- 302 客戶端代碼
- 4xx(客戶端錯誤狀態碼)
- 5xx(服務器錯誤狀態碼)
- 如何排查接口問題
- 網絡請求和響應過程
- time_wait
- keep-alive
- http 和 rpc 的區別
- I/O多路復用 select和poll
- too many open file
- 其它技術
- git 相關操作
- 修改提交備注
- 多個提交合并成一個提交
- 回退版本
- 小程序和公眾號
- 消息模板
- 獲取code
- 靜默登錄
- 其它技術相關
- C盤空間不足
- 生成式人工智能AIGC
- 共享文件
- 接口文檔, mock提供測試數據
- 抓包工具
- Python
- 安裝包失敗
- 自動化測試 Scrapy
- AIGC:人工智能生成內容
- PHP
- xhprof 性能分析
- 一鍵安裝
- 哈希沖突的解決方式
- 鏈地址法(拉鏈法)
- 開放地址法
- 再哈希
- 概念1
- Nginx
- 負載均衡方式
- 加密解密
- 簡單了解
- 簽名算法例子
- 碼例子1
- 代碼例子2
- Linux
- netstat (用于查看和管理網絡連接和路由表)
- ps 用于查看和管理進程
- ab 壓測
- nohup 守護進程
- lsof (List Open File 獲取被進程打開文件的信息)
- tail 查看日志
- 各類linux同步機制
- Socket 服務端的實現,select 和epoll的區別?
- scp 傳輸,awk 是一個強大的文本分析工具
- pidof
- 項目
- 棋牌
- 牌的編碼
- 出牌規則
- 洗牌
- 股票
- 股票知識
- 龍虎榜數據緩存方式
- 單日龍虎榜數據
- 單只股票的歷史上榜
- 遇到的問題
- 浮點數精度問題
- Mysql Sum 精度問題(float, double精度問題)
- 分頁問題(數據重復)
- 工具包
- v3
- common.go
- common_test.go
- customized.go
- customized_test.go
- slice.go
- slice_test.go
- time.go
- time_test.go
- v4
- common.go
- common_test.go
- customized.go
- customized_test.go
- slice.go
- time.go
- time_test.go
- 相關閱讀
- 協程 goroutine
- 通道 channel
- json 和 gob 序列化和反序列化
- redis 有序集合
- mysql22
- 相關閱讀 s
- pyTorch
- defer
- 內存泄漏
- 數據傳輸
- 雜項
- 一提
- gogogoo
- 內容