cache 的简单认识与思考
之前对NOSQL的总结是:基本功能是key-value, 然后各自附加特殊功能. 现在简单的来认识一下cache.
背景
大家都知道NoSQL, 大多数都是 key-value 型的数据库.
有些内存型的数据库甚至可以当做远程cache来使用, 比如memcache, redis, 或者公司内部的TMEM等数据库.

有时候,我们认为远程cache依旧太慢,毕竟一次网络操作来回至少几十毫秒, 加上网上不稳定等因素, 本地cache还是很有必要的.
目前,我使用的本地cache往往是开一个共享内存, 然后服务会开若干进程, 这些进程同时读写本地cache, 基本上解决了服务高访问量的问题.

这个本地cache使用的是一个通用的cache库, 特点是使用hashtable实现, 缺点是key和value的长度是固定的.
固定的长度, 会导致几个问题.
- key和value 最大长度限制.
- 很浪费空间, 所有的value占用相同的空间. 我们的value及时只有很小的长度, 占用的空间依旧很大.

后来, 我遇到这么一个问题: 有大量的数据, value在短时间内只有一个值:0或者1.
看到这个, 大家第一个想到的应该是位压缩吧.
但是注意这里有两个问题: 1.我们不能把所有的key储存下来, 2.value只是在短时间内不变,过了时间就失效了.
其实, 这就是cache能够满足的事情, 只不过这个cache的value比较极端,只有几字节.
再后来,我又遇到一个问题:有大量的数据, value在短时间内非常大,有时候高大30K.
这个问题cache还是可以满足的, 只是这个cache的value又是另一个极端: value非常大.
针对这两个问题, 我们需要改造cache, 来分别适应两个极端情况.
小value极端
对于小value极端情况, 解决方案简单点: 初始化共享内存时动态指定value的长度即可.
当然储存的数据结构的参数也要调整一下, 目的是让key在hash的时候足够的分散, 毕竟我们的value长度可能还没有key的长度长.
当然我们也可以换一下数据结构, 使用hash list 或者 平衡树.
不过一般情况下不要使用树这个数据结构吧, 实现复杂(正确性难以保证),复杂度还是log级别的(和hash相比,还是差一个数量级).
大value极端
对于大value极端情况, 我们就不能简单的增大value来解决问题了.
因为这个大value只是说明极端情况下, 有些value很大, 一般情况下, value还是中等大小的.
如果我们简单增大value, 将会浪费很大内存(内存还是很宝贵的).
PS:我第一次简单的增大value时,增大前占用共享内存是1.6G, 单纯的增大value值,没有减小节点数的时候, 机器瞬时死了,一查内存,申请了24G内存, 16G是虚拟内存,吓尿了.
面对上面的问题,我们目前的储存方式是不能解决的, 所以需要换一种储存方式.
最直接的想法就是key和value分开储存, 我们key的数据结构中只需要储存value的一些元信息即可.
这个时候,对于value的储存,很容易想到操作系统内存分配算法, 对,就是这个方法, 对value分页, 然后保存每一页的信息即可.

这个时候,再回过头看看这个储存方式, 可以支持任意大小的value值了, 对于小value, 浪费顶多不到一页的内存.
当然, 代价是我们需要另外预留一片内存,来管理value的页块.
PS:其实,上面不等长hash table也可以近似做到value分块, 第一级不hash,每次遍历, 第二级hash, 最多可以得到第一级的大小.
尾记
这种value极小, 极大, 一般的情况在我的一个服务中都遇到了, 起初是固定value值比较小, 对于大value, 直接报写cache错误.
后来增大value后, 写cache正常了, 但是cache的节点数讲了一个数量级:由30000变成2000, 根据监控, cache的利用率瞬时飙到80%.
目前比较偷懒的方法是把cache库改造拆分成三个库, 极小情况下使用极小value的cache库, 极大情况下使用极大value的cache库.
PS: 之前感觉共享内存很高大上, 看了源代码, 发现我们先得到共享内存的指针, 然后, 共享内存也仅仅只是一片内存而已了, 怎么干还是自己说了算.
PS: 关于共享内存加锁的问题, 不在该文章范围内, 故不许考虑多写加锁问题.
cache 的简单认识与思考的更多相关文章
- Nancy之Cache的简单使用
一.前言 说起缓存,或许大家都不陌生,甚至是天天都在用!当然缓存也被分的越来越细,页面缓存.数据缓存.文件缓存等等. 其实呢,我个人觉得,主要还是两大类:数据的缓存和页面的缓存.数据缓存的话就包括所有 ...
- LRU Cache的简单c++实现
什么是 LRU LRU Cache是一个Cache的置换算法,含义是“最近最少使用”,把满足“最近最少使用”的数据从Cache中剔除出去,并且保证Cache中第一个数据是最近刚刚访问的,因为这样的数据 ...
- spring使用@Cache的简单实现
基于xml的配置感觉没有注解形式简单明了,咱不考虑了. 进入正题之前先提个疑问,希望知道的人能告诉一下 下述介绍会有这段代码: @Cacheable(value="myCache" ...
- vue axios 简单封装以及思考
先安装 axios npm install axios axios的详细介绍以及用法 就不多说了请 移步 github ➡️ https://github.com/axios/axios 下面是简单 ...
- LRU cache缓存简单实现
LRU cache LRU(最近最少使用)是一种常用的缓存淘汰机制.当缓存大小容量到达最大分配容量的时候,就会将缓存中最近访问最少的对象删除掉,以腾出空间给新来的数据. 实现 (1)单线程简单版本 ( ...
- [Java 缓存] Java Cache之 Guava Cache的简单应用.
前言 今天第一次使用MarkDown的形式发博客. 准备记录一下自己对Guava Cache的认识及项目中的实际使用经验. 一: 什么是Guava Guava工程包含了若干被Google的 Java项 ...
- [Objective-C] Block实现回调和简单的学习思考
初识Block的时候,总觉得其很可怕,因为看不懂其运行原理,所以用起来总是觉得不安全.关于Block的语法,等我把手里的资料全部看完,整理好再发出来.这次先看看用Block怎么实现回调. 新博客:wo ...
- mybatis与springdata的一些简单比较与思考
主题 最近在用mybatis做项目,有一些感触想记录下,主要是mybatis(以及它的一些插件)相比较于Spring data(或者jpa,hibernate等)的优势地方. 感触 我觉得mybati ...
- 基于LRU Cache的简单缓存
package com.test.testCache; import java.util.Map; import org.json.JSONArray; import org.json.JSONExc ...
随机推荐
- http://blog.csdn.net/majian_1987/article/details/44939911
http://blog.csdn.net/majian_1987/article/details/44939911
- QPushButton 的checkable 属性
只有setCheckable(true),这个button才能发射 toggle(bool) 信号. 而toggle(bool)代表了button 按下,弹起的状态像0,1的切换开关.
- 生成整数自增ID(集群主键生成服务)
在集群的环境中,有这种场景 需要整数自增ID,这个整数要求一直自增,并且需要保证唯一性. Web服务器集群调用这个整数生成服务,然后根据各种规则,插入指定的数据库. 一般 ...
- Java SE7新特性之try-with-resources语句
try-with-resources语句是一个声明一个或多个资源的 try 语句.一个资源作为一个对象,必须在程序结束之后随之关闭. try-with-resources语句确保在语句的最后每个 ...
- Memcache+Cookie解决分布式系统共享登录状态------------------------------Why Memcached?
每个用户请求向IIS发送一个请求,但IIS服务器的请求数有限,cpu支持的线程数有限,如果一秒钟向这台服务器发送10000次,那么则一般就会有问题,考虑集群, 请求数据分流,几台服务器共同对应一个公共 ...
- 【HDOJ】4363 Draw and paint
看题解解的.将着色方案映射为40*40*5*5*5*5*2个状态,40*40表示n*m,5*5*5*5表示上下左右相邻块的颜色,0表示未着色.2表示横切或者竖切.基本思路是记忆化搜索然后去重,关键点是 ...
- C#中的多文档的使用
1.首先,新建一个窗体,设置窗体的IsMdiContainer = true; 窗体的大小为700*600 长700 高600 2.在窗体的Load事件中添加如下代码 private void F ...
- R12 - OM改进了对成本与收入确认的流程
我们知道在企业经营活动中,根据财务制度的要求,对于收入与成本确认有很复杂的原则,这里就不去细讨论这些原则了,要了解的话可以看纵横四海的BLOG: 中也有,但11中是灰的. 这个科目什么时候发挥作用呢? ...
- 使用Zxing实现扫二维码描
1.集成Zxing.bar 2.复制代码到项目中 3.修改 MipacActivityCapture.java 的扫描结果方法 handleDecode() /** * 处理扫描结果,实现活动页面跳 ...
- jquery适用技巧
jQuery对象与dom对象的转换 只有jquery对象才能使用jquery定义的方法.注意dom对象和jquery对象是有区别的,调用方法时要注意操作的是dom对象还是jquery对象. 普通的do ...