如何实现线程安全的内存缓存
乙醇 创建于 about 1 year 之前
最后更新: about 1 year 之前
阅读数: 1598
这两天正好看到一个用go实现的线程安全的内存缓存,实现代码非常简洁高效,不卖弄不烧脑,非常值得初学者拿来学习。
项目地址
项目地址在https://github.com/muesli/cache2go,目前已经有1.8k的star。
如何使用
package main
import (
"github.com/muesli/cache2go"
"fmt"
"time"
)
// Keys & values in cache2go can be of arbitrary types, e.g. a struct.
type myStruct struct {
text string
moreData []byte
}
func main() {
// Accessing a new cache table for the first time will create it.
cache :=
// We will put a new item in the cache. It will expire after
// not being accessed via Value(key) for more than 5 seconds.
val := myStruct{"This is a test!", []byte{}}
cache.Add("someKey", 5*time.Second, &val)
// Let's retrieve the item from the cache.
res, err := cache.Value("someKey")
if err == nil {
fmt.Println("Found value in cache:", res.Data().(*myStruct).text)
} else {
fmt.Println("Error retrieving value from cache:", err)
}
// Wait for the item to expire in cache.
time.Sleep(6 * time.Second)
res, err = cache.Value("someKey")
if err != nil {
fmt.Println("Item is not cached (anymore).")
}
// Add another item that never expires.
cache.Add("someKey", 0, &val)
// cache2go supports a few handy callbacks and loading mechanisms.
cache.SetAboutToDeleteItemCallback(func(e *cache2go.CacheItem) {
fmt.Println("Deleting:", e.Key(), e.Data().(*myStruct).text, e.CreatedOn())
})
// Remove the item from the cache.
cache.Delete("someKey")
// And wipe the entire cache table.
cache.Flush()
}
简单看一下核心api
- 创建缓存对象:
cache2go.Cache("myCache")
- 设置一个key:value对:
cache.Add("someKey", 5*time.Second, &val)
设置的时候需要指定缓存的过期时间 - 获取key对应的value值:
res, err = cache.Value("someKey")
这里就简单分析一下对应接口的实现原理。
key value存储
这里使用的是CacheItem这个结构体来实现的key value存储。相应的数据结构是
// CacheItem is an individual cache item
// Parameter data contains the user-set value in the cache.
type CacheItem struct {
sync.RWMutex
// The item's key.
key interface{}
// The item's data.
data interface{}
// How long will the item live in the cache when not being accessed/kept alive.
lifeSpan time.Duration
// Creation timestamp.
createdOn time.Time
// Last access timestamp.
accessedOn time.Time
// How often the item was accessed.
accessCount int64
// Callback method triggered right before removing the item from the cache
aboutToExpire []func(key interface{})
}
值得注意的点有
- 读写锁:
sync.RWMutex
多线程访问的时候用来进行资源的排他锁定 - 键的实现:
key interface{}
所以key可以是任意类型 - 值的实现:
data interface{}
跟key类似,value可以是任意类型 - 存活时间:
lifeSpan time.Duration
大于这个时间间隔没有被访问的话,的话key就会过期被清理 - 上次被访问的时间:
accessedOn time.Time
- key被访问的次数:
accessCount
再看一下CacheItem初始化的代码
// NewCacheItem returns a newly created CacheItem.
// Parameter key is the item's cache-key.
// Parameter lifeSpan determines after which time period without an access the item
// will get removed from the cache.
// Parameter data is the item's value.
func NewCacheItem(key interface{}, lifeSpan time.Duration, data interface{}) *CacheItem {
t := time.Now()
return &CacheItem{
key: key,
lifeSpan: lifeSpan,
createdOn: t,
accessedOn: t,
accessCount: 0,
aboutToExpire: nil,
data: data,
}
}
可以看出来创建时间和上次访问时间都被设置成了当前时间,访问次数是0.
缓存对象的实现CacheTable
CacheTable对象包含了n个CacheItem,看一下具体的数据结构
type CacheTable struct {
sync.RWMutex
// The table's name.
name string
// All cached items.
items map[interface{}]*CacheItem
// Timer responsible for triggering cleanup.
cleanupTimer *time.Timer
// Current timer duration.
cleanupInterval time.Duration
// The logger used for this table.
logger *log.Logger
// Callback method triggered when trying to load a non-existing key.
loadData func(key interface{}, args ...interface{}) *CacheItem
// Callback method triggered when adding a new item to the cache.
addedItem []func(item *CacheItem)
// Callback method triggered before deleting an item from the cache.
aboutToDeleteItem []func(item *CacheItem)
}
这里需要关注的地方是
items map[interface{}]*CacheItem
: 每个item其实都是这个map里的一项,其实map的key就是item的keycleanupTimer *time.Timer
: 用来做缓存过期的定时器cleanupInterval time.Duration
: 扫描所有的items进行缓存过期清理的时间间隔
添加一个key value
// Add adds a key/value pair to the cache.
// Parameter key is the item's cache-key.
// Parameter lifeSpan determines after which time period without an access the item
// will get removed from the cache.
// Parameter data is the item's value.
func (table *CacheTable) Add(key interface{}, lifeSpan time.Duration, data interface{}) *CacheItem {
item := NewCacheItem(key, lifeSpan, data)
// Add item to cache.
table.Lock()
table.addInternal(item)
return item
}
func (table *CacheTable) addInternal(item *CacheItem) {
// Careful: do not run this method unless the table-mutex is locked!
// It will unlock it for the caller before running the callbacks and checks
table.log("Adding item with key", item.key, "and lifespan of", item.lifeSpan, "to table", table.name)
table.items[item.key] = item
// Cache values so we don't keep blocking the mutex.
expDur := table.cleanupInterval
addedItem := table.addedItem
table.Unlock()
// Trigger callback after adding an item to cache.
if addedItem != nil {
for _, callback := range addedItem {
callback(item)
}
}
// If we haven't set up any expiration check timer or found a more imminent item.
if item.lifeSpan > 0 && (expDur == 0 || item.lifeSpan < expDur) {
table.expirationCheck()
}
}
梳理一下流程
- 创建cache item
- 加读写锁
- 调用
addInternal
方法 - 在items map里添加一项,key就是item的key,value就是item
- 获取整个CacheTable的清理缓存间隔时间
- 解锁,到这一步基本上就完成了数据的持久化
- 运行添加item时的回调函数,如果有的话
- 如果item设置了过期时间,并且table的过期扫描间隔是0(首次添加)或者item的过期间隔小于table的过期间隔时间的话,调用
expirationCheck
函数,进行过期扫描
扫描并清理过期的key
代码如下
// Expiration check loop, triggered by a self-adjusting timer.
func (table *CacheTable) expirationCheck() {
table.Lock()
if table.cleanupTimer != nil {
table.cleanupTimer.Stop()
}
if table.cleanupInterval > 0 {
table.log("Expiration check triggered after", table.cleanupInterval, "for table", table.name)
} else {
table.log("Expiration check installed for table", table.name)
}
// To be more accurate with timers, we would need to update 'now' on every
// loop iteration. Not sure it's really efficient though.
now := time.Now()
smallestDuration := 0 * time.Second
for key, item := range table.items {
// Cache values so we don't keep blocking the mutex.
item.RLock()
lifeSpan := item.lifeSpan
accessedOn := item.accessedOn
item.RUnlock()
if lifeSpan == 0 {
continue
}
if now.Sub(accessedOn) >= lifeSpan {
// Item has excessed its lifespan.
table.deleteInternal(key)
} else {
// Find the item chronologically closest to its end-of-lifespan.
if smallestDuration == 0 || lifeSpan-now.Sub(accessedOn) < smallestDuration {
smallestDuration = lifeSpan - now.Sub(accessedOn)
}
}
}
// Setup the interval for the next cleanup run.
table.cleanupInterval = smallestDuration
if smallestDuration > 0 {
table.cleanupTimer = time.AfterFunc(smallestDuration, func() {
go table.expirationCheck()
})
}
table.Unlock()
}
简单过一起逻辑
- 加读写锁
- 如果启动了扫描定时器,关闭定时器先
- 扫描所有的key,对每一个key
- 加读锁
- 获取key的存活周期
- 获取key的上次访问时间
- 如果存活周期是0,则不处理,这是持续保活的逻辑,可以先不管
- 如果现在的时间距离上次访问时间已经大于了key的存活时间,则删除这个key
- 否则的话算出所有key里面最快要到期的那个key的时间间隔
- 如果有拿到了最快要到期那个key的时间间隔,则运行定时器,在下这个时间间隔之后运行清理函数
- 解锁
删除key的实现
// Delete an item from the cache.
func (table *CacheTable) Delete(key interface{}) (*CacheItem, error) {
table.Lock()
defer table.Unlock()
return table.deleteInternal(key)
}
func (table *CacheTable) deleteInternal(key interface{}) (*CacheItem, error) {
r, ok := table.items[key]
if !ok {
return nil, ErrKeyNotFound
}
// Cache value so we don't keep blocking the mutex.
aboutToDeleteItem := table.aboutToDeleteItem
table.Unlock()
// Trigger callbacks before deleting an item from cache.
if aboutToDeleteItem != nil {
for _, callback := range aboutToDeleteItem {
callback(r)
}
}
r.RLock()
defer r.RUnlock()
if r.aboutToExpire != nil {
for _, callback := range r.aboutToExpire {
callback(key)
}
}
table.Lock()
table.log("Deleting item with key", key, "created on", r.createdOn, "and hit", r.accessCount, "times from table", table.name)
delete(table.items, key)
return r, nil
}
删除的逻辑相对简单一些,主要是需要注意加锁解锁以及运行之前注册的回调函数。
总结
这应该是我见过代码最简单但是star相对比较多的开源项目了。这个项目非常适合我们进行学习,因为
- 可以帮助我们理解锁的使用以及如何使用锁来保证线程安全;
- 帮助我们理解key value内存缓存的实现
- 提供了一种使用定时器来实现定时任务的思路
- 帮助我们理解如何注册和运行回调函数
评论
https://ibb.co/MDQkWZyC
https://ibb.co/nNWg0jRs
https://ibb.co/KzmyDWFV
https://ibb.co/Csv0J8dB
https://ibb.co/wZswyC6m
https://ibb.co/SXzSYrqQ
https://ibb.co/J15tMn6
https://ibb.co/6cQDx1Lq
https://ibb.co/PsZXYnHZ
https://ibb.co/4g2KhPpZ
https://ibb.co/601JZWPW
https://ibb.co/7tQD3g4g
https://ibb.co/Cs1VDZGR
https://ibb.co/Zp2440Xz
https://ibb.co/HLqcjt4n
https://ibb.co/cXyRbrxk
https://ibb.co/n8PRjYJL
https://ibb.co/Z6Mt9JZ0
https://ibb.co/xSxQ2RHt
https://ibb.co/Wvw6Kbsn
https://ibb.co/8gC5xmGb
https://ibb.co/3y1pg7w7
https://ibb.co/dsBZF6Jr
https://ibb.co/S7xQQv33
https://ibb.co/RT2fkZqM
https://ibb.co/Qjc60NFx
https://ibb.co/1t0GYjgf
https://ibb.co/99BMc5tQ
https://ibb.co/nskTBCwK
https://ibb.co/fYdLhcD0
https://ibb.co/Zz4kr7ZM
https://ibb.co/Zz7ZGY0R
https://ibb.co/PZkcGyHB
https://ibb.co/fY0kxT3q
https://ibb.co/VcBdsSzM
https://ibb.co/nqpWHtLk
https://ibb.co/LhpkJqPm
https://ibb.co/GQDBx30p
https://ibb.co/MyLXxdbj
https://ibb.co/SDw34Cx5
https://ibb.co/YFB1m4kG
https://ibb.co/7xmXqb83
https://ibb.co/cRN57R7
https://ibb.co/zTY3mRV5
https://ibb.co/vxZVS0G6
https://ibb.co/whSQB5x2
https://ibb.co/351Nb4sq
https://ibb.co/k2zZnHNm
https://ibb.co/BKS6535Z
https://ibb.co/b5W3MXsS
https://ibb.co/bMmW9LGz
https://ibb.co/tpkmHPJJ
https://ibb.co/7xvDgzKx
https://ibb.co/5QRqhRs
https://ibb.co/svtk6Rvy
https://ibb.co/rft9PjVW
https://ibb.co/M5cQ7Dtr
https://ibb.co/6crvXXkW
https://ibb.co/Q3g4J2Lf
https://ibb.co/kspyPY78
https://ibb.co/v43Ty79c
https://ibb.co/C33gpQ6X
https://ibb.co/KxGZPWDp
https://ibb.co/jkZnzysN
https://ibb.co/HJ6Z1mZ
https://ibb.co/390f7HjY
https://ibb.co/xPT0DdD
https://ibb.co/9Hw5Z83r
https://ibb.co/n88fN1qx
https://ibb.co/JWfF2Tmd
https://ibb.co/PzcJZFkX
https://ibb.co/TBXKGbLX
https://ibb.co/XP6RV9M
https://ibb.co/Rp6VfKPq
https://ibb.co/mCpDb9PM
https://ibb.co/N6tLstW0
https://ibb.co/sd6wy49p
https://ibb.co/Rp0Rr7sL
https://ibb.co/RkkBfTKR
https://ibb.co/ttTwqB7
https://ibb.co/7NJXzxxm
https://ibb.co/k6Gzmgrg
https://ibb.co/r2x1YGSZ
https://ibb.co/WWVZT5yH
https://ibb.co/kgQdn7CM
https://ibb.co/8Dbw5yTV
https://ibb.co/PsvvnjZ1
https://ibb.co/kpJ7pth
https://ibb.co/V0KhJhjS
https://ibb.co/G3FbzX9n
https://ibb.co/4n0nbV8h
https://ibb.co/cKWkwQ3p
https://ibb.co/hRRRzy8z
https://ibb.co/391hkg1p
https://ibb.co/XZZ565WY
https://ibb.co/rGnB2Z5k
https://ibb.co/5gfRNv89
https://ibb.co/FkH5jzJb
https://ibb.co/9mhnTD9Z
https://ibb.co/Y7xJ0kYc
https://ibb.co/mFFcnk8B
https://ibb.co/4ny1rxXP
https://ibb.co/FL7zdYDF
https://ibb.co/mVvnLWDp
https://ibb.co/9mcr1FF5
https://ibb.co/chZC7TJw
https://ibb.co/b5QXRTHK
https://ibb.co/mCtDCKVS
https://ibb.co/nMS4ywSm
https://ibb.co/ymnN8KG3
https://ibb.co/0Vc9cHFn
https://ibb.co/B2rF9WNQ
https://ibb.co/jPvs0GVY
https://ibb.co/BFKZNRX
https://ibb.co/prfg0FgD
https://ibb.co/0yT54J7j
https://ibb.co/8LLtvCR6
https://ibb.co/ynQF1rMp
https://ibb.co/rRdnYtTb
https://ibb.co/HTv9Lj2T
https://ibb.co/PsfHS1B6
https://ibb.co/FLvhfpp6
https://ibb.co/SwCNfP7N
https://ibb.co/rRjCGXSC
https://ibb.co/0RScM1jY
https://ibb.co/BKvZzFd6
https://ibb.co/q328kgcS
https://ibb.co/k2W7tb2d
https://ibb.co/HLW3RdSk
https://ibb.co/K8Whpnh
https://ibb.co/k2Vcmrqg
https://ibb.co/sXfvrsy
https://ibb.co/Z6TntSwW
https://ibb.co/z1BP1ny
https://ibb.co/ch6m6c3X
https://ibb.co/B5bJcMK2
https://ibb.co/dsRCVw4c
https://ibb.co/kdNsqkm
https://ibb.co/d4JT5sc7
https://ibb.co/PZRqDQs3
https://ibb.co/twtb33yb
https://ibb.co/HLqcjt4n
https://ibb.co/ycMv6S7S
https://ibb.co/ycNVKsJ5
https://ibb.co/hF6MRbqJ
https://ibb.co/HfsdMN9F
https://ibb.co/zT8RCmYb
https://ibb.co/JwnvR4bF
https://ibb.co/SwVPk89y
https://ibb.co/gF6h9Q3t
https://ibb.co/CKsB5qcc
https://ibb.co/JwVFWb0X
https://ibb.co/3yqdJ0Zs
https://ibb.co/W4qQL1qf
https://ibb.co/YTdtwcmw
https://ibb.co/3YSvRsDt
https://ibb.co/pvFzn6JL
https://ibb.co/jkGfkByX
https://ibb.co/DZJtSsW
https://ibb.co/0RyT9r52
https://ibb.co/d4NRRChn
https://ibb.co/HLFCt968
https://ibb.co/k2YvRJGm
https://ibb.co/cS1HFqmC
https://ibb.co/RTghzhtC
https://ibb.co/cSjWKVHG
https://ibb.co/b5v46XJd
https://ibb.co/4ZW7DB52
https://ibb.co/DD7HRzyX
https://ibb.co/j9Bc09L5
https://ibb.co/Xf42dSR0
https://ibb.co/7xVnsFgR
https://ibb.co/nNwFRBjz
https://ibb.co/Lh1HD1m7
https://ibb.co/4n2sWN3V
https://ibb.co/TsXFGP4
https://ibb.co/MQwnR9T
https://ibb.co/GQ1C8PkK
https://ibb.co/jvmktbw4
https://ibb.co/Rd8KgFg
https://ibb.co/6726749v
https://ibb.co/Gf8TnXKK
https://ibb.co/N2NLkjN8
https://ibb.co/XZksRwts
https://ibb.co/v4cmSt2K
https://ibb.co/kRfJSxS
https://ibb.co/WWc7nS7s
https://ibb.co/PzPmhKLb
https://ibb.co/d47sNY9q
https://ibb.co/Jjm5pTNz
https://ibb.co/kgqYRzXY
https://ibb.co/B5Hyv9fh
https://ibb.co/0yNXjh11
https://ibb.co/RG4W3nrj
https://ibb.co/tTCYHDdK
https://ibb.co/4gtqq3sx
https://ibb.co/xKSfvhw9
https://ibb.co/rfQjx9XD
https://ibb.co/C5v9kGzG
https://ibb.co/HpHVjwnr
https://ibb.co/xKCvyHzK
https://ibb.co/HL8rK4MN
https://ibb.co/C5QSRhgm
https://ibb.co/nsKn4yN6
https://ibb.co/67ZvhqYG
https://ibb.co/KzhYXky4
https://ibb.co/m52Bfxnj
https://ibb.co/60RrVPDR
https://ibb.co/35Ld9yG1
https://ibb.co/KcD663S5
https://ibb.co/yn22yC1r
https://ibb.co/8DvJ4ZDd
https://ibb.co/pjPYNNqP
https://ibb.co/G3QChHMm
https://ibb.co/c07m1M0
https://ibb.co/S7XVxvNB
https://ibb.co/fYjLsSG9
https://ibb.co/2YMGT29J
https://ibb.co/mF1K8Y2b
https://ibb.co/bf2P3Rk
https://ibb.co/LXNSsmNS
https://ibb.co/v4yBVc3x
https://ibb.co/7JKPBDSc
https://ibb.co/4wSKv05T
https://ibb.co/hJXz0Cc9
https://ibb.co/DfZN9qVf
https://ibb.co/nqnN2b9L
https://ibb.co/fzqB1TJD
https://ibb.co/gkD5fpF
https://ibb.co/rGjChVYD
https://ibb.co/SDHndBkQ
https://ibb.co/hRp1ZRQq
https://ibb.co/Xk5wt51C
https://ibb.co/bgMRDgJn
https://ibb.co/MD59SDdM
https://ibb.co/Q3Qw3dRb
https://ibb.co/ZpS9Xz16
https://ibb.co/3mDfVGtJ
https://ibb.co/7dDPsZcC
https://ibb.co/3yH5SrZh
https://ibb.co/xqRxZmB6
https://ibb.co/qLj0gm1Q
https://ibb.co/ZR09BByD
https://ibb.co/6R4TW7mV
https://ibb.co/HftZ4r4K
https://ibb.co/r24qhjNq
https://ibb.co/99yw0RwW
https://ibb.co/LhxwwC8L
https://ibb.co/XfFBr1H9
https://ibb.co/JFnK5CvN
https://ibb.co/8Dwz4qq7
https://ibb.co/ZRWRRj6C
https://ibb.co/LDct6HCK
https://ibb.co/vvhLB1F7
https://ibb.co/qLHj7G0L
https://ibb.co/qZ7BH2J
https://ibb.co/wZtH83bZ
https://ibb.co/DHC88Ln0
https://ibb.co/fGSyRwcc
https://ibb.co/n8znHtTB
https://ibb.co/rGPLMWBz
https://ibb.co/HLX3wdjK
https://ibb.co/PZzhVp8Z
https://ibb.co/p6JkPjKP
https://ibb.co/chhNHpT8
https://ibb.co/B29NGP6W
https://ibb.co/HTy4RznB
https://ibb.co/p5JXpX3
https://ibb.co/8gy777fL
https://ibb.co/Kz5ctLNp
https://ibb.co/yFXhJ8fr
https://ibb.co/Z1tk9MS1
https://ibb.co/Dg876mbM
https://ibb.co/7xbhpsRn
https://ibb.co/W4jtMngZ
https://ibb.co/jZ19Fd4J
https://ibb.co/wFFFwZgt
https://ibb.co/pvjQ5YTb
https://ibb.co/svRNW5mB
https://ibb.co/7JDZvztG
https://ibb.co/6Rkw54DM
https://ibb.co/v4vJ7Mts
https://ibb.co/2016VmXM
https://ibb.co/DPKrxCbh
https://ibb.co/KzBK6tjv
https://ibb.co/SXrQLkVw
https://ibb.co/k6w9Xd4K
https://ibb.co/s98CmYGB
https://ibb.co/FqLV4hG5
https://ibb.co/HTrW62GX
https://ibb.co/WWcSkBP5
https://ibb.co/x82Jj7P8
https://ibb.co/QFLJyH2T
https://ibb.co/WNxTCJq3
https://ibb.co/BHbx8KQr
https://ibb.co/BVDz1pgt
https://ibb.co/rG6YNWmj
https://ibb.co/RkrQpNwV
https://ibb.co/p6Stnj1F
https://ibb.co/P8YSmB2
https://ibb.co/5hdth8h0
https://ibb.co/dwwvpKJ0
https://ibb.co/qLrqzC27
https://ibb.co/Cdg3Pfm
https://ibb.co/v6Vy3g0c
https://ibb.co/tprYZG91
https://ibb.co/N2Jtzstx
https://ibb.co/8LRpJcz4
https://ibb.co/j9wZ38qv
https://ibb.co/MxG3mtMy
https://ibb.co/7NykqZ0w
https://ibb.co/JjPQPVpJ
https://ibb.co/Fk1h2cJF
https://ibb.co/ch7XK7BM
https://ibb.co/S4RVjNBS
https://ibb.co/spn5LdTm
https://ibb.co/Gf4w1hdW
https://ibb.co/pBpmmnnb
https://ibb.co/gMWrtRy7
https://ibb.co/7NW0s2L1
https://ibb.co/zT0ycXcJ
https://ibb.co/kgDWJMfb
https://ibb.co/v4SMXds8
https://ibb.co/1yCLy75
https://ibb.co/67ky2s2k
https://ibb.co/PzMVzdTL
https://ibb.co/DD6TwvRB
https://ibb.co/ycfWZ55X
https://ibb.co/LDwwY85f
https://ibb.co/4R1Ps7bb
https://ibb.co/XfpxJhxH
https://ibb.co/Hf7yc7fm
https://ibb.co/W4v4nK5Z
https://ibb.co/99153qvn
https://ibb.co/q3TcGD4y
https://ibb.co/XxfYTnmX
https://ibb.co/pr0vFrsM
https://ibb.co/Dq1D0b6
https://ibb.co/Df3DBFNM
https://ibb.co/vxhXWRD0
https://ibb.co/208gsHNv
https://ibb.co/RTY8zrwF
https://ibb.co/Y7JBDhXy
https://ibb.co/PZYfzQX7
https://ibb.co/WptkxnJ9
https://ibb.co/ZwW5Zzb
https://ibb.co/bMPRNwYd
https://ibb.co/TDdryjbm
https://ibb.co/S7m2V24P
https://ibb.co/Rkqh2gxL
https://ibb.co/bM7D0kpq
https://ibb.co/fYwfYLC1
https://ibb.co/ycnFFX7v
https://ibb.co/bRLXQgfp
https://ibb.co/FbyHYTKv
https://ibb.co/JWsVphF0
https://ibb.co/CKj3ZM4L
https://ibb.co/QFGK63hL
https://ibb.co/jPWTP8qk
https://ibb.co/HDQMt8df
https://ibb.co/rKvZ682b
https://ibb.co/nMFsdRcW
https://ibb.co/21cJtfRX
https://ibb.co/vvwz5gh3
https://ibb.co/Fjnrkvm
https://ibb.co/35KbkFd5
https://ibb.co/Q5Z8c3y
https://ibb.co/gbyP2Qn1
https://ibb.co/B21nTRnT
https://ibb.co/vvY4Jv05
https://ibb.co/Jj47jxz1
https://ibb.co/cckgg5Jh
https://ibb.co/6R3zb4Qm
https://ibb.co/1GVRLzvQ
https://ibb.co/r2prQ8pw
https://ibb.co/7xs0SJCT
https://ibb.co/xbjxrL9
https://ibb.co/0RKyc5rH
https://ibb.co/fdvpQSVF
https://ibb.co/j9fjwZ7T
https://ibb.co/7NYFrmGt
https://ibb.co/BHxC5NvY
https://ibb.co/v62Zd6JD
https://ibb.co/PLRrRmk
https://ibb.co/HfLYSSBF
https://ibb.co/mFhjRj20
https://ibb.co/yc5zmTxr
https://ibb.co/1tFqQ83m
https://ibb.co/mVBNsTd9
https://ibb.co/GQw999yT
https://ibb.co/2GY8FTT
https://ibb.co/qMj0bYk0
https://ibb.co/7hzk2QJ
https://ibb.co/7xTRsfvx
https://ibb.co/fY0Zk7L8
https://ibb.co/T5pY8HH
https://ibb.co/8L2hbr6f
https://ibb.co/3mrCFvKw
https://ibb.co/rKSDm1WH
https://ibb.co/60R9p5LH
https://ibb.co/NgmvzcLp
https://ibb.co/7d9xqGsx
https://ibb.co/svFwKJHq
https://ibb.co/0pXGgV4g
https://ibb.co/Xkj8xFvf
https://ibb.co/cS2gN0gz
https://ibb.co/5XXcyNPZ
https://ibb.co/v6zJzzs7
https://ibb.co/ymKtM2hr
https://ibb.co/ccNDcx4y
https://ibb.co/JRdYzf2X
https://ibb.co/xSd1zmRT
https://ibb.co/JRfTT15c
https://ibb.co/zhYB4Mgv
https://ibb.co/ZRx67KVj
https://ibb.co/n8jptMnm
https://ibb.co/rfQGJmht
https://ibb.co/7xCK6Zyh
https://ibb.co/5gdtDsHY
https://ibb.co/bMyFKyR5
https://ibb.co/tpq6mvcf
https://ibb.co/WvDMPtNS
https://ibb.co/PzbsWbWy
https://ibb.co/4RWkbYH9
https://ibb.co/v4gdxHDX
https://ibb.co/JWTFLxTX
https://ibb.co/5htCsGXP
https://ibb.co/ZznWy76K
https://ibb.co/gLdc8yw3
https://ibb.co/gMtYtwr6
https://ibb.co/B2Jrx5KS
https://ibb.co/NnGtdRHj
https://ibb.co/SD4t2t0Q
https://ibb.co/bRzgjXWR
https://ibb.co/9mDrkd19
https://ibb.co/tpF0mB2n
https://ibb.co/3Y78yrCf
https://ibb.co/VcvfH21m
https://ibb.co/N6RGcW9M
https://ibb.co/Nn7cTPmm
https://ibb.co/PG7cm2S2
https://ibb.co/Q3cPr5ts
https://ibb.co/WWG3W5Wq
https://ibb.co/RTQvhZRH
https://ibb.co/FkR8DS2M
https://ibb.co/hxkw9CYP
https://ibb.co/391JGrYy
https://ibb.co/MDTyKGMK
https://ibb.co/jPBy60g9
https://ibb.co/jPgW0Dbh
https://ibb.co/jZVTwbWV
https://ibb.co/GQn754Hw
https://ibb.co/Y4k6Dx46
https://ibb.co/21yMbRp2
https://ibb.co/XZCkPYf4
https://ibb.co/5grVhjLM
https://ibb.co/k2DQ73Bt
https://ibb.co/g0gxR9p
https://ibb.co/Kjq98jrx
https://ibb.co/3y0KSHj4
https://ibb.co/Nd5jhQPK
https://ibb.co/XZ0mLPwS
https://ibb.co/xSs7vBvY
https://ibb.co/jkQJC5xd
https://ibb.co/Y4dF7gNX
https://ibb.co/G45g2kvq
https://ibb.co/KpzDF0p0
https://ibb.co/xKmcfqL3
https://ibb.co/DfGJzFcF
https://ibb.co/zVhSk7Lb
https://ibb.co/YTpjNydb
https://ibb.co/v4qgkCpg
https://ibb.co/CK1npYym
https://ibb.co/Jwcwy9Gz
https://ibb.co/0yTCq926
https://ibb.co/5x9D31tt
https://ibb.co/C3CTyCQk
https://ibb.co/prNgg6qG
https://ibb.co/yF50twWG
https://ibb.co/5hxrZQPy
https://ibb.co/wt3wQFj
https://ibb.co/sdkHWg5K
https://ibb.co/5X1s1h7D
https://ibb.co/KpzDF0p0
https://ibb.co/bgTdQW1g
https://ibb.co/tTVrh8LC
https://ibb.co/Xk4VFhF6
https://ibb.co/Fb5LKtyB
https://ibb.co/4n8GxpQk
https://ibb.co/h1HDbmkW
https://ibb.co/jvDM0x4w
https://ibb.co/zVMKmCtx
https://ibb.co/mVDmkQ9v
https://ibb.co/TMQr6Hhq
https://ibb.co/DD0Dn7K1
https://ibb.co/szxQx00
https://ibb.co/YT7Bknm5
https://ibb.co/jPz3DjX5
https://ibb.co/Lh9pkQZv
https://ibb.co/Df4Y75NG
https://ibb.co/5gqzzygS
https://ibb.co/vxYzr99P
https://ibb.co/Qvr2yyD8
https://ibb.co/cKxHHkPZ
https://ibb.co/twBysQ4d
https://ibb.co/s94jvY7T
https://ibb.co/h1HDbmkW
https://ibb.co/v4T6tHzx
https://ibb.co/pBNhPgwy
https://ibb.co/JW1qFpkN
https://ibb.co/rGf7wBDm
https://ibb.co/8gpgSZqV
https://ibb.co/6SQ64my
https://ibb.co/wNfdm19K
https://ibb.co/n4QVZqk
https://ibb.co/Kz97bvMn
https://ibb.co/b5Y2jDwm
https://ibb.co/60cs0HRT
https://ibb.co/xKm3nZTN
https://ibb.co/JVFk9sk
https://ibb.co/N2thDnNs
https://ibb.co/Fq8GPX6W
https://ibb.co/xSKgfgdF
https://ibb.co/FktwMzCL
https://ibb.co/XZncZcVk
https://ibb.co/gZ21CXxn
https://ibb.co/TCgBtgr
https://ibb.co/YTtgSxhy
https://ibb.co/3Y1FRpqB
https://ibb.co/PvY6Xjzk
https://ibb.co/jv4TgXzx
https://ibb.co/YBVy9tXb
https://ibb.co/R4JWqtK2
https://ibb.co/Dfmr5Xpw
https://ibb.co/WWMfPBdp
https://ibb.co/bg473MLZ
https://ibb.co/0ygYY88L
https://ibb.co/Mdj5L7c
https://ibb.co/1GS7ZzJd
https://ibb.co/qFgHctZL
https://ibb.co/xk64Pwd
https://ibb.co/7N8HsQGD
https://ibb.co/HT2KR0Pd
https://ibb.co/wrKZqg8d
https://ibb.co/RT2Nb7PD
https://ibb.co/q3p1dJXw
https://ibb.co/mCp8tzLZ
https://ibb.co/zTPkxWsT
https://ibb.co/hF7Fk7bj
https://ibb.co/BVzhj0RS
https://ibb.co/kVsVZzRB
https://ibb.co/RTB61rWK
https://ibb.co/r23N4j4S
https://ibb.co/q3JMBhmR
https://ibb.co/ym2DJhMG
https://ibb.co/QFCcsxh0
https://ibb.co/yn4FRhRw
https://ibb.co/FkyFPt68
https://ibb.co/bMVCH8Rb
https://ibb.co/39Kfn9FG
https://ibb.co/Qv3NYdFm
https://ibb.co/jPpwq2kV
https://ibb.co/MD1SS6qf
https://ibb.co/KpyVRj47
https://ibb.co/PvkcM9sG
https://ibb.co/FLcVwNS4
https://ibb.co/xKThSJVT
https://ibb.co/svpB2Ywg
https://ibb.co/60g4bfqs
https://ibb.co/spv6NN1y
https://ibb.co/Gv9n7F74
https://ibb.co/HprnjKp7
https://ibb.co/zTfNf2yj
https://ibb.co/Z4fx0Bt
https://ibb.co/VcJ6Bd49
https://ibb.co/TBq6NwYG
https://ibb.co/TBcnH14Y
https://ibb.co/N62JmYLL
https://ibb.co/v6DkCYV7
https://ibb.co/9mTMZpMt
https://ibb.co/bf4ztbV
https://ibb.co/5gxNSm43
https://ibb.co/QFQK11Jq
https://ibb.co/p6LpQ116
https://ibb.co/gM88Z3cK
https://ibb.co/qMx4PWCQ
https://ibb.co/wZX593nm
https://ibb.co/tTQBVBSy
https://ibb.co/zhBnRMNX
https://ibb.co/wNtvZbbX
https://ibb.co/cKHSQHKm
https://ibb.co/dsd1G9Mv
https://ibb.co/Lh2LDgvX
https://ibb.co/cKgLx8xp
https://ibb.co/0yh25gHT
https://ibb.co/whM7t4Gg
https://ibb.co/7dcGW2Nm
https://ibb.co/bM4201pw
https://ibb.co/C30TBF20
https://ibb.co/TDTW7zSp
https://ibb.co/5XR1KGj4
https://ibb.co/s9MGV4n2
https://ibb.co/b5Pyk5m2
https://ibb.co/Wvd9CCN2
https://ibb.co/B2ppkq6F
https://ibb.co/B5cCqVyk
https://ibb.co/tTqkHPWB
https://ibb.co/Kcd5bfBf
https://ibb.co/S41SVvqy
https://ibb.co/7NnPh42R
https://ibb.co/5gZWf2Yg
https://ibb.co/S7BFqF9r
https://ibb.co/B5WTBysb
https://ibb.co/cSSWwFnN
https://ibb.co/Z6MNtYWS
https://ibb.co/mVmytHhy
https://ibb.co/TBnvwxWd
https://ibb.co/gFQ5GmHG
https://ibb.co/zVgZdBNf
https://ibb.co/B29GsDPh
https://ibb.co/9msZ4bpj
https://ibb.co/1GBwXzn1
https://ibb.co/CsDspGHL
https://ibb.co/NgkhDBwB
https://ibb.co/ks6SHnBd
https://ibb.co/FLzPzXKS
https://ibb.co/23cv83VW
https://ibb.co/wNczxzhs
https://ibb.co/HDXswfHs
https://ibb.co/DN3syPZ
https://ibb.co/XZYQG3Db
https://ibb.co/gbKPZ9VX
https://ibb.co/gMX0KdBX
https://ibb.co/GvBwM9gh
https://ibb.co/JwzhTmn7
https://ibb.co/XxpLJtFb
https://ibb.co/Z6CQdLf7
https://ibb.co/wNNPcXM8
https://ibb.co/Vc117jfL
https://ibb.co/PvPpxFx1
https://ibb.co/1Y3vFLQJ
https://ibb.co/nqHkVH4Z
https://ibb.co/VcJTDVCT
https://ibb.co/1JftWV9R
https://ibb.co/bjmxX3BL
https://ibb.co/NdGrGDLF
https://ibb.co/JWFwfWRw
https://ibb.co/dwGNkwwc
https://ibb.co/LwpGnkY
https://ibb.co/JwRwxQqW
https://ibb.co/rKvNGfcT
https://ibb.co/PZ2FJb4B
https://ibb.co/TMgcPT8v
https://ibb.co/ymKnHbsp
https://ibb.co/PzfS7vP7
https://ibb.co/Lz8W1C3K
https://ibb.co/5XNdRXWX
https://ibb.co/Rk9MB08T
https://ibb.co/Y7xWsG4B
https://ibb.co/hJW0NrGR
https://ibb.co/8nNC8nDM
https://ibb.co/zhSZyghJ
https://ibb.co/TDvBKz4b
https://ibb.co/S4TZXB9m
https://ibb.co/LXfvX21S
https://ibb.co/pBR6TDMs
https://ibb.co/8DdvDnQ4
https://ibb.co/Mk1mmR78
https://ibb.co/35wyNhS2
https://ibb.co/LDkvBRKt
https://ibb.co/vvk1rxPB
https://ibb.co/nN3vb5vX
https://ibb.co/DgkLJSfT
https://ibb.co/RGv9TgLn
https://ibb.co/kgqKDnd3
https://ibb.co/s9hJ9kZR
https://ibb.co/YBym0Dmn
https://ibb.co/DD9RwfqP
https://ibb.co/zWjVN5ht
https://ibb.co/x8msFgNv
https://ibb.co/ns1yJ9zy
https://ibb.co/B2w39nQG
https://ibb.co/JwD6pzLS
https://ibb.co/QjmdvLN2
https://ibb.co/RTkV9nZ7
https://ibb.co/0RSsCJVj
https://ibb.co/SCBtGKy
https://ibb.co/N6M8N4nZ
https://ibb.co/0yxBHfcQ
https://ibb.co/fY9FStQd
https://ibb.co/LzKCYF0w
https://ibb.co/fzYTfnQR
https://ibb.co/KprdsqRy
https://ibb.co/4ZbV0GyJ
https://ibb.co/FcW8tXB
https://ibb.co/Y7NLFf1H
https://ibb.co/Hf291Pmp
https://ibb.co/0yxhfP61
https://ibb.co/8gX2N9MP
https://ibb.co/FLjmSq8F
https://ibb.co/TB5b6My7
https://ibb.co/k6ys1Wg9
https://ibb.co/jZZMmzFq
https://ibb.co/ccbDPNhr
https://ibb.co/LXTH5p9w
https://ibb.co/QFF6g72L
https://ibb.co/DDHG5TCj
https://ibb.co/4nDXNkpt
https://ibb.co/B2FQbJXk
https://ibb.co/L32JxDF
https://ibb.co/7N48td4j
https://ibb.co/fV2jBv8N
https://ibb.co/NgYtp5vv
https://ibb.co/PGTgDNdy
https://ibb.co/6GHHFs7
https://ibb.co/NdNJJtff
https://ibb.co/vvQ68C6g
https://ibb.co/Z6YPsbyN
https://ibb.co/zhwHwCgy
https://ibb.co/chy6tnjx
https://ibb.co/mVppZWbS
https://ibb.co/v6XTjnVc
https://ibb.co/cXVdRxg1
https://ibb.co/v6XRnKbF
https://ibb.co/DfTLk7Ws
https://ibb.co/yFfnSL4W
https://ibb.co/7xpP1Tdf
https://ibb.co/1YKxXVCT
https://ibb.co/VcrYBZyf
https://ibb.co/B5mR37cH
https://ibb.co/4wGgHjxk
https://ibb.co/PsrKDhwc
https://ibb.co/BHV0wyB6
https://ibb.co/39dMQB28
https://ibb.co/WpsVKN0Z
https://ibb.co/zhYGkqjL
https://ibb.co/YB6QMBvr
https://ibb.co/YVQS85y
https://ibb.co/qtyGRS2
https://ibb.co/kVyGPHtr
https://ibb.co/fYFtfZsZ
https://ibb.co/yLqygt6
https://ibb.co/TBHXrt6Y
https://ibb.co/x86rSHc4
https://ibb.co/1GL8Fxgx
https://ibb.co/zHmTTpKc
https://ibb.co/GQTPhfF6
https://ibb.co/0yVt4FPF
https://ibb.co/cKjPWJcw
https://ibb.co/39By0jBR
https://ibb.co/mFFP00MC
https://ibb.co/23zS7wct
https://ibb.co/BVp2Z6zp
https://ibb.co/p63MDnNN
https://ibb.co/gb38xCvn
https://ibb.co/yx5KPcb
https://ibb.co/8gNnF81B
https://ibb.co/gM3Mf66Z
https://ibb.co/cBsrJh9
https://ibb.co/Rkx9bTkz
https://ibb.co/1fxrrHZ3
https://ibb.co/y24dXcm
https://ibb.co/SZdrNN5
https://ibb.co/s9C4Dyfv
https://ibb.co/GvQR9gD0
https://ibb.co/VYJwSzbN
https://ibb.co/tMkNL49Z
https://ibb.co/LzNJBWjd
https://ibb.co/KdN3Dvs
https://ibb.co/sJdFQm8Z
https://ibb.co/KjMxSJJt
https://ibb.co/tp3Qfyxq
https://ibb.co/Sw3TrGkZ
https://ibb.co/N65Ddv4z
https://ibb.co/273b7H8n
https://ibb.co/LdGD030B
https://ibb.co/d0tRf7QZ
https://ibb.co/8DRjk0m4
https://ibb.co/B5K5zfs9
https://ibb.co/Vc0VQ7cr
https://ibb.co/KjYyWsG7
https://ibb.co/L2RCG5Q
https://ibb.co/VpMd55ty
https://ibb.co/fdM2s0Jy
https://ibb.co/fzyd3fbC
https://ibb.co/ccG1H8J8
https://ibb.co/67vtQNdm
https://ibb.co/Fbq1cGxn
https://ibb.co/prypr50S
https://ibb.co/KxMKrGT9
https://ibb.co/23PyQmF0
https://ibb.co/h5Ygxvb
https://ibb.co/5xMyr1QR
https://ibb.co/zHG25BC2
https://ibb.co/w5hwFVk
https://ibb.co/TxdDsbmx
https://ibb.co/J8qc4Qz
https://ibb.co/pjpHMXdd
https://ibb.co/XfYLCbjV
https://ibb.co/cKKXMp1c
https://ibb.co/n8w3V9n4
https://ibb.co/p6CZZYPg
https://ibb.co/9khKgy78
https://ibb.co/1tWjRHdx
https://ibb.co/tPvfJnNH
https://ibb.co/HfXNRN4B
https://ibb.co/fzZqypMF
https://ibb.co/3510h9p8
https://ibb.co/FkdRN4jn
https://ibb.co/TxzR7zrR
https://ibb.co/BH6pLJsK
https://ibb.co/k68v0hnT
https://ibb.co/23wVfYMt
https://ibb.co/0pr9Gyjw
https://ibb.co/8LBgjKxP
https://ibb.co/MyqY6M61
https://ibb.co/sp0fZS69
https://ibb.co/21mQF2Rc
https://ibb.co/fdhhFrmP
https://ibb.co/ZzyTWbPP
https://ibb.co/ZRcz421Y
https://ibb.co/1f3x6LWj
https://ibb.co/GQvPd9HN
https://ibb.co/sJD990ZM
https://ibb.co/xTLfWYF
https://ibb.co/ycxg3FKN
https://ibb.co/DHyM3YwL
https://ibb.co/XrMg95PF
https://ibb.co/Ngc0RKkV
https://ibb.co/5hvDxZZR
https://ibb.co/dJ0SX58W
https://ibb.co/Mx91T5dV
https://ibb.co/Kxhx5q9N
https://ibb.co/XxZFtFm1
https://ibb.co/XrjzsXhB
https://ibb.co/BHzXzkgC
https://ibb.co/B5cRwDtf
https://ibb.co/RkCyMxkf
https://ibb.co/x8HfdB6J
https://ibb.co/bMVSM1LG
https://ibb.co/ZRpZmWxB
https://ibb.co/FRQhvCz
https://ibb.co/yFSWt5mm
https://ibb.co/5xMS36ZG
https://ibb.co/NnFTs098
https://ibb.co/FL2TrzZw
https://ibb.co/whqcj1Wh
https://ibb.co/DfdCGGsK
https://ibb.co/9mj4vfBw
https://ibb.co/TxLc4czv
https://ibb.co/MDLzJqq4
https://ibb.co/v43QNkpV
https://ibb.co/LdcSC7JD
https://ibb.co/W4Lv72P8
https://ibb.co/TM2WCqxY
https://ibb.co/gZy4p8vc
https://ibb.co/Gvzyh81Z
https://ibb.co/Lm2fDQm
https://ibb.co/Vcp4vYdb
https://ibb.co/5hnG44MQ
https://ibb.co/8nbRzvtQ
https://ibb.co/RGjfS2p9
https://ibb.co/YBscfbSX
https://ibb.co/8LvwhJYt
https://ibb.co/gFyPGByp
https://ibb.co/dJ0SX58W
https://ibb.co/BHkFFgZk
https://ibb.co/fz3pWV82
https://ibb.co/jPc9dmFC
https://ibb.co/FkFR8Gtx
https://ibb.co/0jcBH2M2
https://ibb.co/hJpDXP88
https://ibb.co/1wBt5PF
https://ibb.co/wZwwyLwS
https://ibb.co/8LnF204C
https://ibb.co/rGtqPxkM
https://ibb.co/CKr2h0Cw
https://ibb.co/5XhRSdhm
https://ibb.co/7ttx15Hs
https://ibb.co/k6Qx7Gd4
https://ibb.co/LXh5rgBv
https://ibb.co/bgLGZtbw
https://ibb.co/FLwKTpS8
https://ibb.co/Y7QLVT0D
https://ibb.co/tTHQVCLV
https://ibb.co/35wG9QhN
https://ibb.co/0V1fWy1M
https://ibb.co/XZWrSGRn
https://ibb.co/ynT0hHgq
https://ibb.co/kV4JTCW2
https://ibb.co/wFqYckGh
https://ibb.co/YBxgxZHB
https://ibb.co/wrxCcCPP
https://ibb.co/jPHdMzdx
https://ibb.co/3Yzjt34N
https://ibb.co/G4G3q5Np
https://ibb.co/fdpxBH4d
https://ibb.co/SX9pstSJ
https://ibb.co/dsMZK4Zq
https://ibb.co/JjZJpDNj
https://ibb.co/tMqwprtV
https://ibb.co/TBy7PYYf
https://ibb.co/yFc4nt5R
https://ibb.co/wt3wQFj
https://ibb.co/GfT1hWyF
https://ibb.co/qMqWgQBR
https://ibb.co/xSLvz0nh
https://ibb.co/v4M6k80k
https://ibb.co/Y7NxFzj8
https://ibb.co/bMY9m3Yc
https://ibb.co/jvwhFKyT
https://ibb.co/d4TZ5NGz
https://ibb.co/C3LCx846