抛弃时间的人,时间也抛弃他。——莎士比亚
1.文档阅读
判断Redis有序集合中是否存在某个成员的方法
08 | 数据库优化方案(一):查询请求增加时,如何做主从分离?-极客时间
2.整理输出 2.1 判断Redis有序集合中是否存在某个成员的方法 方法一 有序集合中,redis没有命令直接判断有序集合中是否存在某个成员,但可以借助ZLEXCOUNT 命令实现:zlexcount 命令 -- Redis中国用户组(CRUG) ZLEXCOUNT key min max
- 有序集合中成员名称 min 和 max 之间的成员数量; Integer类型。
命令使用示例如下:
127.0.0.1:6379> zrevrange zsetkey 0 -1 1) "e" 2) "d" 3) "c" 4) "b" 5) "a" 127.0.0.1:6379> zlexcount zsetkey [a [a (integer) 1 # 存在 127.0.0.1:6379> zlexcount zsetkey [m [m (integer) 0 # 不存在
php代码示例如下:
public function checkExists($zsetkey, $member, $redis) { $ret = intval($redis->zLexCount($zsetkey, '['.$member, '['.$member)); return $ret > 0 ? true : false; }
方法二 使用redis有序集合的ZSCORE 命令实现:zscore 命令 -- Redis中国用户组(CRUG) ZSCORE key member
- 返回有序集key中,成员member的score值。
- 如果member元素不是有序集key的成员,或key不存在,返回nil。
命令使用示例如下:
127.0.0.1:6379> zadd myzset 1 "one" (integer) 1 127.0.0.1:6379> zscore myzset "one" "1" 127.0.0.1:6379> zscore myzset "two" nil
php代码示例如下:
public function checkExists($zsetkey, $member, $redis) { $ret = $redis->zScore($zsetkey, $member); return false === $ret ? false : true; }
2.2 搭建集群,主从复制 单机多实例模式 // 一般用于本地开发环境以及学习redis集群和主从同步 多机多实例模式 // 实际生产环境使用 【狂神说Java】Redis最新超详细版教程通俗易懂_哔哩哔哩_bilibili 2.3 如何将测试环境的redis数据,迁移拷贝到本地redis服务中 三种redis数据导出导入方式 - 无敌仙人掌 - 博客园 如何高效地向Redis插入大量的数据 - iVictor - 博客园 目前个人的思路: 1. 搜索,和使用目前市面上已有的第三方库/工具进行完成 2. 另外自己动手写一个工具/方法,使用代码去同步 3. 最原始的一种方法,就是手动去设置,但是并不是设置所有的数据,而且只设置自己当前开发中需要的数据 -- 这种方式,最简单也是目前比较推荐。 扩展 对于线上ES等数据存储的服务,当访问线上时常不稳定时,也可以使用这种方式作为一种临时方案,而又暂时没有更好的解决办法时,对于个人而言,这种方式不失为一种临时有效的方案。 2.4 关于设置自增操作【或者其他操作】和过期时间一起操作时,可能会导致key永久不过期。 访问频率控制——防止恶意用户频繁访问_LemmonTreelss的博客-CSDN博客_访问频率。-- 尚未验证 -- TBD 20220120 周四 成都 原因: 因为exsits与inc两个操作不能保证原子性,两者必要要么一起执行,要么都不执行,中间不允许有其他操作。 这里的if判断仅仅是针对上面的出现的不能保证原子性的时候的折中而采用的处理方式 -- 其实属于异常情况 异常情况与处理: 判断过期时间,是否为-1,代表永久有效,则重新设置过期时间。 另外可以采用的方式: 采用lua脚本,但是会麻烦一些,结合此处的业务重要性,或许没那么重要。 2.5 并发访问控制 -- 针对单一用户
<?php
namespace appcomponentsredis;
use appcomponentsLimit; use appcomponentsRedisClient;
class ApiLimitRedis {
const key_sms_ip = "limit:sms:ip:"; const key_sms_country = "limit:sms:country:"; const key_sms_ip_whitelist = "limit:sms:ip:whitelist:"; const key_user_follow_pop_up_limit = "limit:follow:";
public static $redis_client;
private static $_redis_pool = 'api-limit';
public static function LimitRedisKey($user_id, $path){ return "limit:" . $user_id . ":" . $path; }
public static function LimitSmsPhoneKey($cellphone){ $time = date("Y-m-d"); return "limit:sms:phone:" .$time .":". $cellphone; }
private static function _getInstance() { if (self::$redis_client instanceof RedisClient) { return self::$redis_client; } self::$redis_client = new RedisClient(self::$_redis_pool); return self::$redis_client; }
public static function SetApiLimit($user_id, $path, $ts = 1) { $key = self::LimitRedisKey($user_id, $path); return self::_getInstance()->set($key, 1, ["NX", "EX" => $ts]); }
public static function ExistApiLimit($user_id, $path) { $key = self::LimitRedisKey($user_id, $path); return self::_getInstance()->exists($key); }
// 短信ip限制 public static function SmsIpLimit($ip){ $key = self::key_sms_ip . $ip; $limitNum = self::_getInstance()->incr($key, 1); if($limitNum == 1){ self::_getInstance()->expire($key, Limit::SmsIpExpire); } return $limitNum; }
public static function SetSmsIpWhitelist($ip){ $key = self::key_sms_ip_whitelist . $ip; $ip = self::_getInstance()->get($key); if (!$ip) { self::_getInstance()->set($key, "1"); } self::_getInstance()->expireat($key, strtotime('tomorrow'));
return true; }
public static function GetSmsIpWhitelist($ip) { return self::_getInstance()->get(self::key_sms_ip_whitelist . $ip); }
// 短信phone限制 public static function SmsPhoneLimit($phone){ $key = self::LimitSmsPhoneKey($phone); $limitNum = self::_getInstance()->incr($key, 1); if($limitNum == 1){ self::_getInstance()->expire($key, 115200); } return $limitNum; }
/** * @param $country_code * @return mixed */ public static function SmsCountryMaxLimit($country_code) { $Ymd = date("Y-m-d", time() + 28800); $key = self::key_sms_country . $Ymd . ":" . $country_code; return self::_getInstance()->incr($key, 1); }
public static function CheckSmsCountryMaxLimit($country_code) { $Ymd = date("Y-m-d", time() + 28800); $key = self::key_sms_country . $Ymd . ":" . $country_code; return self::_getInstance()->get($key); }
/** * Used for follow/operation * Limit for showing the banner for an hour if the user plays with follow button of a specific streamer * @param string $user_guid * @param string $streamer_guid * @return mixed */ public static function SetFollowUpcomingLsLimit(string $user_guid, string $streamer_guid) { $key = self::key_user_follow_pop_up_limit . $user_guid . ':' . $streamer_guid; $limitNum = self::_getInstance()->incr($key, 1); if($limitNum == 1){ self::_getInstance()->expire($key, Limit::FollowPopupExpire); } return $limitNum; }
/** * Used for follow/operation * Limit for showing the banner for an hour if the user plays with follow button of a specific streamer * @param string $user_guid * @param string $streamer_guid * @return mixed */ public static function checkIfExistFollowUpcomingLsLimit(string $user_guid, string $streamer_guid) { $key = self::key_user_follow_pop_up_limit . $user_guid . ':' . $streamer_guid; return self::_getInstance()->exists($key); }
}
2.6 Redis支持查看单个key占用内存情况 / 以及获取配置信息 同时验证bitmap的最大支持的offset,以及占用最大的内存情况 memory usage some.key // 单位是字节
127.0.0.1:6379> setbit test.max.offset-1 536870911 1
(integer) 0
127.0.0.1:6379> getbit test.max.offset-1 536870911
(integer) 1
127.0.0.1:6379> memory usage test.max.offset-1
(integer) 67125320
127.0.0.1:6379> getbit test.max.offset-1 4294967296
(error) ERR bit offset is not an integer or out of range
127.0.0.1:6379> getbit test.max.offset-1 4294967295
(integer) 0
127.0.0.1:6379> getbit test.max.offset-1 4294967295
(integer) 0
127.0.0.1:6379> setbit test.max.offset-1 4294967295 1
(integer) 0
127.0.0.1:6379> getbit test.max.offset-1 4294967295
(integer) 1
127.0.0.1:6379> memory usage test.max.offset-1
(integer) 537935944
127.0.0.1:6379>
CONFIG 命令查看或设置配置项
CONFIG get * // 所有的 CONFIG get param_name CONFIG set param_name value (设置param_name=value)
实践 -- 本地redis服务,默认配置
127.0.0.1:6379> config get *
1) "rdbchecksum"
2) "yes"
3) "daemonize"
4) "no"
5) "io-threads-do-reads"
6) "no"
7) "lua-replicate-commands"
8) "yes"
9) "always-show-logo"
10) "no"
11) "protected-mode"
12) "yes"
13) "rdbcompression"
14) "yes"
15) "rdb-del-sync-files"
16) "no"
17) "activerehashing"
18) "yes"
19) "stop-writes-on-bgsave-error"
20) "yes"
21) "set-proc-title"
22) "yes"
23) "dynamic-hz"
24) "yes"
25) "lazyfree-lazy-eviction"
26) "no"
27) "lazyfree-lazy-expire"
28) "no"
29) "lazyfree-lazy-server-del"
30) "no"
31) "lazyfree-lazy-user-del"
32) "no"
33) "lazyfree-lazy-user-flush"
34) "no"
35) "repl-disable-tcp-nodelay"
36) "no"
37) "repl-diskless-sync"
38) "no"
39) "gopher-enabled"
40) "no"
41) "aof-rewrite-incremental-fsync"
42) "yes"
43) "no-appendfsync-on-rewrite"
44) "no"
45) "cluster-require-full-coverage"
46) "yes"
47) "rdb-save-incremental-fsync"
48) "yes"
49) "aof-load-truncated"
50) "yes"
51) "aof-use-rdb-preamble"
52) "yes"
53) "cluster-replica-no-failover"
54) "no"
55) "cluster-slave-no-failover"
56) "no"
57) "replica-lazy-flush"
58) "no"
59) "slave-lazy-flush"
60) "no"
61) "replica-serve-stale-data"
62) "yes"
63) "slave-serve-stale-data"
64) "yes"
65) "replica-read-only"
66) "yes"
67) "slave-read-only"
68) "yes"
69) "replica-ignore-maxmemory"
70) "yes"
71) "slave-ignore-maxmemory"
72) "yes"
73) "jemalloc-bg-thread"
74) "yes"
75) "activedefrag"
76) "no"
77) "syslog-enabled"
78) "no"
79) "cluster-enabled"
80) "no"
81) "appendonly"
82) "no"
83) "cluster-allow-reads-when-down"
84) "no"
85) "crash-log-enabled"
86) "yes"
87) "crash-memcheck-enabled"
88) "yes"
89) "use-exit-on-panic"
90) "no"
91) "disable-thp"
92) "yes"
93) "cluster-allow-replica-migration"
94) "yes"
95) "replica-announced"
96) "yes"
97) "aclfile"
98) ""
99) "unixsocket"
100) ""
101) "pidfile"
102) ""
103) "replica-announce-ip"
104) ""
105) "slave-announce-ip"
106) ""
107) "masteruser"
108) ""
109) "cluster-announce-ip"
110) ""
111) "syslog-ident"
112) "redis"
113) "dbfilename"
114) "dump.rdb"
115) "appendfilename"
116) "appendonly.aof"
117) "server_cpulist"
118) ""
119) "bio_cpulist"
120) ""
121) "aof_rewrite_cpulist"
122) ""
123) "bgsave_cpulist"
124) ""
125) "ignore-warnings"
126) ""
127) "proc-title-template"
128) "{title} {listen-addr} {server-mode}"
129) "masterauth"
130) ""
131) "requirepass"
132) ""
133) "supervised"
134) "no"
135) "syslog-facility"
136) "local0"
137) "repl-diskless-load"
138) "disabled"
139) "loglevel"
140) "notice"
141) "maxmemory-policy"
142) "noeviction"
143) "appendfsync"
144) "everysec"
145) "oom-score-adj"
146) "no"
147) "acl-pubsub-default"
148) "allchannels"
149) "sanitize-dump-payload"
150) "no"
151) "databases"
152) "16"
153) "port"
154) "6379"
155) "io-threads"
156) "1"
157) "auto-aof-rewrite-percentage"
158) "100"
159) "cluster-replica-validity-factor"
160) "10"
161) "cluster-slave-validity-factor"
162) "10"
163) "list-max-ziplist-size"
164) "-2"
165) "tcp-keepalive"
166) "300"
167) "cluster-migration-barrier"
168) "1"
169) "active-defrag-cycle-min"
170) "1"
171) "active-defrag-cycle-max"
172) "25"
173) "active-defrag-threshold-lower"
174) "10"
175) "active-defrag-threshold-upper"
176) "100"
177) "lfu-log-factor"
178) "10"
179) "lfu-decay-time"
180) "1"
181) "replica-priority"
182) "100"
183) "slave-priority"
184) "100"
185) "repl-diskless-sync-delay"
186) "5"
187) "maxmemory-samples"
188) "5"
189) "maxmemory-eviction-tenacity"
190) "10"
191) "timeout"
192) "0"
193) "replica-announce-port"
194) "0"
195) "slave-announce-port"
196) "0"
197) "tcp-backlog"
198) "511"
199) "cluster-announce-bus-port"
200) "0"
201) "cluster-announce-port"
202) "0"
203) "cluster-announce-tls-port"
204) "0"
205) "repl-timeout"
206) "60"
207) "repl-ping-replica-period"
208) "10"
209) "repl-ping-slave-period"
210) "10"
211) "list-compress-depth"
212) "0"
213) "rdb-key-save-delay"
214) "0"
215) "key-load-delay"
216) "0"
217) "active-expire-effort"
218) "1"
219) "hz"
220) "10"
221) "min-replicas-to-write"
222) "0"
223) "min-slaves-to-write"
224) "0"
225) "min-replicas-max-lag"
226) "10"
227) "min-slaves-max-lag"
228) "10"
229) "maxclients"
230) "10000"
231) "active-defrag-max-scan-fields"
232) "1000"
233) "slowlog-max-len"
234) "128"
235) "acllog-max-len"
236) "128"
237) "lua-time-limit"
238) "5000"
239) "cluster-node-timeout"
240) "15000"
241) "slowlog-log-slower-than"
242) "10000"
243) "latency-monitor-threshold"
244) "0"
245) "proto-max-bulk-len"
246) "536870912"
247) "stream-node-max-entries"
248) "100"
249) "repl-backlog-size"
250) "1048576"
251) "maxmemory"
252) "0"
253) "hash-max-ziplist-entries"
254) "512"
255) "set-max-intset-entries"
256) "512"
257) "zset-max-ziplist-entries"
258) "128"
259) "active-defrag-ignore-bytes"
260) "104857600"
261) "hash-max-ziplist-value"
262) "64"
263) "stream-node-max-bytes"
264) "4096"
265) "zset-max-ziplist-value"
266) "64"
267) "hll-sparse-max-bytes"
268) "3000"
269) "tracking-table-max-keys"
270) "1000000"
271) "client-query-buffer-limit"
272) "1073741824"
273) "repl-backlog-ttl"
274) "3600"
275) "auto-aof-rewrite-min-size"
276) "67108864"
277) "logfile"
278) ""
279) "watchdog-period"
280) "0"
281) "dir"
282) "/Users/kumu/Documents/github/ningxiaofa"
283) "save"
284) "3600 1 300 100 60 10000"
285) "client-output-buffer-limit"
286) "normal 0 0 0 slave 268435456 67108864 60 pubsub 33554432 8388608 60"
287) "unixsocketperm"
288) "0"
289) "slaveof"
290) ""
291) "notify-keyspace-events"
292) ""
293) "bind"
294) ""
295) "oom-score-adj-values"
296) "0 200 800"
127.0.0.1:6379>
Redis MEMORY USAGE 命令 | 程序员笔记 2.7 启动Redis 服务,以及客户端访问的配置
二、Redis启动、停止、Redis命令行的操作 - 钧天府人 - 博客园
2.8 redis批量删除keys
方式一: 笨方法: 依次指定多个 key: DEL key1 key2 key3 ...
方式二: 在方式一的基础上,使用xargs传参 先查询,在删除,使用xargs传参(xargs可以将管道或标准输入(stdin)数据转换成命令行参数),先执行查询语句,在将查询出来的key值,当作del的参数去删除。 redis-cli -n 7 KEYS *platform_config_key* | xargs redis-cli -n 7 del 例如批量删除包含 platform_config_key 字符串的keys [root@ip-172-31-24-254 ~]# redis-cli -n 7 KEYS *platform_config_key* | xargs redis-cli -n 7 del (integer) 10 [root@ip-172-31-24-254 ~]#
redis-cli -h 127.0.0.1 -p 6379 -a xxxxxx -n 1 参数解释: -h <hostname> Server hostname (default: 127.0.0.1). 指定ip -p <port> Server port (default: 6379).指定端口,默认是6379 -a <password> Password to use when connecting to the server. 连接密码 -n <db> Database number.指定的数据库
方式三: 使用 Lua 脚本 EVAL "return redis.call('del', unpack(redis.call('keys', ARGV[1])))" 0 pattern
例如,要删除以 user: 开头的所有 key,可以执行以下命令: EVAL "return redis.call('del', unpack(redis.call('keys', ARGV[1])))" 0 user:*
Localhost-Docker:0>keys * 1) "ning1" 2) "ning"
Localhost-Docker:0>EVAL "return redis.call('del', unpack(redis.call('keys', ARGV[1])))" 0 ning* "2" Localhost-Docker:0>
后续补充 ... |
发表评论 取消回复