阿里官方 Redis 开发规范
本文主要介绍在使用阿里云 Redis 的开发规范,从下面几个方面进行说明。
键值设计 命令使用 客户端使用 相关工具
一、键值设计
1、key 名设计
可读性和可管理性
ugc:video:1
简洁性
user:{uid}:friends:messages:{mid}简化为u:{uid}:fr:m:{mid}。
不要包含特殊字符
2、value 设计
拒绝 bigkey
选择适合的数据类型
set user:1:name tom
set user:1:age 19
set user:1:favor football
hmset user:1 name tom age 19 favor football
控制 key 的生命周期
二、命令使用
1、O(N) 命令关注 N 的数量
2、禁用命令
3、合理使用 select
4、使用批量操作提高效率
原生命令:例如 mget、mset。 非原生命令:可以使用 pipeline 提高效率。
原生是原子操作,pipeline 是非原子操作。 pipeline 可以打包不同的命令,原生做不到 pipeline 需要客户端和服务端同时支持。
5、不建议过多使用 Redis 事务功能
6、Redis 集群版本在使用 Lua 上有特殊要求
7、monitor 命令
三、客户端使用
1、避免多个应用使用一个 Redis 实例
2、使用连接池
执行命令如下:
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
//具体的命令
jedis.executeCommand()
} catch (Exception e) {
logger.error("op key {} error: " + e.getMessage(), key, e);
} finally {
//注意这里不是关闭连接,在JedisPool模式下,Jedis会被归还给资源池。
if (jedis != null)
jedis.close();
}
3、熔断功能
4、合理的加密
5、淘汰策略
allkeys-lru:根据 LRU 算法删除键,不管数据有没有设置超时属性,直到腾出足够空间为止。 allkeys-random:随机删除所有键,直到腾出足够空间为止。 volatile-random: 随机删除过期键,直到腾出足够空间为止。 volatile-ttl:根据键值对象的 ttl 属性,删除最近将要过期数据。如果没有,回退到 noeviction 策略。 noeviction:不会剔除任何数据,拒绝所有写入操作并返回客户端错误信息 "(error) OOM command not allowed when used memory",此时 Redis 只响应读操作。
四、相关工具
1、数据同步
2、big key 搜索
3、热点 key 寻找
五、删除 bigkey
下面操作可以使用 pipeline 加速。 redis 4.0 已经支持 key 的异步删除,欢迎使用。
1、Hash 删除: hscan + hdel
public void delBigHash(String host, int port, String password, String bigHashKey) {
Jedis jedis = new Jedis(host, port);
if (password != null && !"".equals(password)) {
jedis.auth(password);
}
ScanParams scanParams = new ScanParams().count(100);
String cursor = "0";
do {
ScanResult<Entry<String, String>> scanResult = jedis.hscan(bigHashKey, cursor, scanParams);
List<Entry<String, String>> entryList = scanResult.getResult();
if (entryList != null && !entryList.isEmpty()) {
for (Entry<String, String> entry : entryList) {
jedis.hdel(bigHashKey, entry.getKey());
}
}
cursor = scanResult.getStringCursor();
} while (!"0".equals(cursor));
//删除bigkey
jedis.del(bigHashKey);
}
2、List 删除: ltrim
public void delBigList(String host, int port, String password, String bigListKey) {
Jedis jedis = new Jedis(host, port);
if (password != null && !"".equals(password)) {
jedis.auth(password);
}
long llen = jedis.llen(bigListKey);
int counter = 0;
int left = 100;
while (counter < llen) {
//每次从左侧截掉100个
jedis.ltrim(bigListKey, left, llen);
counter += left;
}
//最终删除key
jedis.del(bigListKey);
}
3、Set 删除: sscan + srem
public void delBigSet(String host, int port, String password, String bigSetKey) {
Jedis jedis = new Jedis(host, port);
if (password != null && !"".equals(password)) {
jedis.auth(password);
}
ScanParams scanParams = new ScanParams().count(100);
String cursor = "0";
do {
ScanResult<String> scanResult = jedis.sscan(bigSetKey, cursor, scanParams);
List<String> memberList = scanResult.getResult();
if (memberList != null && !memberList.isEmpty()) {
for (String member : memberList) {
jedis.srem(bigSetKey, member);
}
}
cursor = scanResult.getStringCursor();
} while (!"0".equals(cursor));
//删除bigkey
jedis.del(bigSetKey);
}
4、SortedSet 删除: zscan + zrem
public void delBigZset(String host, int port, String password, String bigZsetKey) {
Jedis jedis = new Jedis(host, port);
if (password != null && !"".equals(password)) {
jedis.auth(password);
}
ScanParams scanParams = new ScanParams().count(100);
String cursor = "0";
do {
ScanResult<Tuple> scanResult = jedis.zscan(bigZsetKey, cursor, scanParams);
List<Tuple> tupleList = scanResult.getResult();
if (tupleList != null && !tupleList.isEmpty()) {
for (Tuple tuple : tupleList) {
jedis.zrem(bigZsetKey, tuple.getElement());
}
}
cursor = scanResult.getStringCursor();
} while (!"0".equals(cursor));
//删除bigkey
jedis.del(bigZsetKey);
}
胖虎联合一线大厂朋友花费8个月的时间,录制了一份Java入门+进阶视频教程
课程特色:
总共88G,时常高达365小时,覆盖所有主流技术栈
均为同一人录制,不是东拼西凑的
对标线下T0级别的培训课,讲师大厂架构师,多年授课经验,通俗易懂
内容丰富,每一个技术点除了视频,还有课堂源码、笔记、PPT、图解
五大实战项目(视频+源码+笔记+SQL+软件)
一次付费,持续更新,永无二次费用
点击下方超链接查看详情(或者点击文末阅读原文):
评论