解决 Redis 的 Big Key 问题
Redis 的 Big Key 问题Big Key 问题
指 key 对应的 value 所占的内存空间比较大
对于字符串类型的 value,一般认为超过 10KB 属于 bigkey
非字符串类型(哈希、列表、集合、有序集合),体现在元素个数过多
造成的影响
内存空间不均匀(在 Redis Cluster 中,bigkey 会造成节点的内存空间使用不均匀)
超时阻塞:由于 Redis 单线程的特性,操作 bigkey 比较耗时,意味着阻塞 Redis 可能性增大
网络阻塞:每次获取 bigkey 产生的网络流量较大,假设一个 bigkey 为 1MB,每秒访问量为 1000,那么每秒产生 1000MB 的流量,对于普通的千兆网卡(128 MB/s)的服务器来说简直是灭顶之灾,而且一般服务器会采用单机多实例的方式来部署,也就是说一个 bigkey 可能会对其它实例造成影响
解决方案示例通过用户 user_id 获取对应用户的宠物信息(假设用户、宠物信息存在 Redis 中,且一个用户只有一只宠物)
方案一用户信息与宠物信息存在一起
把所有数据存入一个集合( ...
ueditor 自定义上传接口
123456789101112131415161718192021222324UE.delEditor("resume"); // 防止第二次加载渲染失败var resume_ue = UE.getEditor('resume',{ // 这里可以选择自己需要的工具按钮名称,此处仅选择如下五个 // toolbars:[['FullScreen', 'Source', 'Undo', 'Redo','Bold','test']], // focus时自动清空初始化时的内容 // autoClearinitialContent:true, // 关闭字数统计 wordCount:false, // 关闭elementPath elementPathEnabled:false, // 默认的编辑区域高度 initialFrameHeight:300 // 更 ...
ORDER BY 排序 IF 以及 IN
在某些特定的业务场景下,需要把符合条件的单独几行,放在查询结果的开始,或者查询结果的尾部
通过的方法就是 IN 语句(也可以通过 IF 语句)
表内容:
使用 ORDER BY 配合 IF 语句
比如我想将 species 为 snake 的行数,单独列出来,我可以这样查询
SELECT \* FROM pet ORDER BY if (species='snake',0,1),species;
结果如下
我们可以看到,species 为 snake 的行数,被强行放置到了查询结果开头,这是怎么做到的呢?
这里需要注意:if (species='snake',0,1),species;
这句话的意思是,我对 species 进行排序的同时,给 species 附加一个隐藏属性,这个隐藏属性,可以是 0 或者 1,什么意思呢?就是对species 排序的时候,优先级是判断 species 是否为 snake,如果是,返回 0,如果不是,返回 1.随后,先进行 species 隐藏属性的排序,隐藏属性拍完以后,再进行剩余 species 的排序也 ...
MySQL 加密遇到的问题
应安全部门要求,数据库敏感信息需加密存储
使用 MySQL 提供的 AES_ENCRYPT 和 AES_DECRYPT 进行了加解密
使用方式如下:
12345678# 插入insert into user_info (`user_name`) values (AES_ENCRYPT(`张三`,'key'));# 更新update user_info set user_name = AES_ENCRYPT(`张三`,'key') where id = 1;# 查询select AES_DECRYPT(user_name, 'key') from user_info where id = 1;
需要注意的地方
密文列的编码方式应选择 latin1,排序方式使用 latin1_german1_ci
查询出现中文乱码时,可以使用 CONVERT (AES_DECRYPT(value, key) USING utf8) 处理
1select CONVERT (AES_DECRYPT(user_name, 'key ...
Linux 配置多个 Git 账号
Linux 配置多个 Git 账号公司迁移到腾讯 DevCloud ,记录一下配置小伙伴们的 Git 情况
生成公钥12cd ~/.sshssh-keygen -t rsa -C "xxx@xxx.com"
这里默认生成的是 id_rsa 和 id_rsa.pub,此处需要在第一次出现输入提示的时候,分别输入带有表示意义的名字,以便于识别
配置 config将公钥配置到对应的 git 平台上,然后编辑 ~/.ssh/config
12345678910111213141516171819# 域名地址的别名Host github# 这个是真实的域名地址 Hostname github.com# 配置使用用户名 User xxx@xx.com# 这里是id_rsa的目录位置 IdentityFile ~/.ssh/id_rsa_github # 域名地址的别名Host gitee# 这个是真实的域名地址 Hostname gitee.com# 配置使用用户名 User xxx@x ...
MySQL 存储引擎原理 & 锁
一、MySQL 存储引擎原理拆解`
mysql 存储最小单位 page
一、MySQL 记录存储
1、页头记录页面的控制信息,共占56字节,包括页的左右兄弟页指针、页面空间使用情况等
2、虚记录最大虚记录(比页内最大主键还大)最小虚记录(比页内最小主键还小)
3、记录堆行记录存储区,分为有效记录和已删除记录两种
4、自由空间链表已删除记录组成的链表
5、未分配空间页面未使用的存储空间
6、Slot 区
7、页尾页面最后部分,占8个字节,主要存储页面的校验信息
二、页内记录维护1、顺序保证
物理有序
逻辑有序查询速度可以优化
2、插入策略
自由空间链表
未分配空间
数据库收缩,主从,删从库,重新创建从库,全量同步。从库切主库,主库变从库,再删从库,重新创建从库,全量同步
3、页内查询
遍历
二分查询
所有记录以逻辑有序的方式存为链表,Slot 区将链表分为多个 sub list,对 slot 区进行二分查找,快速定位到 sub list,然后遍历 sub list
二、MySQL 锁一、Innodb 锁种类1、锁粒度
行级锁
作用在索引上
聚 ...
Redis 缓存数据库双写不一致
Redis 缓存数据库双写不一致正常情况下,缓存的读取流程如下:
什么是缓存一致性的问题,其实就是我们最终落库数据和我们缓存中的数据不一致
解决方案
1、设置过期时间
这种方案是为缓存的 key 值设置失效时间,这种情况下不管数据库数据怎么折腾,最晚会在缓存失效后,重新从数据库中获取最新的数据,加载到缓存中。
优点:最终缓存内数据和数据库中数据是一致的
缺点:内容更新不及时
2、先更新数据库,再更新缓存
种这方案的问题在于,当有两个或者多个线程同时进行数据更新时,会发生数据不一致的情况。流程如下图:
当线程 1 先更新数据库,但是由于网路等原因晚于线程 2 更新缓存,最终导致的结果是缓存数据的不一致。
3、先删除缓存,再更新数据库
此方案问题在于,当有一个线程读取缓存时,缓存已经被另一个更新线程删除了,此时读取线程会去数据库查询数据,并且放到缓存中,此时更新线程还没有完成数据库的更新操作,依旧会出现缓存不一致的问题。流程如下:
这种情况可以采用延时双删的策略,在更新数据库之后,延时一段时间,然后将缓存再次删除掉,这样其他读取线程再次读取时候,还是会加载最新的数据。
4 ...
MySql 索引类型 BTree 和 Hash
MySql 索引类型 BTree 和 Hash索引是帮助mysql获取数据的数据结构。最常见的索引是Btree索引和Hash索引。主键索引叶子节点存储的就是 MySql 的整个数据行,普通索引的叶子节点存储的是索引列和主键值。
不同的引擎对于索引有不同的支持:Innodb 和 MyISAM 默认的索引是 Btree 索引;而 Mermory 默认的索引是 Hash 索引。
一、BTreeBTree 索引是最常用的 mysql 数据库索引算法,因为它不仅可以被用在 =, >, >=, <, <= 和 between 这些比较操作符上,而且还可以用于 like 操作符,只要它的查询条件是一个不以通配符开头的常量,例如:
select * from user where name like ‘jack%’;
select * from user where name like ‘jac%k%’;
如果一通配符开头,或者没有使用常量,则不会使用索引,例如:
select * from user where name like ‘% ...
js 对象数组赋值问题
开发过程中遇到了 js 数组赋值问题,新数组的改变会影响原数组,记录如下:
1234567var arr = [1, 2, 3];console.log(arr); // [1, 2, 3]var newArr = arr;console.log(newArr); // [1, 2, 3]newArr[0] = 2;console.log(arr); // [2, 2, 3]console.log(newArr); // [2, 2, 3]
这种情况,赋值的时候使用以下方法就可以实现改变新数组不影响原数组:
1234567var arr = [1, 2, 3];console.log(arr); // [1, 2, 3]var newArr = [].concat(arr);console.log(newArr); // [1, 2, 3]newArr[0] = 2;console.log(arr); // [1, 2, 3]console.log(newArr); // [2, 2, 3]
但是,当 arr 为一个对象数 ...
数字不同进制之间的转换
各进制介绍
二进制 0 和 1 ,满 2 进 1
八进制 0 - 7 ,满 8 进 1
十六进制 0 - 9 及 a - f ,满 16 进 1 ,a - f 不区分大小写,以 0x 开头表示
各进制之间的转换二进制转十进制
从最低位开始,将每个位上的数提取出来,乘以 2 的 (位数 - 1)次方,最后求和
1011 = 1 * 1 + 1 * 2 + 0 + 1 * 2 * 2 * 2 = 1 + 2 + 0 + 8 = 11
八进制转十进制
从最低位开始,将每个位上的数提取出来,乘以 8 的 (位数 - 1)次方,最后求和
0123 = 3 * 1 + 2 * 8 + 1 * 8 * 8 + 0 = 3 + 16 + 64 = 83
十六进制转十进制
从最低位开始,将每个位上的数提取出来,乘以 16 的 (位数 - 1)次方,最后求和
0x34A = 10 * 1 + 4 * 16 + 3 * 16 * 16 = 10 + 64 + 768 = 842
十进制转二进制
将该数 ...