当前位置: 首页 > news >正文

做视频网站收费侵权吗django 网站开发视频教程

做视频网站收费侵权吗,django 网站开发视频教程,定制微信小程序价格,北京网站建设公司分形科技Redis高级篇之最佳实践 今日内容 Redis键值设计批处理优化服务端优化集群最佳实践 1、Redis键值设计 1.1、优雅的key结构 Redis的Key虽然可以自定义#xff0c;但最好遵循下面的几个最佳实践约定#xff1a; 遵循基本格式#xff1a;[业务名称]:[数据名]:[id]长度不超过…Redis高级篇之最佳实践 今日内容 Redis键值设计批处理优化服务端优化集群最佳实践 1、Redis键值设计 1.1、优雅的key结构 Redis的Key虽然可以自定义但最好遵循下面的几个最佳实践约定 遵循基本格式[业务名称]:[数据名]:[id]长度不超过44字节不包含特殊字符 例如我们的登录业务保存用户信息其key可以设计成如下格式 这样设计的好处 可读性强避免key冲突方便管理更节省内存 key是string类型底层编码包含int、embstr和raw三种。embstr在小于44字节使用采用连续内存空间内存占用更小。当字节数大于44字节时会转为raw模式存储在raw模式下内存空间不是连续的而是采用一个指针指向了另外一段内存空间在这段空间里存储SDS内容这样空间不连续访问的时候性能也就会收到影响还有可能产生内存碎片 1.2、拒绝BigKey BigKey通常以Key的大小和Key中成员的数量来综合判定例如 Key本身的数据量过大一个String类型的Key它的值为5 MBKey中的成员数过多一个ZSET类型的Key它的成员数量为10,000个Key中成员的数据量过大一个Hash类型的Key它的成员数量虽然只有1,000个但这些成员的Value值总大小为100 MB 那么如何判断元素的大小呢redis也给我们提供了命令 推荐值 单个key的value小于10KB对于集合类型的key建议元素数量小于1000 1.2.1、BigKey的危害 网络阻塞 对BigKey执行读请求时少量的QPS就可能导致带宽使用率被占满导致Redis实例乃至所在物理机变慢 数据倾斜 BigKey所在的Redis实例内存使用率远超其他实例无法使数据分片的内存资源达到均衡 Redis阻塞 对元素较多的hash、list、zset等做运算会耗时较旧使主线程被阻塞 CPU压力 对BigKey的数据序列化和反序列化会导致CPU的使用率飙升影响Redis实例和本机其它应用 1.2.2、如何发现BigKey ①redis-cli --bigkeys 利用redis-cli提供的–bigkeys参数可以遍历分析所有key并返回Key的整体统计信息与每个数据的Top1的big key 命令redis-cli -a 密码 --bigkeys ②scan扫描 自己编程利用scan扫描Redis中的所有key利用strlen、hlen等命令判断key的长度此处不建议使用MEMORY USAGE scan 命令调用完后每次会返回2个元素第一个是下一次迭代的光标第一次光标会设置为0当最后一次scan 返回的光标等于0时表示整个scan遍历结束了第二个返回的是List一个匹配的key的数组 import com.qinghua.jedis.util.JedisConnectionFactory; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import redis.clients.jedis.Jedis; import redis.clients.jedis.ScanResult;import java.util.HashMap; import java.util.List; import java.util.Map;public class JedisTest {private Jedis jedis;BeforeEachvoid setUp() {// 1.建立连接// jedis new Jedis(192.168.150.101, 6379);jedis JedisConnectionFactory.getJedis();// 2.设置密码jedis.auth(123321);// 3.选择库jedis.select(0);}final static int STR_MAX_LEN 10 * 1024;final static int HASH_MAX_LEN 500;Testvoid testScan() {int maxLen 0;long len 0;String cursor 0;do {// 扫描并获取一部分keyScanResultString result jedis.scan(cursor);// 记录cursorcursor result.getCursor();ListString list result.getResult();if (list null || list.isEmpty()) {break;}// 遍历for (String key : list) {// 判断key的类型String type jedis.type(key);switch (type) {case string:len jedis.strlen(key);maxLen STR_MAX_LEN;break;case hash:len jedis.hlen(key);maxLen HASH_MAX_LEN;break;case list:len jedis.llen(key);maxLen HASH_MAX_LEN;break;case set:len jedis.scard(key);maxLen HASH_MAX_LEN;break;case zset:len jedis.zcard(key);maxLen HASH_MAX_LEN;break;default:break;}if (len maxLen) {System.out.printf(Found big key : %s, type: %s, length or size: %d %n, key, type, len);}}} while (!cursor.equals(0));}AfterEachvoid tearDown() {if (jedis ! null) {jedis.close();}}}③第三方工具 利用第三方工具如 Redis-Rdb-Tools 分析RDB快照文件全面分析内存使用情况https://github.com/sripathikrishnan/redis-rdb-tools ④网络监控 自定义工具监控进出Redis的网络数据超出预警值时主动告警一般阿里云搭建的云服务器就有相关监控页面 1.2.3、如何删除BigKey BigKey内存占用较多即便时删除这样的key也需要耗费很长时间导致Redis主线程阻塞引发一系列问题。 redis 3.0 及以下版本 如果是集合类型则遍历BigKey的元素先逐个删除子元素最后删除BigKey Redis 4.0以后 Redis在4.0后提供了异步删除的命令unlink 1.3、恰当的数据类型 例1比如存储一个User对象我们有三种存储方式 ①方式一json字符串 user:1{“name”: “Jack”, “age”: 21} 优点实现简单粗暴 缺点数据耦合不够灵活 ②方式二字段打散 user:1:nameJackuser:1:age21 优点可以灵活访问对象任意字段 缺点占用空间大、没办法做统一控制 ③方式三hash推荐 user:1namejackage21 优点底层使用ziplist空间占用小可以灵活访问对象的任意字段 缺点代码相对复杂 例2假如有hash类型的key其中有100万对field和valuefield是自增id这个key存在什么问题如何优化 keyfieldvaluesomeKeyid:0value0..........id:999999value999999 存在的问题 hash的entry数量超过500时会使用哈希表而不是ZipList内存占用较多 可以通过hash-max-ziplist-entries配置entry上限。但是如果entry过多就会导致BigKey问题 方案一 拆分为string类型 keyvalueid:0value0..........id:999999value999999 存在的问题 string结构底层没有太多内存优化内存占用较多 想要批量获取这些数据比较麻烦 方案二 拆分为小的hash将 id / 100 作为key 将id % 100 作为field这样每100个元素为一个Hash keyfieldvaluekey:0id:00value0..........id:99value99key:1id:00value100..........id:99value199....key:9999id:00value999900..........id:99value999999 package com.qinghua.test;import com.qinghua.jedis.util.JedisConnectionFactory; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import redis.clients.jedis.Jedis; import redis.clients.jedis.Pipeline; import redis.clients.jedis.ScanResult;import java.util.HashMap; import java.util.List; import java.util.Map;public class JedisTest {private Jedis jedis;BeforeEachvoid setUp() {// 1.建立连接// jedis new Jedis(192.168.150.101, 6379);jedis JedisConnectionFactory.getJedis();// 2.设置密码jedis.auth(123321);// 3.选择库jedis.select(0);}Testvoid testSetBigKey() {MapString, String map new HashMap();for (int i 1; i 650; i) {map.put(hello_ i, world!);}jedis.hmset(m2, map);}Testvoid testBigHash() {MapString, String map new HashMap();for (int i 1; i 100000; i) {map.put(key_ i, value_ i);}jedis.hmset(test:big:hash, map);}Testvoid testBigString() {for (int i 1; i 100000; i) {jedis.set(test:str:key_ i, value_ i);}}Testvoid testSmallHash() {int hashSize 100;MapString, String map new HashMap(hashSize);for (int i 1; i 100000; i) {int k (i - 1) / hashSize;int v i % hashSize;map.put(key_ v, value_ v);if (v 0) {jedis.hmset(test:small:hash_ k, map);}}}AfterEachvoid tearDown() {if (jedis ! null) {jedis.close();}} }1.4、总结 Key的最佳实践 固定格式[业务名]:[数据名]:[id]足够简短不超过44字节不包含特殊字符 Value的最佳实践 合理的拆分数据拒绝BigKey选择合适数据结构Hash结构的entry数量不要超过1000设置合理的超时时间 2、批处理优化 2.1、Pipeline 2.1.1、我们的客户端与redis服务器是这样交互的 单个命令的执行流程 N条命令的执行流程 redis处理指令是很快的主要花费的时候在于网络传输。于是乎很容易想到将多条指令批量的传输给redis 2.1.2、MSet Redis提供了很多Mxxx这样的命令可以实现批量插入数据例如 msethmset 利用mset批量插入10万条数据 Test void testMxx() {String[] arr new String[2000];int j;long b System.currentTimeMillis();for (int i 1; i 100000; i) {j (i % 1000) 1;arr[j] test:key_ i;arr[j 1] value_ i;if (j 0) {jedis.mset(arr);}}long e System.currentTimeMillis();System.out.println(time: (e - b)); }2.1.3、Pipeline MSET虽然可以批处理但是却只能操作部分数据类型因此如果有对复杂数据类型的批处理需要建议使用Pipeline Test void testPipeline() {// 创建管道Pipeline pipeline jedis.pipelined();long b System.currentTimeMillis();for (int i 1; i 100000; i) {// 放入命令到管道pipeline.set(test:key_ i, value_ i);if (i % 1000 0) {// 每放入1000条命令批量执行pipeline.sync();}}long e System.currentTimeMillis();System.out.println(time: (e - b)); }2.2、集群下的批处理 如MSET或Pipeline这样的批处理需要在一次请求中携带多条命令而此时如果Redis是一个集群那批处理命令的多个key必须落在一个插槽中否则就会导致执行失败。大家可以想一想这样的要求其实很难实现因为我们在批处理时可能一次要插入很多条数据这些数据很有可能不会都落在相同的节点上这就会导致报错了 这个时候我们可以找到4种解决方案 第一种方案串行执行所以这种方式没有什么意义当然执行起来就很简单了缺点就是耗时过久。 第二种方案串行slot简单来说就是执行前客户端先计算一下对应的key的slot一样slot的key就放到一个组里边不同的就放到不同的组里边然后对每个组执行pipeline的批处理他就能串行执行各个组的命令这种做法比第一种方法耗时要少但是缺点呢相对来说复杂一点所以这种方案还需要优化一下 第三种方案并行slot相较于第二种方案在分组完成后串行执行第三种方案就变成了并行执行各个命令所以他的耗时就非常短但是实现呢也更加复杂。 第四种hash_tagredis计算key的slot的时候其实是根据key的有效部分来计算的通过这种方式就能一次处理所有的key这种方式耗时最短实现也简单但是如果通过操作key的有效部分那么就会导致所有的key都落在一个节点上产生数据倾斜的问题所以我们推荐使用第三种方式。 2.2.1 串行化执行代码实践 public class JedisClusterTest {private JedisCluster jedisCluster;BeforeEachvoid setUp() {// 配置连接池JedisPoolConfig poolConfig new JedisPoolConfig();poolConfig.setMaxTotal(8);poolConfig.setMaxIdle(8);poolConfig.setMinIdle(0);poolConfig.setMaxWaitMillis(1000);HashSetHostAndPort nodes new HashSet();nodes.add(new HostAndPort(192.168.150.101, 7001));nodes.add(new HostAndPort(192.168.150.101, 7002));nodes.add(new HostAndPort(192.168.150.101, 7003));nodes.add(new HostAndPort(192.168.150.101, 8001));nodes.add(new HostAndPort(192.168.150.101, 8002));nodes.add(new HostAndPort(192.168.150.101, 8003));jedisCluster new JedisCluster(nodes, poolConfig);}Testvoid testMSet() {jedisCluster.mset(name, Jack, age, 21, sex, male);}Testvoid testMSet2() {MapString, String map new HashMap(3);map.put(name, Jack);map.put(age, 21);map.put(sex, Male);//对Map数据进行分组。根据相同的slot放在一个分组//key就是slotvalue就是一个组MapInteger, ListMap.EntryString, String result map.entrySet().stream().collect(Collectors.groupingBy(entry - ClusterSlotHashUtil.calculateSlot(entry.getKey())));//串行的去执行mset的逻辑for (ListMap.EntryString, String list : result.values()) {String[] arr new String[list.size() * 2];int j 0;for (int i 0; i list.size(); i) {j i2;Map.EntryString, String e list.get(0);arr[j] e.getKey();arr[j 1] e.getValue();}jedisCluster.mset(arr);}}AfterEachvoid tearDown() {if (jedisCluster ! null) {jedisCluster.close();}} }2.2.2 Spring集群环境下批处理代码 Testvoid testMSetInCluster() {MapString, String map new HashMap(3);map.put(name, Rose);map.put(age, 21);map.put(sex, Female);stringRedisTemplate.opsForValue().multiSet(map);ListString strings stringRedisTemplate.opsForValue().multiGet(Arrays.asList(name, age, sex));strings.forEach(System.out::println);}原理分析 在RedisAdvancedClusterAsyncCommandsImpl 类中 首先根据slotHash算出来一个partitioned的mapmap中的key就是slot而他的value就是对应的对应相同slot的key对应的数据 通过 RedisFuture mset super.mset(op);进行异步的消息发送 Override public RedisFutureString mset(MapK, V map) {MapInteger, ListK partitioned SlotHash.partition(codec, map.keySet());if (partitioned.size() 2) {return super.mset(map);}MapInteger, RedisFutureString executions new HashMap();for (Map.EntryInteger, ListK entry : partitioned.entrySet()) {MapK, V op new HashMap();entry.getValue().forEach(k - op.put(k, map.get(k)));RedisFutureString mset super.mset(op);executions.put(entry.getKey(), mset);}return MultiNodeExecution.firstOfAsync(executions); }3、服务器端优化-持久化配置 Redis的持久化虽然可以保证数据安全但也会带来很多额外的开销因此持久化请遵循下列建议 用来做缓存的Redis实例尽量不要开启持久化功能建议关闭RDB持久化功能使用AOF持久化利用脚本定期在slave节点做RDB实现数据备份设置合理的rewrite阈值避免频繁的bgrewrite配置no-appendfsync-on-rewrite yes禁止在rewrite期间做aof避免因AOF引起的阻塞部署有关建议 Redis实例的物理机要预留足够内存应对fork和rewrite单个Redis实例内存上限不要太大例如4G或8G。可以加快fork的速度、减少主从同步、数据迁移压力不要与CPU密集型应用部署在一起不要与高硬盘负载应用一起部署。例如数据库、消息队列 4、服务器端优化-慢查询优化 4.1 什么是慢查询 并不是很慢的查询才是慢查询而是在Redis执行时耗时超过某个阈值的命令称为慢查询。 慢查询的危害由于Redis是单线程的所以当客户端发出指令后他们都会进入到redis底层的queue来执行如果此时有一些慢查询的数据就会导致大量请求阻塞从而引起报错所以我们需要解决慢查询问题。 慢查询的阈值可以通过配置指定 slowlog-log-slower-than慢查询阈值单位是微秒。默认是10000建议1000 慢查询会被放入慢查询日志中日志的长度有上限可以通过配置指定 slowlog-max-len慢查询日志本质是一个队列的长度。默认是128建议1000 修改这两个配置可以使用config set命令 4.2 如何查看慢查询 知道了以上内容之后那么咱们如何去查看慢查询日志列表呢 slowlog len查询慢查询日志长度slowlog get [n]读取n条慢查询日志slowlog reset清空慢查询列表 5、服务器端优化-命令及安全配置 安全可以说是服务器端一个非常重要的话题如果安全出现了问题那么一旦这个漏洞被一些坏人知道了之后并且进行攻击那么这就会给咱们的系统带来很多的损失所以我们这节课就来解决这个问题。 Redis会绑定在0.0.0.0:6379这样将会将Redis服务暴露到公网上而Redis如果没有做身份认证会出现严重的安全漏洞. 漏洞重现方式https://cloud.tencent.com/developer/article/1039000 为什么会出现不需要密码也能够登录呢主要是Redis考虑到每次登录都比较麻烦所以Redis就有一种ssh免秘钥登录的方式生成一对公钥和私钥私钥放在本地公钥放在redis端当我们登录时服务器再登录时候他会去解析公钥和私钥如果没有问题则不需要利用redis的登录也能访问这种做法本身也很常见但是这里有一个前提前提就是公钥必须保存在服务器上才行但是Redis的漏洞在于在不登录的情况下也能把秘钥送到Linux服务器从而产生漏洞 漏洞出现的核心的原因有以下几点 Redis未设置密码利用了Redis的config set命令动态修改Redis配置使用了Root账号权限启动Redis 所以如何解决呢我们可以采用如下几种方案 为了避免这样的漏洞这里给出一些建议 Redis一定要设置密码禁止线上使用下面命令keys、flushall、flushdb、config set等命令。可以利用rename-command禁用。bind限制网卡禁止外网网卡访问开启防火墙不要使用Root账户启动Redis尽量不是有默认的端口 6、服务器端优化-Redis内存划分和内存配置 当Redis内存不足时可能导致Key频繁被删除、响应时间变长、QPS不稳定等问题。当内存使用率达到90%以上时就需要我们警惕并快速定位到内存占用的原因。 有关碎片问题分析 Redis底层分配并不是这个key有多大他就会分配多大而是有他自己的分配策略比如8,16,20等等假定当前key只需要10个字节此时分配8肯定不够那么他就会分配16个字节多出来的6个字节就不能被使用这就是我们常说的 碎片问题 进程内存问题分析 这片内存通常我们都可以忽略不计 缓冲区内存问题分析 一般包括客户端缓冲区、AOF缓冲区、复制缓冲区等。客户端缓冲区又包括输入缓冲区和输出缓冲区两种。这部分内存占用波动较大所以这片内存也是我们需要重点分析的内存问题。 内存占用说明数据内存是Redis最主要的部分存储Redis的键值信息。主要问题是BigKey问题、内存碎片问题进程内存Redis主进程本身运⾏肯定需要占⽤内存如代码、常量池等等这部分内存⼤约⼏兆在⼤多数⽣产环境中与Redis数据占⽤的内存相⽐可以忽略。缓冲区内存一般包括客户端缓冲区、AOF缓冲区、复制缓冲区等。客户端缓冲区又包括输入缓冲区和输出缓冲区两种。这部分内存占用波动较大不当使用BigKey可能导致内存溢出。 于是我们就需要通过一些命令可以查看到Redis目前的内存分配状态 info memory查看内存分配的情况 memory xxx查看key的主要占用情况 接下来我们看到了这些配置最关键的缓存区内存如何定位和解决呢 内存缓冲区常见的有三种 复制缓冲区主从复制的repl_backlog_buf如果太小可能导致频繁的全量复制影响性能。通过replbacklog-size来设置默认1mbAOF缓冲区AOF刷盘之前的缓存区域AOF执行rewrite的缓冲区。无法设置容量上限客户端缓冲区分为输入缓冲区和输出缓冲区输入缓冲区最大1G且不能设置。输出缓冲区可以设置 以上复制缓冲区和AOF缓冲区 不会有问题最关键就是客户端缓冲区的问题 客户端缓冲区指的就是我们发送命令时客户端用来缓存命令的一个缓冲区也就是我们向redis输入数据的输入端缓冲区和redis向客户端返回数据的响应缓存区输入缓冲区最大1G且不能设置所以这一块我们根本不用担心如果超过了这个空间redis会直接断开因为本来此时此刻就代表着redis处理不过来了我们需要担心的就是输出端缓冲区 我们在使用redis过程中处理大量的big value那么会导致我们的输出结果过多如果输出缓存区过大会导致redis直接断开而默认配置的情况下 其实他是没有大小的这就比较坑了内存可能一下子被占满会直接导致咱们的redis断开所以解决方案有两个 1、设置一个大小 2、增加我们带宽的大小避免我们出现大量数据从而直接超过了redis的承受能力 7、服务器端集群优化-集群还是主从 集群虽然具备高可用特性能实现自动故障恢复但是如果使用不当也会存在一些问题 集群完整性问题集群带宽问题数据倾斜问题客户端性能问题命令的集群兼容性问题lua和事务问题 问题1、在Redis的默认配置中如果发现任意一个插槽不可用则整个集群都会停止对外服务 大家可以设想一下如果有几个slot不能使用那么此时整个集群都不能用了我们在开发中其实最重要的是可用性所以需要把如下配置修改成no即有slot不能使用时我们的redis集群还是可以对外提供服务 问题2、集群带宽问题 集群节点之间会不断的互相Ping来确定集群中其它节点的状态。每次Ping携带的信息至少包括 插槽信息集群状态信息 集群中节点越多集群状态信息数据量也越大10个节点的相关信息可能达到1kb此时每次集群互通需要的带宽会非常高这样会导致集群中大量的带宽都会被ping信息所占用这是一个非常可怕的问题所以我们需要去解决这样的问题 解决途径 避免大集群集群节点数不要太多最好少于1000如果业务庞大则建立多个集群。避免在单个物理机中运行太多Redis实例配置合适的cluster-node-timeout值 问题3、命令的集群兼容性问题 有关这个问题咱们已经探讨过了当我们使用批处理的命令时redis要求我们的key必须落在相同的slot上然后大量的key同时操作时是无法完成的所以客户端必须要对这样的数据进行处理这些方案我们之前已经探讨过了所以不再这个地方赘述了。 问题4、lua和事务的问题 lua和事务都是要保证原子性问题如果你的key不在一个节点那么是无法保证lua的执行和事务的特性的所以在集群模式是没有办法执行lua和事务的 那我们到底是集群还是主从 单体Redis主从Redis已经能达到万级别的QPS并且也具备很强的高可用特性。如果主从能满足业务需求的情况下所以如果不是在万不得已的情况下尽量不搭建Redis集群 8、结束语 亲爱的小伙帮们辛苦啦咱们有关redis的最佳实践到这里就讲解完毕了期待小伙们学业有成~~~~
http://www.tj-hxxt.cn/news/224892.html

相关文章:

  • 个人网站搭建wordpress网站分析与优化
  • 久久网站建设专业网站建设公司兴田德润优惠吗
  • 顺德网站优化wordpress嵌入代码
  • 广告在什么网站做设计广告图用什么软件好用
  • 汽车网站建设网上海网站推广行业需求
  • 黄埭做网站团队建设优缺点
  • 用vis做的简单网站个人建站免费服务器
  • 网站建设项目补充协议石墨网站开发
  • 用 htmi5做网站网站查不到备案
  • 口碑好的镇江网站建设图标怎么在wordpress
  • 收钱码合并的网站怎么做在线作图网
  • 网站后台数据处理编辑主要是做什么的啊网上怎么自己做网站
  • 做影视网站被告怎么办阿里巴巴1688采购平台官网
  • 网站系统排名怎样看网站建设
  • 什么网站做推广农产品比较好有哪些网站做外贸的
  • 临沂网站wordpress社交平台主题
  • 成都购物网站建设网站建设和管理制度
  • 沈阳网站seo公司私人网站如何建
  • 温岭网站制作网站建设与管理 试卷
  • 装修的网站泉州共创科技
  • 云南网站推广的目的软文广告案例分析
  • 做网站的流程百科网站开发项目合同书
  • 视频网站的广告能怎么做网页制作基础与实例教程
  • 安阳网站如何做优化平邑做网站的
  • 抚顺您做煮火锅网站开源免费建站程序用的最多的
  • 有什么做设计的兼职网站找人建设一个网站多少钱
  • 网站建设与维护理解seo搜索引擎优化推广专员
  • 汕头网站建设工作安阳市建设工程领域网站
  • 广州建设工程安全质量监督网站郑州建网站价格
  • 网站链接提交网站备案名字填写