首页
归档
关于
Search
1
C服务器端
9 阅读
2
管道处理模型
9 阅读
3
数据结构与算法
8 阅读
4
EF 贪婪加载 , 延迟加载,显式加载
8 阅读
5
1.数据流图(下午题)
8 阅读
软件设计师笔记
.Net
Java
数据库
PHP
运维
前端
Python
中间件相关
云原生
架构设计
Search
标签搜索
websocket
科技新闻
Bi8bo
有钱终成眷属,没钱亲眼目睹
累计撰写
267
篇文章
累计收到
2
条评论
首页
栏目
软件设计师笔记
.Net
Java
数据库
PHP
运维
前端
Python
中间件相关
云原生
架构设计
页面
归档
关于
搜索到
17
篇与
的结果
2025-04-03
Redis缓存穿透解决方案
缓存穿透描述: 缓存穿透是指缓存和数据库中都没有的数据,而用户不断发起请求。由于缓存是不命中时被动写的,并且出于容错考虑,如果从存储层查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到存储层去查询,失去了缓存的意义。在流量大时,可能DB就挂掉了,要是有人利用不存在的key频繁攻击我们的应用,这就是漏洞。如发起为id为“-1”的数据或id为特别大不存在的数据。这时的用户很可能是攻击者,攻击会导致数据库压力过大。 解决方案:接口层增加校验,如用户鉴权校验,id做基础校验,id<=0的直接拦截;从缓存取不到的数据,在数据库中也没有取到,这时也可以将key-value对写为key-null,缓存有效时间可以设置短点,如30秒(设置太长会导致正常情况也没法使用)。这样可以防止攻击用户反复用同一个id暴力攻击
2025年04月03日
4 阅读
0 评论
0 点赞
2025-04-03
RedisTemplate之opsForValue使用说明
1、set(K key, V value) 新增一个字符串类型的值,key是键,value是值。redisTemplate.opsForValue().set("stringValue","bbb"); 2、get(Object key) 获取key键对应的值。String stringValue = redisTemplate.opsForValue().get("key")3、append(K key, String value)在原有的值基础上新增字符串到末尾。redisTemplate.opsForValue().append("key", "appendValue"); String stringValueAppend = redisTemplate.opsForValue().get("key"); System.out.println("通过append(K key, String value)方法修改后的字符串:"+stringValueAppend); 4、get(K key, long start, long end)截取key键对应值得字符串,从开始下标位置开始到结束下标的位置(包含结束下标)的字符串。String cutString = redisTemplate.opsForValue().get("key", 0, 3); System.out.println("通过get(K key, long start, long end)方法获取截取的字符串:"+cutString); 5、getAndSet(K key, V value) 获取原来key键对应的值并重新赋新值。String oldAndNewStringValue = redisTemplate.opsForValue().getAndSet("key", "ccc"); System.out.print("通过getAndSet(K key, V value)方法获取原来的值:" + oldAndNewStringValue ); String newStringValue = redisTemplate.opsForValue().get("key"); System.out.println("修改过后的值:"+newStringValue); 6、setBit(K key, long offset, boolean value) key键对应的值value对应的ascii码,在offset的位置(从左向右数)变为value。redisTemplate.opsForValue().setBit("key",1,false); newStringValue = redisTemplate.opsForValue().get("key")+""; System.out.println("通过setBit(K key,long offset,boolean value)方法修改过后的值:"+newStringValue); 7、getBit(K key, long offset) 判断指定的位置ASCII码的bit位是否为1。boolean bitBoolean = redisTemplate.opsForValue().getBit("key",1); System.out.println("通过getBit(K key,long offset)方法判断指定bit位的值是:" + bitBoolean); 8、size(K key) 获取指定字符串的长度Long stringValueLength = redisTemplate.opsForValue().size("key"); System.out.println("通过size(K key)方法获取字符串的长度:"+stringValueLength); 9、increment(K key, double delta) 以增量的方式将double值存储在变量中。double stringValueDouble = redisTemplate.opsForValue().increment("doubleKey",5); System.out.println("通过increment(K key, double delta)方法以增量方式存储double值:" + stringValueDouble); 10、increment(K key, long delta) 以增量的方式将long值存储在变量中。double stringValueLong = redisTemplate.opsForValue().increment("longKey",6); System.out.println("通过increment(K key, long delta)方法以增量方式存储long值:" + stringValueLong); 11、setIfAbsent(K key, V value) 如果键不存在则新增,存在则不改变已经有的值。boolean absentBoolean = redisTemplate.opsForValue().setIfAbsent("absentKey","fff"); System.out.println("通过setIfAbsent(K key, V value)方法判断变量值absentValue是否存在:" + absentBoolean); if(absentBoolean){ String absentValue = redisTemplate.opsForValue().get("absentKey")+""; System.out.print(",不存在,则新增后的值是:"+absentValue); boolean existBoolean = redisTemplate.opsForValue().setIfAbsent("absentKey","eee"); System.out.print(",再次调用setIfAbsent(K key, V value)判断absentValue是否存在并重新赋值:" + existBoolean); if(!existBoolean){ absentValue = redisTemplate.opsForValue().get("absentKey")+""; System.out.print("如果存在,则重新赋值后的absentValue变量的值是:" + absentValue); 12、set(K key, V value, long timeout, TimeUnit unit) 设置变量值的过期时间。redisTemplate.opsForValue().set("timeOutKey", "timeOut", 5, TimeUnit.SECONDS); String timeOutValue = redisTemplate.opsForValue().get("timeOutKey")+""; System.out.println("通过set(K key, V value, long timeout, TimeUnit unit)方法设置过期时间,过期之前获取的数据:"+timeOutValue); Thread.sleep(5*1000); timeOutValue = redisTemplate.opsForValue().get("timeOutKey")+""; System.out.print(",等待10s过后,获取的值:"+timeOutValue); 13、set(K key, V value, long offset) 覆盖从指定位置开始的值。redisTemplate.opsForValue().set("absentKey","dd",1); String overrideString = redisTemplate.opsForValue().get("absentKey"); System.out.println("通过set(K key, V value, long offset)方法覆盖部分的值:"+overrideString); 14、multiSet(Map<? extends K,? extends V> map) 设置map集合到redis。Map valueMap = new HashMap(); valueMap.put("valueMap1","map1"); valueMap.put("valueMap2","map2"); valueMap.put("valueMap3","map3"); redisTemplate.opsForValue().multiSet(valueMap); 15、multiGet(Collection keys) 根据集合取出对应的value值。//根据List集合取出对应的value值 List paraList = new ArrayList(); paraList.add("valueMap1"); paraList.add("valueMap2"); paraList.add("valueMap3"); List<String> valueList = redisTemplate.opsForValue().multiGet(paraList); for (String value : valueList){ System.out.println("通过multiGet(Collection<K> keys)方法获取map值:" + value); }16、multiSetIfAbsent(Map<? extends K,? extends V> map)Map valueMap = new HashMap(); valueMap.put("valueMap1","map1"); valueMap.put("valueMap2","map2"); valueMap.put("valueMap3","map3"); redisTemplate.opsForValue().multiSetIfAbsent(valueMap);
2025年04月03日
4 阅读
0 评论
0 点赞
2025-04-03
哨兵 Sentinel
暂无简介
2025年04月03日
4 阅读
0 评论
0 点赞
2025-04-03
Redis集群方案
只需要监听主库即可
2025年04月03日
4 阅读
0 评论
0 点赞
2025-04-03
Redis脑裂解决方案
一、哨兵(sentinel)模式下的脑裂如上图,1个master与3个slave组成的哨兵模式(哨兵独立部署于其它机器),刚开始时,2个应用服务器server1、server2都连接在master上,如果master与slave及哨兵之间的网络发生故障,但是哨兵与slave之间通讯正常,这时3个slave其中1个经过哨兵投票后,提升为新master,如果恰好此时server1仍然连接的是旧的master,而server2连接到了新的master上。数据就不一致了,基于setNX指令的分布式锁,可能会拿到相同的锁;基于incr生成的全局唯一id,也可能出现重复。有多少个redis slave就写多少个最小连接数量
2025年04月03日
5 阅读
0 评论
0 点赞
1
2
...
4