# redis
> something redis is not a good choice, something redis is just ok, but redis is so easy
關于持久化和數據查詢的相關技術 -> 關系型數據庫再也不是放之四海皆準 -> 圍繞數據的解決方案不可能再只有唯一一種
redis: 容易學習; 在處理一組特定的問題集的同時能保持相當的通用性 -> 什么是可行的,什么是不應該由Redis來處理的
- [try redis](http://try.redis.io/)
- [the little redis book](https://github.com/JasonLai256/the-little-redis-book/blob/master/cn/redis.md)
- [redis.cn](http://www.redis.cn/documentation.html): 文檔/月報
- [Redis的數據類型——探究竟](https://mp.weixin.qq.com/s/Jve5RPYsSBsMtK1Lqo66Sg)
- [aliyun redis 開發規范](https://yq.aliyun.com/articles/531067)
- [redis的陳年往事](https://mp.weixin.qq.com/s/8-GxH4_WjoRe8DwFlk3qNw)
- [redis過期及逐出策略](https://help.aliyun.com/knowledge_detail/55892.html)
- [redis重要知識點](https://github.com/Weiwf/redis-mindmap)
## 最佳實踐
- key命名: `業務:子業務:id` -> 可讀/簡潔/不含轉義字符
- 過期時間
- 高危操作: flushdb flushall keys monitor
- 加鎖: 1 == redis->incr(key)
- 游戲玩家積分排行版: zset
- 網上商城商品相關性分析: 為每種商品構建一個有序集合 -> score 為商品同時出現的次數
- pub/sub: 消息「非持久」 pub非獨占 sub獨占阻塞
- 數據集成(Data Integration): mysql -> redis
- 熱點: client -> slb -> proxy(讀寫分離, 本地緩存->熱點數據+技術) -> master(write) - slave(backup) - read
- 用戶關注列表: hash uid-uid-value
- 評論游標分頁: zset(id-timestamp) + hash(comment-id-content)
- redis 內存分析: pip install rdbtools + sqlite
- 秒殺: 秒殺前-商品詳情頁-瀏覽器緩存/CDN -> 秒殺開始-redis讀寫分離/數據(flag/all/donebooked) -> 庫存-hash(all/booked)/lua腳本原子性 -> 落庫-list
- 大量key操作: scan 分批 找到索引邊界 批量(hmset pipeline)
- redis所有請求對不存在的key都有輸出返回, 比如 ttl -2 -> 減少不必要的請求
- 避免value過大: 1k-性能拐點 MTU-1.5k
## base 入門
```
# key-value
set key value # 常使用 : 作為key的分隔符
get key
setnx key # set if not exist
incr key # incr 并發安全
del key
expire / expireat / ttl / persist # 過期, ttl->time to live
strlen getrange append # string類型的value
# list
lpush/rpush list value..
lpop/rpop list
llen list
lrange list 0 -1 # 查看所有
ltrim list 0 -1 # 只留下范圍內的值, 其他刪除
lindex/lset # 通過索引獲取值/通過索引設置值
# set
sadd set value
srem set value # remove
sismember set value
smembers set
sunion s1 s2
sinter s1 s2 # 是否有共同元素
sinterstore s1 s2 s3 # 存儲共同元素
# sorted set
zadd set score value # score is float number
zrange set 0 -1
zcount z s1 s2 # 按照 score 進行 count
zrank / zrevzank # 升序/降序
# hash
hset h field value
hmset h f1 v1 f2 v2 ...
hget h f
hgetall h
hincrby h f num # increment to a num value
hdel h f
# HyperLogLog
pfadd key v1 v2
pfcount key
pfmerge new key1 key2
# pub/sub
subscribe / unsubscribe # 訂閱
psubscribe # 模式匹配訂閱
publish channel value
blpop / brpop / blpush / brpush
# pipeline: 批量操作
# eval + lua
eval code
script load / evalsha # 加載腳本后返回 sha1 值, 通過 sha1 值執行腳本
# transaction
multi
...do something
exec / discard # 非嚴格意義上事務->操作失敗/discard->不回滾
watch / unwatch # CAS 樂觀鎖
# more
redis-cli --raw # 中文亂碼
redis-benchmark # 類似 ab 1w~10w/s
redis-server # 啟動時沒有指定 conf, redis將采用默認配置
config set slowlog-log-slower-than 0 # 修改配置
auth # 密碼驗證
info # 查看服務器狀態
select 1 # 切換db, 默認為0, 默認有 16 個
type key # 查看 key 的數據類型
scan 0 match * count 10 # 使用 scan 替代 keys/smembers等會一次性掃描所有記錄的命令; scan 返回2個值, 第一個值為游標
flushdb / flushall # 高危命令
setbit / getbit # 今天我們有多少個獨立用戶訪問 -> 2個命令/1.28億/50ms/16m
monitor # 監控
slowlog # 慢日志
slowlog get
slowlog get 10
sort # list/set/hash -> 基于bug嚴重級別的排序 / 大數據量雙維度排序
# redis-cli 數據備份
bgsave # RDB
redis-cli -h old_instance_ip -p old_instance_port config set appendonly yes
redis-cli -h aliyun_redis_instance_ip -p 6379 -a password --pipe < appendonly.aof
```
- key & value: key的數據為標量, value可為任意數據類型(序列化)
- Big O Notation: 許多Redis命令都具有O(1)的時間復雜度; `O(1) -> O(log(N)) -> O(N)`; N 不一定是記錄總數; 發現一些操作具有O(N)的時間復雜度時 -> 可能可以找到更為好的方法去處理
- Memory and Persistence(3種方式): snapshot append-only slaveDB
- Replication(復制): 配置 `slaveof` -> master-slave; 沒有提供自動故障恢復
- backup(備份): Redis會把快照存儲為一個名為`dump.rdb`的文件
- Scaling and Redis Cluster(縮放/集群)